@@ -370,12 +370,34 @@ impl LinkSelfContained {
370
370
}
371
371
372
372
/// To help checking CLI usage while some of the values are unstable: returns whether one of the
373
- /// components was set individually. This would also require the `-Zunstable-options` flag, to
374
- /// be allowed.
375
- fn are_unstable_variants_set ( & self ) -> bool {
376
- let any_component_set =
377
- !self . enabled_components . is_empty ( ) || !self . disabled_components . is_empty ( ) ;
378
- self . explicitly_set . is_none ( ) && any_component_set
373
+ /// unstable components was set individually, for the given `TargetTuple`. This would also
374
+ /// require the `-Zunstable-options` flag, to be allowed.
375
+ fn check_unstable_variants ( & self , target_tuple : & TargetTuple ) -> Result < ( ) , String > {
376
+ if self . explicitly_set . is_some ( ) {
377
+ return Ok ( ( ) ) ;
378
+ }
379
+
380
+ // `-C link-self-contained=-linker` is only stable on x64 linux.
381
+ let has_minus_linker = self . disabled_components . is_linker_enabled ( ) ;
382
+ if has_minus_linker && target_tuple. tuple ( ) != "x86_64-unknown-linux-gnu" {
383
+ return Err ( format ! (
384
+ "`-C link-self-contained=-linker` is unstable on the `{target_tuple}` \
385
+ target. The `-Z unstable-options` flag must also be passed to use it on this target",
386
+ ) ) ;
387
+ }
388
+
389
+ // Any `+linker` or other component used is unstable, and that's an error.
390
+ let unstable_enabled = self . enabled_components ;
391
+ let unstable_disabled = self . disabled_components - LinkSelfContainedComponents :: LINKER ;
392
+ if !unstable_enabled. union ( unstable_disabled) . is_empty ( ) {
393
+ return Err ( String :: from (
394
+ "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off`/`-linker` \
395
+ are stable, the `-Z unstable-options` flag must also be passed to use \
396
+ the unstable values",
397
+ ) ) ;
398
+ }
399
+
400
+ Ok ( ( ) )
379
401
}
380
402
381
403
/// Returns whether the self-contained linker component was enabled on the CLI, using the
@@ -402,7 +424,7 @@ impl LinkSelfContained {
402
424
}
403
425
}
404
426
405
- /// The different values that `-Z linker-features` can take on the CLI: a list of individually
427
+ /// The different values that `-C linker-features` can take on the CLI: a list of individually
406
428
/// enabled or disabled features used during linking.
407
429
///
408
430
/// There is no need to enable or disable them in bulk. Each feature is fine-grained, and can be
@@ -442,6 +464,39 @@ impl LinkerFeaturesCli {
442
464
_ => None ,
443
465
}
444
466
}
467
+
468
+ /// When *not* using `-Z unstable-options` on the CLI, ensure only stable linker features are
469
+ /// used, for the given `TargetTuple`. Returns `Ok` if no unstable variants are used.
470
+ /// The caller should ensure that e.g. `nightly_options::is_unstable_enabled()`
471
+ /// returns false.
472
+ pub ( crate ) fn check_unstable_variants ( & self , target_tuple : & TargetTuple ) -> Result < ( ) , String > {
473
+ // `-C linker-features=-lld` is only stable on x64 linux.
474
+ let has_minus_lld = self . disabled . is_lld_enabled ( ) ;
475
+ if has_minus_lld && target_tuple. tuple ( ) != "x86_64-unknown-linux-gnu" {
476
+ return Err ( format ! (
477
+ "`-C linker-features=-lld` is unstable on the `{target_tuple}` \
478
+ target. The `-Z unstable-options` flag must also be passed to use it on this target",
479
+ ) ) ;
480
+ }
481
+
482
+ // Any `+lld` or non-lld feature used is unstable, and that's an error.
483
+ let unstable_enabled = self . enabled ;
484
+ let unstable_disabled = self . disabled - LinkerFeatures :: LLD ;
485
+ if !unstable_enabled. union ( unstable_disabled) . is_empty ( ) {
486
+ let unstable_features: Vec < _ > = unstable_enabled
487
+ . iter ( )
488
+ . map ( |f| format ! ( "+{}" , f. as_str( ) . unwrap( ) ) )
489
+ . chain ( unstable_disabled. iter ( ) . map ( |f| format ! ( "-{}" , f. as_str( ) . unwrap( ) ) ) )
490
+ . collect ( ) ;
491
+ return Err ( format ! (
492
+ "`-C linker-features={}` is unstable, and also requires the \
493
+ `-Z unstable-options` flag to be used",
494
+ unstable_features. join( "," ) ,
495
+ ) ) ;
496
+ }
497
+
498
+ Ok ( ( ) )
499
+ }
445
500
}
446
501
447
502
/// Used with `-Z assert-incr-state`.
@@ -2638,26 +2693,21 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
2638
2693
}
2639
2694
}
2640
2695
2641
- if !nightly_options:: is_unstable_enabled ( matches)
2642
- && cg. force_frame_pointers == FramePointer :: NonLeaf
2643
- {
2696
+ let unstable_options_enabled = nightly_options:: is_unstable_enabled ( matches) ;
2697
+ if !unstable_options_enabled && cg. force_frame_pointers == FramePointer :: NonLeaf {
2644
2698
early_dcx. early_fatal (
2645
2699
"`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
2646
2700
and a nightly compiler",
2647
2701
)
2648
2702
}
2649
2703
2650
- // For testing purposes, until we have more feedback about these options: ensure `-Z
2651
- // unstable-options` is required when using the unstable `-C link-self-contained` and `-C
2652
- // linker-flavor` options.
2653
- if !nightly_options:: is_unstable_enabled ( matches) {
2654
- let uses_unstable_self_contained_option =
2655
- cg. link_self_contained . are_unstable_variants_set ( ) ;
2656
- if uses_unstable_self_contained_option {
2657
- early_dcx. early_fatal (
2658
- "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
2659
- the `-Z unstable-options` flag must also be passed to use the unstable values",
2660
- ) ;
2704
+ let target_triple = parse_target_triple ( early_dcx, matches) ;
2705
+
2706
+ // Ensure `-Z unstable-options` is required when using the unstable `-C link-self-contained` and
2707
+ // `-C linker-flavor` options.
2708
+ if !unstable_options_enabled {
2709
+ if let Err ( error) = cg. link_self_contained . check_unstable_variants ( & target_triple) {
2710
+ early_dcx. early_fatal ( error) ;
2661
2711
}
2662
2712
2663
2713
if let Some ( flavor) = cg. linker_flavor {
@@ -2697,7 +2747,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
2697
2747
2698
2748
let cg = cg;
2699
2749
2700
- let target_triple = parse_target_triple ( early_dcx, matches) ;
2701
2750
let opt_level = parse_opt_level ( early_dcx, matches, & cg) ;
2702
2751
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
2703
2752
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
@@ -2706,6 +2755,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
2706
2755
let debuginfo = select_debuginfo ( matches, & cg) ;
2707
2756
let debuginfo_compression = unstable_opts. debuginfo_compression ;
2708
2757
2758
+ if !unstable_options_enabled {
2759
+ if let Err ( error) = cg. linker_features . check_unstable_variants ( & target_triple) {
2760
+ early_dcx. early_fatal ( error) ;
2761
+ }
2762
+ }
2763
+
2709
2764
let crate_name = matches. opt_str ( "crate-name" ) ;
2710
2765
let unstable_features = UnstableFeatures :: from_environment ( crate_name. as_deref ( ) ) ;
2711
2766
// Parse any `-l` flags, which link to native libraries.
0 commit comments