@@ -370,9 +370,14 @@ impl LinkSelfContained {
370
370
/// components was set individually. This would also require the `-Zunstable-options` flag, to
371
371
/// be allowed.
372
372
fn are_unstable_variants_set ( & self ) -> bool {
373
- let any_component_set =
374
- !self . enabled_components . is_empty ( ) || !self . disabled_components . is_empty ( ) ;
375
- self . explicitly_set . is_none ( ) && any_component_set
373
+ if self . explicitly_set . is_some ( ) {
374
+ return false ;
375
+ }
376
+
377
+ // Only the linker component is stable, anything else is thus unstable.
378
+ let mentioned_components = self . enabled_components . union ( self . disabled_components ) ;
379
+ let unstable_components = mentioned_components - LinkSelfContainedComponents :: LINKER ;
380
+ !unstable_components. is_empty ( )
376
381
}
377
382
378
383
/// Returns whether the self-contained linker component was enabled on the CLI, using the
@@ -399,7 +404,7 @@ impl LinkSelfContained {
399
404
}
400
405
}
401
406
402
- /// The different values that `-Z linker-features` can take on the CLI: a list of individually
407
+ /// The different values that `-C linker-features` can take on the CLI: a list of individually
403
408
/// enabled or disabled features used during linking.
404
409
///
405
410
/// There is no need to enable or disable them in bulk. Each feature is fine-grained, and can be
@@ -439,6 +444,44 @@ impl LinkerFeaturesCli {
439
444
_ => None ,
440
445
}
441
446
}
447
+
448
+ /// When *not* using `-Z unstable-options` on the CLI, ensure only stable linker features are
449
+ /// used, for the given `TargetTuple`. Returns `Ok` if no unstable variants are used.
450
+ /// The caller should ensure that e.g. `nightly_options::is_unstable_enabled()`
451
+ /// returns false.
452
+ pub ( crate ) fn check_unstable_variants ( & self , target_tuple : & TargetTuple ) -> Result < ( ) , String > {
453
+ // `-C linker-features=[-+]lld` is only stable on x64 linux.
454
+ let check_lld = |features : LinkerFeatures , polarity : & str | {
455
+ let has_lld = features. is_lld_enabled ( ) ;
456
+ if has_lld && target_tuple. tuple ( ) != "x86_64-unknown-linux-gnu" {
457
+ return Err ( format ! (
458
+ "`-C linker-features={polarity}lld` is unstable on the `{target_tuple}` \
459
+ target. The `-Z unstable-options` flag must also be passed to use it on this target",
460
+ ) ) ;
461
+ }
462
+ Ok ( ( ) )
463
+ } ;
464
+ check_lld ( self . enabled , "+" ) ?;
465
+ check_lld ( self . disabled , "-" ) ?;
466
+
467
+ // Since only lld is stable, any non-lld feature used is unstable, and that's an error.
468
+ let unstable_enabled = self . enabled - LinkerFeatures :: LLD ;
469
+ let unstable_disabled = self . disabled - LinkerFeatures :: LLD ;
470
+ if !unstable_enabled. union ( unstable_disabled) . is_empty ( ) {
471
+ let unstable_features: Vec < _ > = unstable_enabled
472
+ . iter ( )
473
+ . map ( |f| format ! ( "+{}" , f. as_str( ) . unwrap( ) ) )
474
+ . chain ( unstable_disabled. iter ( ) . map ( |f| format ! ( "-{}" , f. as_str( ) . unwrap( ) ) ) )
475
+ . collect ( ) ;
476
+ return Err ( format ! (
477
+ "the requested `-C linker-features={}` are unstable, and also require the \
478
+ `-Z unstable-options` flag to be usable",
479
+ unstable_features. join( "," ) ,
480
+ ) ) ;
481
+ }
482
+
483
+ Ok ( ( ) )
484
+ }
442
485
}
443
486
444
487
/// Used with `-Z assert-incr-state`.
@@ -2587,9 +2630,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
2587
2630
}
2588
2631
}
2589
2632
2590
- if !nightly_options:: is_unstable_enabled ( matches)
2591
- && cg. force_frame_pointers == FramePointer :: NonLeaf
2592
- {
2633
+ let unstable_options_enabled = nightly_options:: is_unstable_enabled ( matches) ;
2634
+ if !unstable_options_enabled && cg. force_frame_pointers == FramePointer :: NonLeaf {
2593
2635
early_dcx. early_fatal (
2594
2636
"`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
2595
2637
and a nightly compiler",
@@ -2599,12 +2641,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
2599
2641
// For testing purposes, until we have more feedback about these options: ensure `-Z
2600
2642
// unstable-options` is required when using the unstable `-C link-self-contained` and `-C
2601
2643
// linker-flavor` options.
2602
- if !nightly_options :: is_unstable_enabled ( matches ) {
2644
+ if !unstable_options_enabled {
2603
2645
let uses_unstable_self_contained_option =
2604
2646
cg. link_self_contained . are_unstable_variants_set ( ) ;
2605
2647
if uses_unstable_self_contained_option {
2606
2648
early_dcx. early_fatal (
2607
- "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off` are stable, \
2649
+ "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off`/`-linker`/`+linker` are stable, \
2608
2650
the `-Z unstable-options` flag must also be passed to use the unstable values",
2609
2651
) ;
2610
2652
}
@@ -2647,6 +2689,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
2647
2689
let debuginfo = select_debuginfo ( matches, & cg) ;
2648
2690
let debuginfo_compression = unstable_opts. debuginfo_compression ;
2649
2691
2692
+ if !unstable_options_enabled {
2693
+ if let Err ( error) = cg. linker_features . check_unstable_variants ( & target_triple) {
2694
+ early_dcx. early_fatal ( error) ;
2695
+ }
2696
+ }
2697
+
2650
2698
let crate_name = matches. opt_str ( "crate-name" ) ;
2651
2699
let unstable_features = UnstableFeatures :: from_environment ( crate_name. as_deref ( ) ) ;
2652
2700
// Parse any `-l` flags, which link to native libraries.
0 commit comments