@@ -6,6 +6,14 @@ pub(crate) trait ConfigType: Sized {
66 /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
77 /// pipe-separated list of variants; for other types it returns "<type>".
88 fn doc_hint ( ) -> String ;
9+
10+ /// Return `true` if the variant (i.e. value of this type) is stable.
11+ ///
12+ /// By default, return true for all values. Enums annotated with `#[config_type]`
13+ /// are automatically implemented, based on the `#[unstable_variant]` annotation.
14+ fn stable_variant ( & self ) -> bool {
15+ true
16+ }
917}
1018
1119impl ConfigType for bool {
@@ -51,6 +59,13 @@ impl ConfigType for IgnoreList {
5159}
5260
5361macro_rules! create_config {
62+ // Options passed in to the macro.
63+ //
64+ // - $i: the ident name of the option
65+ // - $ty: the type of the option value
66+ // - $def: the default value of the option
67+ // - $stb: true if the option is stable
68+ // - $dstring: description of the option
5469 ( $( $i: ident: $ty: ty, $def: expr, $stb: expr, $( $dstring: expr ) ,+ ) ;+ $( ; ) * ) => (
5570 #[ cfg( test) ]
5671 use std:: collections:: HashSet ;
@@ -61,9 +76,12 @@ macro_rules! create_config {
6176 #[ derive( Clone ) ]
6277 #[ allow( unreachable_pub) ]
6378 pub struct Config {
64- // For each config item, we store a bool indicating whether it has
65- // been accessed and the value, and a bool whether the option was
66- // manually initialised, or taken from the default,
79+ // For each config item, we store:
80+ //
81+ // - 0: true if the value has been access
82+ // - 1: true if the option was manually initialized
83+ // - 2: the option value
84+ // - 3: true if the option is unstable
6785 $( $i: ( Cell <bool >, bool , $ty, bool ) ) ,+
6886 }
6987
@@ -143,18 +161,13 @@ macro_rules! create_config {
143161
144162 fn fill_from_parsed_config( mut self , parsed: PartialConfig , dir: & Path ) -> Config {
145163 $(
146- if let Some ( val) = parsed. $i {
147- if self . $i. 3 {
164+ if let Some ( option_value) = parsed. $i {
165+ let option_stable = self . $i. 3 ;
166+ if $crate:: config:: config_type:: is_stable_option_and_value(
167+ stringify!( $i) , option_stable, & option_value
168+ ) {
148169 self . $i. 1 = true ;
149- self . $i. 2 = val;
150- } else {
151- if crate :: is_nightly_channel!( ) {
152- self . $i. 1 = true ;
153- self . $i. 2 = val;
154- } else {
155- eprintln!( "Warning: can't set `{} = {:?}`, unstable features are only \
156- available in nightly channel.", stringify!( $i) , val) ;
157- }
170+ self . $i. 2 = option_value;
158171 }
159172 }
160173 ) +
@@ -221,12 +234,22 @@ macro_rules! create_config {
221234 match key {
222235 $(
223236 stringify!( $i) => {
224- self . $i. 1 = true ;
225- self . $i. 2 = val. parse:: <$ty>( )
237+ let option_value = val. parse:: <$ty>( )
226238 . expect( & format!( "Failed to parse override for {} (\" {}\" ) as a {}" ,
227239 stringify!( $i) ,
228240 val,
229241 stringify!( $ty) ) ) ;
242+
243+ // Users are currently allowed to set unstable
244+ // options/variants via the `--config` options override.
245+ //
246+ // There is ongoing discussion about how to move forward here:
247+ // https://github.com/rust-lang/rustfmt/pull/5379
248+ //
249+ // For now, do not validate whether the option or value is stable,
250+ // just always set it.
251+ self . $i. 1 = true ;
252+ self . $i. 2 = option_value;
230253 }
231254 ) +
232255 _ => panic!( "Unknown config key in override: {}" , key)
@@ -424,3 +447,38 @@ macro_rules! create_config {
424447 }
425448 )
426449}
450+
451+ pub ( crate ) fn is_stable_option_and_value < T > (
452+ option_name : & str ,
453+ option_stable : bool ,
454+ option_value : & T ,
455+ ) -> bool
456+ where
457+ T : PartialEq + std:: fmt:: Debug + ConfigType ,
458+ {
459+ let nightly = crate :: is_nightly_channel!( ) ;
460+ let variant_stable = option_value. stable_variant ( ) ;
461+ match ( nightly, option_stable, variant_stable) {
462+ // Stable with an unstable option
463+ ( false , false , _) => {
464+ eprintln ! (
465+ "Warning: can't set `{} = {:?}`, unstable features are only \
466+ available in nightly channel.",
467+ option_name, option_value
468+ ) ;
469+ false
470+ }
471+ // Stable with a stable option, but an unstable variant
472+ ( false , true , false ) => {
473+ eprintln ! (
474+ "Warning: can't set `{} = {:?}`, unstable variants are only \
475+ available in nightly channel.",
476+ option_name, option_value
477+ ) ;
478+ false
479+ }
480+ // Nightly: everything allowed
481+ // Stable with stable option and variant: allowed
482+ ( true , _, _) | ( false , true , true ) => true ,
483+ }
484+ }
0 commit comments