• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(rustc::bad_opt_access)]
2 use crate::interface::parse_cfgspecs;
3 
4 use rustc_data_structures::fx::FxHashSet;
5 use rustc_data_structures::profiling::TimePassesFormat;
6 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
7 use rustc_session::config::rustc_optgroups;
8 use rustc_session::config::DebugInfo;
9 use rustc_session::config::Input;
10 use rustc_session::config::InstrumentXRay;
11 use rustc_session::config::LinkSelfContained;
12 use rustc_session::config::TraitSolver;
13 use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
14 use rustc_session::config::{
15     BranchProtection, Externs, OomStrategy, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
16     ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel,
17 };
18 use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
19 use rustc_session::config::{DumpMonoStatsFormat, MirSpanview};
20 use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip};
21 use rustc_session::config::{InstrumentCoverage, Passes};
22 use rustc_session::lint::Level;
23 use rustc_session::search_paths::SearchPath;
24 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
25 use rustc_session::{build_session, getopts, Session};
26 use rustc_session::{CompilerIO, EarlyErrorHandler};
27 use rustc_span::edition::{Edition, DEFAULT_EDITION};
28 use rustc_span::symbol::sym;
29 use rustc_span::FileName;
30 use rustc_span::SourceFileHashAlgorithm;
31 use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
32 use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
33 
34 use std::collections::{BTreeMap, BTreeSet};
35 use std::num::NonZeroUsize;
36 use std::path::{Path, PathBuf};
37 
38 type CfgSpecs = FxHashSet<(String, Option<String>)>;
39 
build_session_options_and_crate_config( handler: &mut EarlyErrorHandler, matches: getopts::Matches, ) -> (Options, CfgSpecs)40 fn build_session_options_and_crate_config(
41     handler: &mut EarlyErrorHandler,
42     matches: getopts::Matches,
43 ) -> (Options, CfgSpecs) {
44     let sessopts = build_session_options(handler, &matches);
45     let cfg = parse_cfgspecs(handler, matches.opt_strs("cfg"));
46     (sessopts, cfg)
47 }
48 
mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, CfgSpecs)49 fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, CfgSpecs) {
50     let registry = registry::Registry::new(&[]);
51     let (sessopts, cfg) = build_session_options_and_crate_config(handler, matches);
52     let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
53     let io = CompilerIO {
54         input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
55         output_dir: None,
56         output_file: None,
57         temps_dir,
58     };
59     let sess = build_session(
60         handler,
61         sessopts,
62         io,
63         None,
64         registry,
65         vec![],
66         Default::default(),
67         None,
68         None,
69         "",
70     );
71     (sess, cfg)
72 }
73 
new_public_extern_entry<S, I>(locations: I) -> ExternEntry where S: Into<String>, I: IntoIterator<Item = S>,74 fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
75 where
76     S: Into<String>,
77     I: IntoIterator<Item = S>,
78 {
79     let locations: BTreeSet<CanonicalizedPath> =
80         locations.into_iter().map(|s| CanonicalizedPath::new(Path::new(&s.into()))).collect();
81 
82     ExternEntry {
83         location: ExternLocation::ExactPaths(locations),
84         is_private_dep: false,
85         add_prelude: true,
86         nounused_dep: false,
87         force: false,
88     }
89 }
90 
optgroups() -> getopts::Options91 fn optgroups() -> getopts::Options {
92     let mut opts = getopts::Options::new();
93     for group in rustc_optgroups() {
94         (group.apply)(&mut opts);
95     }
96     return opts;
97 }
98 
mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V>99 fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> {
100     BTreeMap::from_iter(entries.into_iter())
101 }
102 
assert_same_clone(x: &Options)103 fn assert_same_clone(x: &Options) {
104     assert_eq!(x.dep_tracking_hash(true), x.clone().dep_tracking_hash(true));
105     assert_eq!(x.dep_tracking_hash(false), x.clone().dep_tracking_hash(false));
106 }
107 
assert_same_hash(x: &Options, y: &Options)108 fn assert_same_hash(x: &Options, y: &Options) {
109     assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
110     assert_eq!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
111     // Check clone
112     assert_same_clone(x);
113     assert_same_clone(y);
114 }
115 
assert_different_hash(x: &Options, y: &Options)116 fn assert_different_hash(x: &Options, y: &Options) {
117     assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
118     assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
119     // Check clone
120     assert_same_clone(x);
121     assert_same_clone(y);
122 }
123 
assert_non_crate_hash_different(x: &Options, y: &Options)124 fn assert_non_crate_hash_different(x: &Options, y: &Options) {
125     assert_eq!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
126     assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
127     // Check clone
128     assert_same_clone(x);
129     assert_same_clone(y);
130 }
131 
132 // When the user supplies --test we should implicitly supply --cfg test
133 #[test]
test_switch_implies_cfg_test()134 fn test_switch_implies_cfg_test() {
135     rustc_span::create_default_session_globals_then(|| {
136         let matches = optgroups().parse(&["--test".to_string()]).unwrap();
137         let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
138         let (sess, cfg) = mk_session(&mut handler, matches);
139         let cfg = build_configuration(&sess, to_crate_config(cfg));
140         assert!(cfg.contains(&(sym::test, None)));
141     });
142 }
143 
144 // When the user supplies --test and --cfg test, don't implicitly add another --cfg test
145 #[test]
test_switch_implies_cfg_test_unless_cfg_test()146 fn test_switch_implies_cfg_test_unless_cfg_test() {
147     rustc_span::create_default_session_globals_then(|| {
148         let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
149         let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
150         let (sess, cfg) = mk_session(&mut handler, matches);
151         let cfg = build_configuration(&sess, to_crate_config(cfg));
152         let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test);
153         assert!(test_items.next().is_some());
154         assert!(test_items.next().is_none());
155     });
156 }
157 
158 #[test]
test_can_print_warnings()159 fn test_can_print_warnings() {
160     rustc_span::create_default_session_globals_then(|| {
161         let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
162         let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
163         let (sess, _) = mk_session(&mut handler, matches);
164         assert!(!sess.diagnostic().can_emit_warnings());
165     });
166 
167     rustc_span::create_default_session_globals_then(|| {
168         let matches =
169             optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap();
170         let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
171         let (sess, _) = mk_session(&mut handler, matches);
172         assert!(sess.diagnostic().can_emit_warnings());
173     });
174 
175     rustc_span::create_default_session_globals_then(|| {
176         let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
177         let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
178         let (sess, _) = mk_session(&mut handler, matches);
179         assert!(sess.diagnostic().can_emit_warnings());
180     });
181 }
182 
183 #[test]
test_output_types_tracking_hash_different_paths()184 fn test_output_types_tracking_hash_different_paths() {
185     let mut v1 = Options::default();
186     let mut v2 = Options::default();
187     let mut v3 = Options::default();
188 
189     v1.output_types = OutputTypes::new(&[(
190         OutputType::Exe,
191         Some(OutFileName::Real(PathBuf::from("./some/thing"))),
192     )]);
193     v2.output_types = OutputTypes::new(&[(
194         OutputType::Exe,
195         Some(OutFileName::Real(PathBuf::from("/some/thing"))),
196     )]);
197     v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
198 
199     assert_non_crate_hash_different(&v1, &v2);
200     assert_non_crate_hash_different(&v1, &v3);
201     assert_non_crate_hash_different(&v2, &v3);
202 }
203 
204 #[test]
test_output_types_tracking_hash_different_construction_order()205 fn test_output_types_tracking_hash_different_construction_order() {
206     let mut v1 = Options::default();
207     let mut v2 = Options::default();
208 
209     v1.output_types = OutputTypes::new(&[
210         (OutputType::Exe, Some(OutFileName::Real(PathBuf::from("./some/thing")))),
211         (OutputType::Bitcode, Some(OutFileName::Real(PathBuf::from("./some/thing.bc")))),
212     ]);
213 
214     v2.output_types = OutputTypes::new(&[
215         (OutputType::Bitcode, Some(OutFileName::Real(PathBuf::from("./some/thing.bc")))),
216         (OutputType::Exe, Some(OutFileName::Real(PathBuf::from("./some/thing")))),
217     ]);
218 
219     assert_same_hash(&v1, &v2);
220 }
221 
222 #[test]
test_externs_tracking_hash_different_construction_order()223 fn test_externs_tracking_hash_different_construction_order() {
224     let mut v1 = Options::default();
225     let mut v2 = Options::default();
226     let mut v3 = Options::default();
227 
228     v1.externs = Externs::new(mk_map(vec![
229         (String::from("a"), new_public_extern_entry(vec!["b", "c"])),
230         (String::from("d"), new_public_extern_entry(vec!["e", "f"])),
231     ]));
232 
233     v2.externs = Externs::new(mk_map(vec![
234         (String::from("d"), new_public_extern_entry(vec!["e", "f"])),
235         (String::from("a"), new_public_extern_entry(vec!["b", "c"])),
236     ]));
237 
238     v3.externs = Externs::new(mk_map(vec![
239         (String::from("a"), new_public_extern_entry(vec!["b", "c"])),
240         (String::from("d"), new_public_extern_entry(vec!["f", "e"])),
241     ]));
242 
243     assert_same_hash(&v1, &v2);
244     assert_same_hash(&v1, &v3);
245     assert_same_hash(&v2, &v3);
246 }
247 
248 #[test]
test_lints_tracking_hash_different_values()249 fn test_lints_tracking_hash_different_values() {
250     let mut v1 = Options::default();
251     let mut v2 = Options::default();
252     let mut v3 = Options::default();
253 
254     v1.lint_opts = vec![
255         (String::from("a"), Level::Allow),
256         (String::from("b"), Level::Warn),
257         (String::from("c"), Level::Deny),
258         (String::from("d"), Level::Forbid),
259     ];
260 
261     v2.lint_opts = vec![
262         (String::from("a"), Level::Allow),
263         (String::from("b"), Level::Warn),
264         (String::from("X"), Level::Deny),
265         (String::from("d"), Level::Forbid),
266     ];
267 
268     v3.lint_opts = vec![
269         (String::from("a"), Level::Allow),
270         (String::from("b"), Level::Warn),
271         (String::from("c"), Level::Forbid),
272         (String::from("d"), Level::Deny),
273     ];
274 
275     assert_non_crate_hash_different(&v1, &v2);
276     assert_non_crate_hash_different(&v1, &v3);
277     assert_non_crate_hash_different(&v2, &v3);
278 }
279 
280 #[test]
test_lints_tracking_hash_different_construction_order()281 fn test_lints_tracking_hash_different_construction_order() {
282     let mut v1 = Options::default();
283     let mut v2 = Options::default();
284 
285     v1.lint_opts = vec![
286         (String::from("a"), Level::Allow),
287         (String::from("b"), Level::Warn),
288         (String::from("c"), Level::Deny),
289         (String::from("d"), Level::Forbid),
290     ];
291 
292     v2.lint_opts = vec![
293         (String::from("a"), Level::Allow),
294         (String::from("c"), Level::Deny),
295         (String::from("b"), Level::Warn),
296         (String::from("d"), Level::Forbid),
297     ];
298 
299     // The hash should be order-dependent
300     assert_non_crate_hash_different(&v1, &v2);
301 }
302 
303 #[test]
test_lint_cap_hash_different()304 fn test_lint_cap_hash_different() {
305     let mut v1 = Options::default();
306     let mut v2 = Options::default();
307     let v3 = Options::default();
308 
309     v1.lint_cap = Some(Level::Forbid);
310     v2.lint_cap = Some(Level::Allow);
311 
312     assert_non_crate_hash_different(&v1, &v2);
313     assert_non_crate_hash_different(&v1, &v3);
314     assert_non_crate_hash_different(&v2, &v3);
315 }
316 
317 #[test]
test_search_paths_tracking_hash_different_order()318 fn test_search_paths_tracking_hash_different_order() {
319     let mut v1 = Options::default();
320     let mut v2 = Options::default();
321     let mut v3 = Options::default();
322     let mut v4 = Options::default();
323 
324     let handler = EarlyErrorHandler::new(JSON);
325     const JSON: ErrorOutputType = ErrorOutputType::Json {
326         pretty: false,
327         json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
328     };
329 
330     // Reference
331     v1.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc"));
332     v1.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def"));
333     v1.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi"));
334     v1.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl"));
335     v1.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno"));
336 
337     v2.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc"));
338     v2.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi"));
339     v2.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def"));
340     v2.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl"));
341     v2.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno"));
342 
343     v3.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def"));
344     v3.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl"));
345     v3.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc"));
346     v3.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi"));
347     v3.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno"));
348 
349     v4.search_paths.push(SearchPath::from_cli_opt(&handler, "all=mno"));
350     v4.search_paths.push(SearchPath::from_cli_opt(&handler, "native=abc"));
351     v4.search_paths.push(SearchPath::from_cli_opt(&handler, "crate=def"));
352     v4.search_paths.push(SearchPath::from_cli_opt(&handler, "dependency=ghi"));
353     v4.search_paths.push(SearchPath::from_cli_opt(&handler, "framework=jkl"));
354 
355     assert_same_hash(&v1, &v2);
356     assert_same_hash(&v1, &v3);
357     assert_same_hash(&v1, &v4);
358 }
359 
360 #[test]
test_native_libs_tracking_hash_different_values()361 fn test_native_libs_tracking_hash_different_values() {
362     let mut v1 = Options::default();
363     let mut v2 = Options::default();
364     let mut v3 = Options::default();
365     let mut v4 = Options::default();
366     let mut v5 = Options::default();
367 
368     // Reference
369     v1.libs = vec![
370         NativeLib {
371             name: String::from("a"),
372             new_name: None,
373             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
374             verbatim: None,
375         },
376         NativeLib {
377             name: String::from("b"),
378             new_name: None,
379             kind: NativeLibKind::Framework { as_needed: None },
380             verbatim: None,
381         },
382         NativeLib {
383             name: String::from("c"),
384             new_name: None,
385             kind: NativeLibKind::Unspecified,
386             verbatim: None,
387         },
388     ];
389 
390     // Change label
391     v2.libs = vec![
392         NativeLib {
393             name: String::from("a"),
394             new_name: None,
395             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
396             verbatim: None,
397         },
398         NativeLib {
399             name: String::from("X"),
400             new_name: None,
401             kind: NativeLibKind::Framework { as_needed: None },
402             verbatim: None,
403         },
404         NativeLib {
405             name: String::from("c"),
406             new_name: None,
407             kind: NativeLibKind::Unspecified,
408             verbatim: None,
409         },
410     ];
411 
412     // Change kind
413     v3.libs = vec![
414         NativeLib {
415             name: String::from("a"),
416             new_name: None,
417             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
418             verbatim: None,
419         },
420         NativeLib {
421             name: String::from("b"),
422             new_name: None,
423             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
424             verbatim: None,
425         },
426         NativeLib {
427             name: String::from("c"),
428             new_name: None,
429             kind: NativeLibKind::Unspecified,
430             verbatim: None,
431         },
432     ];
433 
434     // Change new-name
435     v4.libs = vec![
436         NativeLib {
437             name: String::from("a"),
438             new_name: None,
439             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
440             verbatim: None,
441         },
442         NativeLib {
443             name: String::from("b"),
444             new_name: Some(String::from("X")),
445             kind: NativeLibKind::Framework { as_needed: None },
446             verbatim: None,
447         },
448         NativeLib {
449             name: String::from("c"),
450             new_name: None,
451             kind: NativeLibKind::Unspecified,
452             verbatim: None,
453         },
454     ];
455 
456     // Change verbatim
457     v5.libs = vec![
458         NativeLib {
459             name: String::from("a"),
460             new_name: None,
461             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
462             verbatim: None,
463         },
464         NativeLib {
465             name: String::from("b"),
466             new_name: None,
467             kind: NativeLibKind::Framework { as_needed: None },
468             verbatim: Some(true),
469         },
470         NativeLib {
471             name: String::from("c"),
472             new_name: None,
473             kind: NativeLibKind::Unspecified,
474             verbatim: None,
475         },
476     ];
477 
478     assert_different_hash(&v1, &v2);
479     assert_different_hash(&v1, &v3);
480     assert_different_hash(&v1, &v4);
481     assert_different_hash(&v1, &v5);
482 }
483 
484 #[test]
test_native_libs_tracking_hash_different_order()485 fn test_native_libs_tracking_hash_different_order() {
486     let mut v1 = Options::default();
487     let mut v2 = Options::default();
488     let mut v3 = Options::default();
489 
490     // Reference
491     v1.libs = vec![
492         NativeLib {
493             name: String::from("a"),
494             new_name: None,
495             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
496             verbatim: None,
497         },
498         NativeLib {
499             name: String::from("b"),
500             new_name: None,
501             kind: NativeLibKind::Framework { as_needed: None },
502             verbatim: None,
503         },
504         NativeLib {
505             name: String::from("c"),
506             new_name: None,
507             kind: NativeLibKind::Unspecified,
508             verbatim: None,
509         },
510     ];
511 
512     v2.libs = vec![
513         NativeLib {
514             name: String::from("b"),
515             new_name: None,
516             kind: NativeLibKind::Framework { as_needed: None },
517             verbatim: None,
518         },
519         NativeLib {
520             name: String::from("a"),
521             new_name: None,
522             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
523             verbatim: None,
524         },
525         NativeLib {
526             name: String::from("c"),
527             new_name: None,
528             kind: NativeLibKind::Unspecified,
529             verbatim: None,
530         },
531     ];
532 
533     v3.libs = vec![
534         NativeLib {
535             name: String::from("c"),
536             new_name: None,
537             kind: NativeLibKind::Unspecified,
538             verbatim: None,
539         },
540         NativeLib {
541             name: String::from("a"),
542             new_name: None,
543             kind: NativeLibKind::Static { bundle: None, whole_archive: None },
544             verbatim: None,
545         },
546         NativeLib {
547             name: String::from("b"),
548             new_name: None,
549             kind: NativeLibKind::Framework { as_needed: None },
550             verbatim: None,
551         },
552     ];
553 
554     // The hash should be order-dependent
555     assert_different_hash(&v1, &v2);
556     assert_different_hash(&v1, &v3);
557     assert_different_hash(&v2, &v3);
558 }
559 
560 #[test]
test_codegen_options_tracking_hash()561 fn test_codegen_options_tracking_hash() {
562     let reference = Options::default();
563     let mut opts = Options::default();
564 
565     macro_rules! untracked {
566         ($name: ident, $non_default_value: expr) => {
567             assert_ne!(opts.cg.$name, $non_default_value);
568             opts.cg.$name = $non_default_value;
569             assert_same_hash(&reference, &opts);
570         };
571     }
572 
573     // Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
574     // tidy-alphabetical-start
575     untracked!(ar, String::from("abc"));
576     untracked!(codegen_units, Some(42));
577     untracked!(default_linker_libraries, true);
578     untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
579     untracked!(extra_filename, String::from("extra-filename"));
580     untracked!(incremental, Some(String::from("abc")));
581     // `link_arg` is omitted because it just forwards to `link_args`.
582     untracked!(link_args, vec![String::from("abc"), String::from("def")]);
583     untracked!(link_self_contained, LinkSelfContained::on());
584     untracked!(linker, Some(PathBuf::from("linker")));
585     untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc));
586     untracked!(no_stack_check, true);
587     untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")]));
588     untracked!(rpath, true);
589     untracked!(save_temps, true);
590     untracked!(strip, Strip::Debuginfo);
591     // tidy-alphabetical-end
592 
593     macro_rules! tracked {
594         ($name: ident, $non_default_value: expr) => {
595             opts = reference.clone();
596             assert_ne!(opts.cg.$name, $non_default_value);
597             opts.cg.$name = $non_default_value;
598             assert_different_hash(&reference, &opts);
599         };
600     }
601 
602     // Make sure that changing a [TRACKED] option changes the hash.
603     // tidy-alphabetical-start
604     tracked!(code_model, Some(CodeModel::Large));
605     tracked!(control_flow_guard, CFGuard::Checks);
606     tracked!(debug_assertions, Some(true));
607     tracked!(debuginfo, DebugInfo::Limited);
608     tracked!(embed_bitcode, false);
609     tracked!(force_frame_pointers, Some(false));
610     tracked!(force_unwind_tables, Some(true));
611     tracked!(inline_threshold, Some(0xf007ba11));
612     tracked!(instrument_coverage, Some(InstrumentCoverage::All));
613     tracked!(link_dead_code, Some(true));
614     tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
615     tracked!(llvm_args, vec![String::from("1"), String::from("2")]);
616     tracked!(lto, LtoCli::Fat);
617     tracked!(metadata, vec![String::from("A"), String::from("B")]);
618     tracked!(no_prepopulate_passes, true);
619     tracked!(no_redzone, Some(true));
620     tracked!(no_vectorize_loops, true);
621     tracked!(no_vectorize_slp, true);
622     tracked!(opt_level, "3".to_string());
623     tracked!(overflow_checks, Some(true));
624     tracked!(panic, Some(PanicStrategy::Abort));
625     tracked!(passes, vec![String::from("1"), String::from("2")]);
626     tracked!(prefer_dynamic, true);
627     tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
628     tracked!(profile_use, Some(PathBuf::from("abc")));
629     tracked!(relocation_model, Some(RelocModel::Pic));
630     tracked!(relro_level, Some(RelroLevel::Full));
631     tracked!(soft_float, true);
632     tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
633     tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
634     tracked!(target_cpu, Some(String::from("abc")));
635     tracked!(target_feature, String::from("all the features, all of them"));
636     // tidy-alphabetical-end
637 }
638 
639 #[test]
test_top_level_options_tracked_no_crate()640 fn test_top_level_options_tracked_no_crate() {
641     let reference = Options::default();
642     let mut opts;
643 
644     macro_rules! tracked {
645         ($name: ident, $non_default_value: expr) => {
646             opts = reference.clone();
647             assert_ne!(opts.$name, $non_default_value);
648             opts.$name = $non_default_value;
649             // The crate hash should be the same
650             assert_eq!(reference.dep_tracking_hash(true), opts.dep_tracking_hash(true));
651             // The incremental hash should be different
652             assert_ne!(reference.dep_tracking_hash(false), opts.dep_tracking_hash(false));
653         };
654     }
655 
656     // Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash.
657     // tidy-alphabetical-start
658     tracked!(
659         real_rust_source_base_dir,
660         Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into())
661     );
662     tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
663     // tidy-alphabetical-end
664 }
665 
666 #[test]
test_unstable_options_tracking_hash()667 fn test_unstable_options_tracking_hash() {
668     let reference = Options::default();
669     let mut opts = Options::default();
670 
671     macro_rules! untracked {
672         ($name: ident, $non_default_value: expr) => {
673             assert_ne!(opts.unstable_opts.$name, $non_default_value);
674             opts.unstable_opts.$name = $non_default_value;
675             assert_same_hash(&reference, &opts);
676         };
677     }
678 
679     // Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
680     // tidy-alphabetical-start
681     untracked!(assert_incr_state, Some(String::from("loaded")));
682     untracked!(deduplicate_diagnostics, false);
683     untracked!(dep_tasks, true);
684     untracked!(dont_buffer_diagnostics, true);
685     untracked!(dump_dep_graph, true);
686     untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string()));
687     untracked!(dump_mir, Some(String::from("abc")));
688     untracked!(dump_mir_dataflow, true);
689     untracked!(dump_mir_dir, String::from("abc"));
690     untracked!(dump_mir_exclude_pass_number, true);
691     untracked!(dump_mir_graphviz, true);
692     untracked!(dump_mir_spanview, Some(MirSpanview::Statement));
693     untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into())));
694     untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json);
695     untracked!(dylib_lto, true);
696     untracked!(emit_stack_sizes, true);
697     untracked!(future_incompat_test, true);
698     untracked!(hir_stats, true);
699     untracked!(identify_regions, true);
700     untracked!(incremental_info, true);
701     untracked!(incremental_verify_ich, true);
702     untracked!(input_stats, true);
703     untracked!(keep_hygiene_data, true);
704     untracked!(link_native_libraries, false);
705     untracked!(llvm_time_trace, true);
706     untracked!(ls, true);
707     untracked!(macro_backtrace, true);
708     untracked!(meta_stats, true);
709     untracked!(mir_include_spans, true);
710     untracked!(nll_facts, true);
711     untracked!(no_analysis, true);
712     untracked!(no_leak_check, true);
713     untracked!(no_parallel_llvm, true);
714     untracked!(parse_only, true);
715     untracked!(perf_stats, true);
716     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
717     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
718     untracked!(print_llvm_passes, true);
719     untracked!(print_mono_items, Some(String::from("abc")));
720     untracked!(print_type_sizes, true);
721     untracked!(proc_macro_backtrace, true);
722     untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread);
723     untracked!(profile_closures, true);
724     untracked!(query_dep_graph, true);
725     untracked!(self_profile, SwitchWithOptPath::Enabled(None));
726     untracked!(self_profile_events, Some(vec![String::new()]));
727     untracked!(span_debug, true);
728     untracked!(span_free_formats, true);
729     untracked!(temps_dir, Some(String::from("abc")));
730     untracked!(threads, 99);
731     untracked!(time_llvm_passes, true);
732     untracked!(time_passes, true);
733     untracked!(time_passes_format, TimePassesFormat::Json);
734     untracked!(trace_macros, true);
735     untracked!(track_diagnostics, true);
736     untracked!(trim_diagnostic_paths, false);
737     untracked!(ui_testing, true);
738     untracked!(unpretty, Some("expanded".to_string()));
739     untracked!(unstable_options, true);
740     untracked!(validate_mir, true);
741     untracked!(verbose, true);
742     // tidy-alphabetical-end
743 
744     macro_rules! tracked {
745         ($name: ident, $non_default_value: expr) => {
746             opts = reference.clone();
747             assert_ne!(opts.unstable_opts.$name, $non_default_value);
748             opts.unstable_opts.$name = $non_default_value;
749             assert_different_hash(&reference, &opts);
750         };
751     }
752 
753     // Make sure that changing a [TRACKED] option changes the hash.
754     // tidy-alphabetical-start
755     tracked!(allow_features, Some(vec![String::from("lang_items")]));
756     tracked!(always_encode_mir, true);
757     tracked!(asm_comments, true);
758     tracked!(assume_incomplete_release, true);
759     tracked!(binary_dep_depinfo, true);
760     tracked!(box_noalias, false);
761     tracked!(
762         branch_protection,
763         Some(BranchProtection {
764             bti: true,
765             pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B })
766         })
767     );
768     tracked!(codegen_backend, Some("abc".to_string()));
769     tracked!(crate_attr, vec!["abc".to_string()]);
770     tracked!(debug_info_for_profiling, true);
771     tracked!(debug_macros, true);
772     tracked!(dep_info_omit_d_target, true);
773     tracked!(drop_tracking, true);
774     tracked!(dual_proc_macros, true);
775     tracked!(dwarf_version, Some(5));
776     tracked!(emit_thin_lto, false);
777     tracked!(export_executable_symbols, true);
778     tracked!(fewer_names, Some(true));
779     tracked!(flatten_format_args, false);
780     tracked!(force_unstable_if_unmarked, true);
781     tracked!(fuel, Some(("abc".to_string(), 99)));
782     tracked!(function_sections, Some(false));
783     tracked!(human_readable_cgu_names, true);
784     tracked!(incremental_ignore_spans, true);
785     tracked!(inline_in_all_cgus, Some(true));
786     tracked!(inline_mir, Some(true));
787     tracked!(inline_mir_hint_threshold, Some(123));
788     tracked!(inline_mir_threshold, Some(123));
789     tracked!(instrument_coverage, Some(InstrumentCoverage::All));
790     tracked!(instrument_mcount, true);
791     tracked!(instrument_xray, Some(InstrumentXRay::default()));
792     tracked!(link_directives, false);
793     tracked!(link_only, true);
794     tracked!(llvm_plugins, vec![String::from("plugin_name")]);
795     tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
796     tracked!(maximal_hir_to_mir_coverage, true);
797     tracked!(merge_functions, Some(MergeFunctions::Disabled));
798     tracked!(mir_emit_retag, true);
799     tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
800     tracked!(mir_keep_place_mention, true);
801     tracked!(mir_opt_level, Some(4));
802     tracked!(move_size_limit, Some(4096));
803     tracked!(mutable_noalias, false);
804     tracked!(no_generate_arange_section, true);
805     tracked!(no_jump_tables, true);
806     tracked!(no_link, true);
807     tracked!(no_profiler_runtime, true);
808     tracked!(no_unique_section_names, true);
809     tracked!(oom, OomStrategy::Panic);
810     tracked!(osx_rpath_install_name, true);
811     tracked!(packed_bundled_libs, true);
812     tracked!(panic_abort_tests, true);
813     tracked!(panic_in_drop, PanicStrategy::Abort);
814     tracked!(plt, Some(true));
815     tracked!(polonius, true);
816     tracked!(precise_enum_drop_elaboration, false);
817     tracked!(print_fuel, Some("abc".to_string()));
818     tracked!(profile, true);
819     tracked!(profile_emit, Some(PathBuf::from("abc")));
820     tracked!(profile_sample_use, Some(PathBuf::from("abc")));
821     tracked!(profiler_runtime, "abc".to_string());
822     tracked!(relax_elf_relocations, Some(true));
823     tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
824     tracked!(report_delayed_bugs, true);
825     tracked!(sanitizer, SanitizerSet::ADDRESS);
826     tracked!(sanitizer_cfi_canonical_jump_tables, None);
827     tracked!(sanitizer_cfi_generalize_pointers, Some(true));
828     tracked!(sanitizer_cfi_normalize_integers, Some(true));
829     tracked!(sanitizer_memory_track_origins, 2);
830     tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
831     tracked!(saturating_float_casts, Some(true));
832     tracked!(share_generics, Some(true));
833     tracked!(show_span, Some(String::from("abc")));
834     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
835     tracked!(split_lto_unit, Some(true));
836     tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
837     tracked!(stack_protector, StackProtector::All);
838     tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
839     tracked!(teach, true);
840     tracked!(thinlto, Some(true));
841     tracked!(thir_unsafeck, true);
842     tracked!(tiny_const_eval_limit, true);
843     tracked!(tls_model, Some(TlsModel::GeneralDynamic));
844     tracked!(trait_solver, TraitSolver::NextCoherence);
845     tracked!(translate_remapped_path_to_local_path, false);
846     tracked!(trap_unreachable, Some(false));
847     tracked!(treat_err_as_bug, NonZeroUsize::new(1));
848     tracked!(tune_cpu, Some(String::from("abc")));
849     tracked!(uninit_const_chunk_threshold, 123);
850     tracked!(unleash_the_miri_inside_of_you, true);
851     tracked!(use_ctors_section, Some(true));
852     tracked!(verify_llvm_ir, true);
853     tracked!(virtual_function_elimination, true);
854     tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
855     // tidy-alphabetical-end
856 
857     macro_rules! tracked_no_crate_hash {
858         ($name: ident, $non_default_value: expr) => {
859             opts = reference.clone();
860             assert_ne!(opts.unstable_opts.$name, $non_default_value);
861             opts.unstable_opts.$name = $non_default_value;
862             assert_non_crate_hash_different(&reference, &opts);
863         };
864     }
865     tracked_no_crate_hash!(no_codegen, true);
866 }
867 
868 #[test]
test_edition_parsing()869 fn test_edition_parsing() {
870     // test default edition
871     let options = Options::default();
872     assert!(options.edition == DEFAULT_EDITION);
873 
874     let mut handler = EarlyErrorHandler::new(ErrorOutputType::default());
875 
876     let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap();
877     let (sessopts, _) = build_session_options_and_crate_config(&mut handler, matches);
878     assert!(sessopts.edition == Edition::Edition2018)
879 }
880