charon_lib/options.rs
1//! The options that control charon behavior.
2use annotate_snippets::Level;
3use clap::ValueEnum;
4use indoc::indoc;
5use itertools::Itertools;
6use macros::EnumAsGetters;
7use serde::{Deserialize, Serialize};
8use std::path::PathBuf;
9
10use crate::{
11 ast::*,
12 errors::{ErrorCtx, display_unspanned_error},
13 name_matcher::NamePattern,
14 raise_error, register_error,
15};
16
17/// The name of the environment variable we use to save the serialized Cli options
18/// when calling charon-driver from cargo-charon.
19pub const CHARON_ARGS: &str = "CHARON_ARGS";
20
21// This structure is used to store the command-line instructions.
22// We automatically derive a command-line parser based on this structure.
23// Note that the doc comments are used to generate the help message when using
24// `--help`.
25//
26// Note that because we need to transmit the options to the charon driver,
27// we store them in a file before calling this driver (hence the `Serialize`,
28// `Deserialize` options).
29#[derive(Debug, Default, Clone, clap::Args, PartialEq, Eq, Serialize, Deserialize)]
30#[clap(name = "Charon")]
31#[charon::rename("cli_options")]
32pub struct CliOpts {
33 /// Extract the unstructured LLBC (i.e., don't reconstruct the control-flow)
34 #[clap(long)]
35 #[serde(default)]
36 pub ullbc: bool,
37 /// Whether to precisely translate drops and drop-related code. For this, we add explicit
38 /// `Destruct` bounds to all generic parameters, set the MIR level to at least `elaborated`,
39 /// and attempt to retrieve drop glue for all types.
40 ///
41 /// This option is known to cause panics inside rustc, because their drop handling is not
42 /// design to work on polymorphic types. To silence the warning, pass appropriate `--opaque
43 /// '{impl core::marker::Destruct for some::Type}'` options.
44 ///
45 /// Without this option, drops may be "conditional" and we may lack information about what code
46 /// is run on drop in a given polymorphic function body.
47 #[clap(long)]
48 #[serde(default)]
49 pub precise_drops: bool,
50 /// If activated, this skips borrow-checking of the crate.
51 #[clap(long)]
52 #[serde(default)]
53 pub skip_borrowck: bool,
54 /// The MIR stage to extract. This is only relevant for the current crate; for dpendencies only
55 /// MIR optimized is available.
56 #[arg(long)]
57 pub mir: Option<MirLevel>,
58 /// Extra flags to pass to rustc.
59 #[clap(long = "rustc-arg")]
60 #[serde(default)]
61 pub rustc_args: Vec<String>,
62
63 /// Monomorphize the items encountered when possible. Generic items found in the crate are
64 /// skipped. To only translate a particular call graph, use `--start-from`. Note: this doesn't
65 /// currently support `dyn Trait`.
66 #[clap(long, visible_alias = "mono")]
67 #[serde(default)]
68 pub monomorphize: bool,
69 /// Partially monomorphize items to make it so that no item is ever monomorphized with a
70 /// mutable reference (or type containing one); said differently, so that the presence of
71 /// mutable references in a type is independent of its generics. This is used by Aeneas.
72 #[clap(
73 long,
74 value_name("INCLUDE_TYPES"),
75 num_args(0..=1),
76 require_equals(true),
77 default_missing_value("all"),
78 )]
79 #[serde(default)]
80 pub monomorphize_mut: Option<MonomorphizeMut>,
81
82 /// A list of item paths to use as starting points for the translation. We will translate these
83 /// items and any items they refer to, according to the opacity rules. When absent, we start
84 /// from the path `crate` (which translates the whole crate).
85 #[clap(long, value_delimiter = ',')]
86 #[serde(default)]
87 pub start_from: Vec<String>,
88 /// Same as --start-from, but won't raise an error if a pattern doesn't match any item. This is useful
89 /// when the patterns are generated by a build script and may be out of sync with the code.
90 #[clap(long, value_delimiter = ',')]
91 #[serde(default)]
92 pub start_from_if_exists: Vec<String>,
93 /// Use all the items annotated with the given attribute as starting points for translation
94 /// (except modules).
95 /// If an attribute name is not specified, `verify::start_from` is used.
96 #[clap(
97 long,
98 value_name("ATTRIBUTE"),
99 num_args(0..=1),
100 require_equals(true),
101 default_missing_value("verify::start_from"),
102 )]
103 #[serde(default)]
104 pub start_from_attribute: Option<String>,
105 /// Use all the `pub` items as starting points for translation (except modules).
106 #[clap(long)]
107 #[serde(default)]
108 pub start_from_pub: bool,
109
110 /// Whitelist of items to translate. These use the name-matcher syntax.
111 #[clap(
112 long,
113 help = indoc!("
114 Whitelist of items to translate. These use the name-matcher syntax (note: this differs
115 a bit from the ocaml NameMatcher).
116
117 Note: This is very rough at the moment. E.g. this parses `u64` as a path instead of the
118 built-in type. It is also not possible to filter a trait impl (this will only filter
119 its methods). Please report bugs or missing features.
120
121 Examples:
122 - `crate::module1::module2::item`: refers to this item and all its subitems (e.g.
123 submodules or trait methods);
124 - `crate::module1::module2::item::_`: refers only to the subitems of this item;
125 - `core::convert::{impl core::convert::Into<_> for _}`: retrieve the body of this
126 very useful impl;
127
128 When multiple patterns in the `--include` and `--opaque` options match the same item,
129 the most precise pattern wins. E.g.: `charon --opaque crate::module --include
130 crate::module::_` makes the `module` opaque (we won't explore its contents), but the
131 items in it transparent (we will translate them if we encounter them.)
132 "))]
133 #[serde(default)]
134 #[charon::rename("included")]
135 pub include: Vec<String>,
136 /// Blacklist of items to keep opaque. Works just like `--include`, see the doc there.
137 #[clap(long)]
138 #[serde(default)]
139 pub opaque: Vec<String>,
140 /// Blacklist of items to not translate at all. Works just like `--include`, see the doc there.
141 #[clap(long)]
142 #[serde(default)]
143 pub exclude: Vec<String>,
144 /// Usually we skip the bodies of foreign methods and structs with private fields. When this
145 /// flag is on, we don't.
146 #[clap(long)]
147 #[serde(default)]
148 pub extract_opaque_bodies: bool,
149 /// Usually we skip the provided methods that aren't used. When this flag is on, we translate
150 /// them all.
151 #[clap(long)]
152 #[serde(default)]
153 pub translate_all_methods: bool,
154
155 /// Transform the associate types of traits to be type parameters instead. This takes a list
156 /// of name patterns of the traits to transform, using the same syntax as `--include`.
157 #[clap(long, alias = "remove-associated-types")]
158 #[serde(default)]
159 pub lift_associated_types: Vec<String>,
160 /// Whether to hide various marker traits such as `Sized`, `Sync`, `Send` and `Destruct`
161 /// anywhere they show up. This can considerably speed up translation.
162 #[clap(long)]
163 #[serde(default)]
164 pub hide_marker_traits: bool,
165 /// Remove trait clauses from type declarations. Must be combined with
166 /// `--remove-associated-types` for type declarations that use trait associated types in their
167 /// fields, otherwise this will result in errors.
168 #[clap(long)]
169 #[serde(default)]
170 pub remove_adt_clauses: bool,
171 /// Hide the `A` type parameter on standard library containers (`Box`, `Vec`, etc).
172 #[clap(long)]
173 #[serde(default)]
174 pub hide_allocator: bool,
175 /// Trait method declarations take a `Self: Trait` clause as parameter, so that they can be
176 /// reused by multiple trait impls. This however causes trait definitions to be mutually
177 /// recursive with their method declarations. This flag removes `Self` clauses that aren't used
178 /// to break this mutual recursion when possible.
179 #[clap(long)]
180 #[serde(default)]
181 pub remove_unused_self_clauses: bool,
182
183 /// Transform precise drops to the equivalent `drop_in_place(&raw mut p)` call.
184 #[clap(long)]
185 #[serde(default)]
186 pub desugar_drops: bool,
187 /// Transform array-to-slice unsizing, repeat expressions, and raw pointer construction into
188 /// builtin functions in ULLBC.
189 #[clap(long)]
190 #[serde(default)]
191 pub ops_to_function_calls: bool,
192 /// Transform array/slice indexing into builtin functions in ULLBC. Note that this may
193 /// introduce UB since it creates references that were not normally created, including when
194 /// indexing behind a raw pointer.
195 #[clap(long)]
196 #[serde(default)]
197 pub index_to_function_calls: bool,
198 /// Treat `Box<T>` as if it was a built-in type.
199 #[clap(long)]
200 #[serde(default)]
201 pub treat_box_as_builtin: bool,
202 /// Do not inline or evaluate constants.
203 #[clap(long)]
204 #[serde(default)]
205 pub raw_consts: bool,
206 /// Replace string literal constants with a constant u8 array that gets unsized,
207 /// expliciting the fact a string constant has a hidden reference.
208 #[clap(long)]
209 #[serde(default)]
210 pub unsized_strings: bool,
211 /// Replace "bound checks followed by UB-on-overflow operation" with the corresponding
212 /// panic-on-overflow operation. This loses unwinding information.
213 #[clap(long)]
214 #[serde(default)]
215 pub reconstruct_fallible_operations: bool,
216 /// Replace "if x { panic() }" with "assert(x)".
217 #[clap(long)]
218 #[serde(default)]
219 pub reconstruct_asserts: bool,
220 /// Use `DeBruijnVar::Free` for the variables bound in item signatures, instead of
221 /// `DeBruijnVar::Bound` everywhere. This simplifies the management of generics for projects
222 /// that don't intend to manipulate them too much.
223 #[clap(long)]
224 #[serde(default)]
225 pub unbind_item_vars: bool,
226
227 /// Pretty-print the ULLBC immediately after extraction from MIR.
228 #[clap(long)]
229 #[serde(default)]
230 pub print_original_ullbc: bool,
231 /// Pretty-print the ULLBC after applying the micro-passes (before serialization/control-flow reconstruction).
232 #[clap(long)]
233 #[serde(default)]
234 pub print_ullbc: bool,
235 /// Pretty-print the LLBC just after we built it (i.e., immediately after loop reconstruction).
236 #[clap(long)]
237 #[serde(default)]
238 pub print_built_llbc: bool,
239 /// Pretty-print the final LLBC (after all the cleaning micro-passes).
240 #[clap(long)]
241 #[serde(default)]
242 pub print_llbc: bool,
243
244 /// The destination directory. Files will be generated as `<dest_dir>/<crate_name>.{u}llbc`,
245 /// unless `dest_file` is set. `dest_dir` defaults to the current directory.
246 #[clap(long = "dest", value_parser)]
247 #[serde(default)]
248 pub dest_dir: Option<PathBuf>,
249 /// The destination file. By default `<dest_dir>/<crate_name>.llbc`. If this is set we ignore
250 /// `dest_dir`.
251 #[clap(long, value_parser)]
252 #[serde(default)]
253 pub dest_file: Option<PathBuf>,
254 /// Don't deduplicate values (types, trait refs) in the .(u)llbc file. This makes the file easier to inspect.
255 #[clap(long)]
256 #[serde(default)]
257 pub no_dedup_serialized_ast: bool,
258 /// Don't serialize the final (U)LLBC to a file.
259 #[clap(long)]
260 #[serde(default)]
261 pub no_serialize: bool,
262 /// Panic on the first error. This is useful for debugging.
263 #[clap(long)]
264 #[serde(default)]
265 pub abort_on_error: bool,
266 /// Consider any warnings to be errors.
267 #[clap(long)]
268 #[serde(default)]
269 pub error_on_warnings: bool,
270
271 /// Named builtin sets of options.
272 #[clap(long)]
273 #[arg(value_enum)]
274 pub preset: Option<Preset>,
275}
276
277/// The MIR stage to use. This is only relevant for the current crate: for dependencies, only mir
278/// optimized is available (or mir elaborated for consts).
279#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)]
280pub enum MirLevel {
281 /// The MIR just after MIR lowering.
282 Built,
283 /// The MIR after const promotion. This is the MIR used by the borrow-checker.
284 Promoted,
285 /// The MIR after drop elaboration. This is the first MIR to include all the runtime
286 /// information.
287 Elaborated,
288 /// The MIR after optimizations. Charon disables all the optimizations it can, so this is
289 /// sensibly the same MIR as the elaborated MIR.
290 Optimized,
291}
292
293/// Presets to make it easier to tweak options without breaking dependent projects. Eventually we
294/// should define semantically-meaningful presets instead of project-specific ones.
295#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)]
296#[non_exhaustive]
297pub enum Preset {
298 /// The default translation used before May 2025. After that, many passes were made optional
299 /// and disabled by default.
300 OldDefaults,
301 /// Emit the MIR as unmodified as possible. This is very imperfect for now, we should make more
302 /// passes optional.
303 RawMir,
304 Aeneas,
305 Eurydice,
306 Soteria,
307 Tests,
308}
309
310#[derive(
311 Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize,
312)]
313pub enum MonomorphizeMut {
314 /// Monomorphize any item instantiated with `&mut`.
315 #[default]
316 All,
317 /// Monomorphize all non-typedecl items instantiated with `&mut`.
318 ExceptTypes,
319}
320
321impl CliOpts {
322 pub fn apply_preset(&mut self) {
323 if let Some(preset) = self.preset {
324 match preset {
325 Preset::OldDefaults => {
326 self.treat_box_as_builtin = true;
327 self.hide_allocator = true;
328 self.ops_to_function_calls = true;
329 self.index_to_function_calls = true;
330 self.reconstruct_fallible_operations = true;
331 self.reconstruct_asserts = true;
332 self.unbind_item_vars = true;
333 }
334 Preset::RawMir => {
335 self.extract_opaque_bodies = true;
336 self.raw_consts = true;
337 self.ullbc = true;
338 }
339 Preset::Aeneas => {
340 self.lift_associated_types.push("*".to_owned());
341 self.treat_box_as_builtin = true;
342 self.ops_to_function_calls = true;
343 self.index_to_function_calls = true;
344 self.reconstruct_fallible_operations = true;
345 self.reconstruct_asserts = true;
346 self.hide_marker_traits = true;
347 self.hide_allocator = true;
348 self.remove_unused_self_clauses = true;
349 self.unbind_item_vars = true;
350 // Hide drop impls because they often involve nested borrows. which aeneas
351 // doesn't handle yet.
352 self.exclude.push("core::ops::drop::Drop".to_owned());
353 self.exclude
354 .push("{impl core::ops::drop::Drop for _}".to_owned());
355 }
356 Preset::Eurydice => {
357 self.hide_allocator = true;
358 self.treat_box_as_builtin = true;
359 self.ops_to_function_calls = true;
360 self.index_to_function_calls = true;
361 self.reconstruct_fallible_operations = true;
362 self.reconstruct_asserts = true;
363 self.lift_associated_types.push("*".to_owned());
364 self.unbind_item_vars = true;
365 // Eurydice doesn't support opaque vtables it seems?
366 self.include.push("core::marker::MetaSized".to_owned());
367 }
368 Preset::Soteria => {
369 self.extract_opaque_bodies = true;
370 self.monomorphize = true;
371 self.mir = Some(MirLevel::Elaborated);
372 self.ullbc = true;
373 }
374 Preset::Tests => {
375 self.no_dedup_serialized_ast = true; // Helps debug
376 self.treat_box_as_builtin = true;
377 self.hide_allocator = true;
378 self.reconstruct_fallible_operations = true;
379 self.reconstruct_asserts = true;
380 self.ops_to_function_calls = true;
381 self.index_to_function_calls = true;
382 self.rustc_args.push("--edition=2021".to_owned());
383 self.rustc_args
384 .push("-Zcrate-attr=feature(register_tool)".to_owned());
385 self.rustc_args
386 .push("-Zcrate-attr=register_tool(charon)".to_owned());
387 self.exclude.push("core::fmt::Formatter".to_owned());
388 }
389 }
390 }
391 }
392
393 /// Check that the options are meaningful
394 pub fn validate(&self) -> anyhow::Result<()> {
395 if self.dest_dir.is_some() {
396 display_unspanned_error(
397 Level::WARNING,
398 "`--dest` is deprecated, use `--dest-file` instead",
399 )
400 }
401
402 if self.remove_adt_clauses && self.lift_associated_types.is_empty() {
403 anyhow::bail!(
404 "`--remove-adt-clauses` should be used with `--remove-associated-types='*'` \
405 to avoid missing clause errors",
406 )
407 }
408 if matches!(self.monomorphize_mut, Some(MonomorphizeMut::ExceptTypes))
409 && !self.remove_adt_clauses
410 {
411 anyhow::bail!(
412 "`--monomorphize-mut=except-types` should be used with `--remove-adt-clauses` \
413 to avoid generics mismatches"
414 )
415 }
416 Ok(())
417 }
418}
419
420/// Predicates that determine wihch items to use as starting point for translation.
421#[derive(Debug, Clone, EnumAsGetters)]
422pub enum StartFrom {
423 /// Item identified by a pattern/path. If strict is true, then failing to
424 /// find an item matching the pattern is an error; otherwise, we just ignore this pattern.
425 Pattern { pattern: NamePattern, strict: bool },
426 /// Item annotated with the given attribute.
427 Attribute(String),
428 /// Item marked `pub`. Note that this does not take accessibility into account; a
429 /// non-reexported `pub` item will be included here.
430 Pub,
431}
432
433impl StartFrom {
434 pub fn matches(&self, ctx: &TranslatedCrate, item_meta: &ItemMeta) -> bool {
435 match self {
436 StartFrom::Pattern { pattern, .. } => pattern.matches(ctx, &item_meta.name),
437 StartFrom::Attribute(attr) => item_meta
438 .attr_info
439 .attributes
440 .iter()
441 .filter_map(|a| a.as_unknown())
442 .any(|raw_attr| raw_attr.path == *attr),
443 StartFrom::Pub => item_meta.attr_info.public,
444 }
445 }
446}
447
448/// The options that control translation and transformation.
449pub struct TranslateOptions {
450 /// Items from which to start translation.
451 pub start_from: Vec<StartFrom>,
452 /// The level at which to extract the MIR
453 pub mir_level: MirLevel,
454 /// Usually we skip the provided methods that aren't used. When this flag is on, we translate
455 /// them all.
456 pub translate_all_methods: bool,
457 /// If `Some(_)`, run the partial mutability monomorphization pass. The contained enum
458 /// indicates whether to partially monomorphize types.
459 pub monomorphize_mut: Option<MonomorphizeMut>,
460 /// Whether to hide various marker traits such as `Sized`, `Sync`, `Send` and `Destruct`
461 /// anywhere they show up.
462 pub hide_marker_traits: bool,
463 /// Remove trait clauses attached to type declarations.
464 pub remove_adt_clauses: bool,
465 /// Hide the `A` type parameter on standard library containers (`Box`, `Vec`, etc).
466 pub hide_allocator: bool,
467 /// Remove unused `Self: Trait` clauses on method declarations.
468 pub remove_unused_self_clauses: bool,
469 /// Monomorphize code using hax's instantiation mechanism.
470 pub monomorphize_with_hax: bool,
471 /// Transform array-to-slice unsizing, repeat expressions, and raw pointer construction into
472 /// builtin functions in ULLBC.
473 pub ops_to_function_calls: bool,
474 /// Transform array/slice indexing into builtin functions in ULLBC.
475 pub index_to_function_calls: bool,
476 /// Print the llbc just after control-flow reconstruction.
477 pub print_built_llbc: bool,
478 /// Treat `Box<T>` as if it was a built-in type.
479 pub treat_box_as_builtin: bool,
480 /// Don't inline or evaluate constants.
481 pub raw_consts: bool,
482 /// Replace string literal constants with a constant u8 array that gets unsized,
483 /// expliciting the fact a string constant has a hidden reference.
484 pub unsized_strings: bool,
485 /// Replace "bound checks followed by UB-on-overflow operation" with the corresponding
486 /// panic-on-overflow operation. This loses unwinding information.
487 pub reconstruct_fallible_operations: bool,
488 /// Replace "if x { panic() }" with "assert(x)".
489 pub reconstruct_asserts: bool,
490 // Use `DeBruijnVar::Free` for the variables bound in item signatures.
491 pub unbind_item_vars: bool,
492 /// List of patterns to assign a given opacity to. Same as the corresponding `TranslateOptions`
493 /// field.
494 pub item_opacities: Vec<(NamePattern, ItemOpacity)>,
495 /// List of traits for which we transform associated types to type parameters.
496 pub lift_associated_types: Vec<NamePattern>,
497 /// Transform Drop to Call drop_in_place
498 pub desugar_drops: bool,
499 /// Add `Destruct` bounds to all generic params.
500 pub add_destruct_bounds: bool,
501 /// Translate drop glue for poly types, knowing that this may cause ICEs.
502 pub translate_poly_drop_glue: bool,
503}
504
505impl TranslateOptions {
506 pub fn new(error_ctx: &mut ErrorCtx, options: &CliOpts) -> Self {
507 let mut parse_pattern = |s: &str| match NamePattern::parse(s) {
508 Ok(p) => Ok(p),
509 Err(e) => {
510 raise_error!(
511 error_ctx,
512 crate(&TranslatedCrate::default()),
513 Span::dummy(),
514 "failed to parse pattern `{s}` ({e})"
515 )
516 }
517 };
518
519 let mut mir_level = options.mir.unwrap_or(MirLevel::Promoted);
520 if options.precise_drops {
521 mir_level = std::cmp::max(mir_level, MirLevel::Elaborated);
522 }
523
524 let mut start_from = options
525 .start_from
526 .iter()
527 .filter_map(|path| parse_pattern(&path).ok())
528 .map(|p| StartFrom::Pattern {
529 pattern: p,
530 strict: true,
531 })
532 .collect_vec();
533 start_from.extend(
534 options
535 .start_from_if_exists
536 .iter()
537 .filter_map(|path| parse_pattern(&path).ok())
538 .map(|p| StartFrom::Pattern {
539 pattern: p,
540 strict: false,
541 }),
542 );
543 if let Some(attr) = options.start_from_attribute.clone() {
544 start_from.push(StartFrom::Attribute(attr));
545 }
546 if options.start_from_pub {
547 start_from.push(StartFrom::Pub);
548 }
549 if start_from.is_empty() {
550 start_from.push(StartFrom::Pattern {
551 pattern: parse_pattern("crate").unwrap(),
552 strict: true,
553 });
554 }
555
556 let item_opacities = {
557 use ItemOpacity::*;
558 let mut opacities = vec![];
559
560 // This is how to treat items that don't match any other pattern.
561 if options.extract_opaque_bodies {
562 opacities.push(("_".to_string(), Transparent));
563 } else {
564 opacities.push(("_".to_string(), Foreign));
565 }
566
567 // We always include the items from the crate.
568 opacities.push(("crate".to_owned(), Transparent));
569
570 for pat in options.include.iter() {
571 opacities.push((pat.to_string(), Transparent));
572 }
573 for pat in options.opaque.iter() {
574 opacities.push((pat.to_string(), Opaque));
575 }
576 for pat in options.exclude.iter() {
577 opacities.push((pat.to_string(), Invisible));
578 }
579
580 if options.hide_allocator {
581 opacities.push((format!("core::alloc::Allocator"), Invisible));
582 opacities.push((
583 format!("alloc::alloc::{{impl core::alloc::Allocator for _}}"),
584 Invisible,
585 ));
586 }
587
588 opacities
589 .into_iter()
590 .filter_map(|(s, opacity)| parse_pattern(&s).ok().map(|pat| (pat, opacity)))
591 .collect()
592 };
593
594 let lift_associated_types = options
595 .lift_associated_types
596 .iter()
597 .filter_map(|s| parse_pattern(&s).ok())
598 .collect();
599
600 TranslateOptions {
601 start_from,
602 mir_level,
603 monomorphize_mut: options.monomorphize_mut,
604 hide_marker_traits: options.hide_marker_traits,
605 remove_adt_clauses: options.remove_adt_clauses,
606 hide_allocator: options.hide_allocator,
607 remove_unused_self_clauses: options.remove_unused_self_clauses,
608 monomorphize_with_hax: options.monomorphize,
609 ops_to_function_calls: options.ops_to_function_calls,
610 index_to_function_calls: options.index_to_function_calls,
611 print_built_llbc: options.print_built_llbc,
612 item_opacities,
613 treat_box_as_builtin: options.treat_box_as_builtin,
614 raw_consts: options.raw_consts,
615 unsized_strings: options.unsized_strings,
616 reconstruct_fallible_operations: options.reconstruct_fallible_operations,
617 reconstruct_asserts: options.reconstruct_asserts,
618 lift_associated_types,
619 unbind_item_vars: options.unbind_item_vars,
620 translate_all_methods: options.translate_all_methods,
621 desugar_drops: options.desugar_drops,
622 add_destruct_bounds: options.precise_drops,
623 translate_poly_drop_glue: options.precise_drops,
624 }
625 }
626
627 /// Find the opacity requested for the given name. This does not take into account
628 /// `#[charon::opaque]` annotations, only cli parameters.
629 #[tracing::instrument(skip(self, krate), ret)]
630 pub fn opacity_for_name(&self, krate: &TranslatedCrate, name: &Name) -> ItemOpacity {
631 // Find the most precise pattern that matches this name. There is always one since
632 // the list contains the `_` pattern. If there are conflicting settings for this item, we
633 // err on the side of being more opaque.
634 let (_, opacity) = self
635 .item_opacities
636 .iter()
637 .filter(|(pat, _)| pat.matches(krate, name))
638 .max()
639 .unwrap();
640 *opacity
641 }
642}