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