11//! Code for dealing with `--print` requests.
22
3+ use std:: fmt;
34use std:: sync:: LazyLock ;
45
56use rustc_data_structures:: fx:: FxHashSet ;
@@ -8,35 +9,7 @@ use crate::EarlyDiagCtxt;
89use crate :: config:: {
910 CodegenOptions , OutFileName , UnstableOptions , nightly_options, split_out_file_name,
1011} ;
11-
12- const PRINT_KINDS : & [ ( & str , PrintKind ) ] = & [
13- // tidy-alphabetical-start
14- ( "all-target-specs-json" , PrintKind :: AllTargetSpecsJson ) ,
15- ( "calling-conventions" , PrintKind :: CallingConventions ) ,
16- ( "cfg" , PrintKind :: Cfg ) ,
17- ( "check-cfg" , PrintKind :: CheckCfg ) ,
18- ( "code-models" , PrintKind :: CodeModels ) ,
19- ( "crate-name" , PrintKind :: CrateName ) ,
20- ( "crate-root-lint-levels" , PrintKind :: CrateRootLintLevels ) ,
21- ( "deployment-target" , PrintKind :: DeploymentTarget ) ,
22- ( "file-names" , PrintKind :: FileNames ) ,
23- ( "host-tuple" , PrintKind :: HostTuple ) ,
24- ( "link-args" , PrintKind :: LinkArgs ) ,
25- ( "native-static-libs" , PrintKind :: NativeStaticLibs ) ,
26- ( "relocation-models" , PrintKind :: RelocationModels ) ,
27- ( "split-debuginfo" , PrintKind :: SplitDebuginfo ) ,
28- ( "stack-protector-strategies" , PrintKind :: StackProtectorStrategies ) ,
29- ( "supported-crate-types" , PrintKind :: SupportedCrateTypes ) ,
30- ( "sysroot" , PrintKind :: Sysroot ) ,
31- ( "target-cpus" , PrintKind :: TargetCPUs ) ,
32- ( "target-features" , PrintKind :: TargetFeatures ) ,
33- ( "target-libdir" , PrintKind :: TargetLibdir ) ,
34- ( "target-list" , PrintKind :: TargetList ) ,
35- ( "target-spec-json" , PrintKind :: TargetSpecJson ) ,
36- ( "target-spec-json-schema" , PrintKind :: TargetSpecJsonSchema ) ,
37- ( "tls-models" , PrintKind :: TlsModels ) ,
38- // tidy-alphabetical-end
39- ] ;
12+ use crate :: macros:: AllVariants ;
4013
4114#[ derive( Clone , PartialEq , Debug ) ]
4215pub struct PrintRequest {
@@ -45,6 +18,7 @@ pub struct PrintRequest {
4518}
4619
4720#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
21+ #[ derive( AllVariants ) ]
4822pub enum PrintKind {
4923 // tidy-alphabetical-start
5024 AllTargetSpecsJson ,
@@ -74,11 +48,94 @@ pub enum PrintKind {
7448 // tidy-alphabetical-end
7549}
7650
51+ impl PrintKind {
52+ /// FIXME: rust-analyzer doesn't support `#![feature(macro_derive)]` yet
53+ /// (<https://github.com/rust-lang/rust-analyzer/issues/21043>), which breaks autocomplete.
54+ /// Work around that by aliasing the trait constant to a regular constant.
55+ const ALL_VARIANTS : & [ Self ] = <Self as AllVariants >:: ALL_VARIANTS ;
56+
57+ fn name ( self ) -> & ' static str {
58+ use PrintKind :: * ;
59+ match self {
60+ // tidy-alphabetical-start
61+ AllTargetSpecsJson => "all-target-specs-json" ,
62+ CallingConventions => "calling-conventions" ,
63+ Cfg => "cfg" ,
64+ CheckCfg => "check-cfg" ,
65+ CodeModels => "code-models" ,
66+ CrateName => "crate-name" ,
67+ CrateRootLintLevels => "crate-root-lint-levels" ,
68+ DeploymentTarget => "deployment-target" ,
69+ FileNames => "file-names" ,
70+ HostTuple => "host-tuple" ,
71+ LinkArgs => "link-args" ,
72+ NativeStaticLibs => "native-static-libs" ,
73+ RelocationModels => "relocation-models" ,
74+ SplitDebuginfo => "split-debuginfo" ,
75+ StackProtectorStrategies => "stack-protector-strategies" ,
76+ SupportedCrateTypes => "supported-crate-types" ,
77+ Sysroot => "sysroot" ,
78+ TargetCPUs => "target-cpus" ,
79+ TargetFeatures => "target-features" ,
80+ TargetLibdir => "target-libdir" ,
81+ TargetList => "target-list" ,
82+ TargetSpecJson => "target-spec-json" ,
83+ TargetSpecJsonSchema => "target-spec-json-schema" ,
84+ TlsModels => "tls-models" ,
85+ // tidy-alphabetical-end
86+ }
87+ }
88+
89+ fn is_stable ( self ) -> bool {
90+ use PrintKind :: * ;
91+ match self {
92+ // Stable values:
93+ CallingConventions
94+ | Cfg
95+ | CodeModels
96+ | CrateName
97+ | DeploymentTarget
98+ | FileNames
99+ | HostTuple
100+ | LinkArgs
101+ | NativeStaticLibs
102+ | RelocationModels
103+ | SplitDebuginfo
104+ | StackProtectorStrategies
105+ | Sysroot
106+ | TargetCPUs
107+ | TargetFeatures
108+ | TargetLibdir
109+ | TargetList
110+ | TlsModels => true ,
111+
112+ // Unstable values:
113+ AllTargetSpecsJson => false ,
114+ CheckCfg => false ,
115+ CrateRootLintLevels => false ,
116+ SupportedCrateTypes => false ,
117+ TargetSpecJson => false ,
118+ TargetSpecJsonSchema => false ,
119+ }
120+ }
121+
122+ fn from_str ( s : & str ) -> Option < Self > {
123+ Self :: ALL_VARIANTS . iter ( ) . find ( |kind| kind. name ( ) == s) . copied ( )
124+ }
125+ }
126+
127+ impl fmt:: Display for PrintKind {
128+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
129+ self . name ( ) . fmt ( f)
130+ }
131+ }
132+
77133pub ( crate ) static PRINT_HELP : LazyLock < String > = LazyLock :: new ( || {
134+ let print_kinds =
135+ PrintKind :: ALL_VARIANTS . iter ( ) . map ( |kind| kind. name ( ) ) . collect :: < Vec < _ > > ( ) . join ( "|" ) ;
78136 format ! (
79137 "Compiler information to print on stdout (or to a file)\n \
80- INFO may be one of <{}>.",
81- PRINT_KINDS . iter( ) . map( |( name, _) | format!( "{name}" ) ) . collect:: <Vec <_>>( ) . join( "|" )
138+ INFO may be one of <{print_kinds}>.",
82139 )
83140} ) ;
84141
@@ -107,11 +164,9 @@ pub(crate) fn collect_print_requests(
107164 prints. extend ( matches. opt_strs ( "print" ) . into_iter ( ) . map ( |req| {
108165 let ( req, out) = split_out_file_name ( & req) ;
109166
110- let kind = if let Some ( ( print_name, print_kind) ) =
111- PRINT_KINDS . iter ( ) . find ( |& & ( name, _) | name == req)
112- {
113- check_print_request_stability ( early_dcx, unstable_opts, ( print_name, * print_kind) ) ;
114- * print_kind
167+ let kind = if let Some ( print_kind) = PrintKind :: from_str ( req) {
168+ check_print_request_stability ( early_dcx, unstable_opts, print_kind) ;
169+ print_kind
115170 } else {
116171 let is_nightly = nightly_options:: match_is_nightly_build ( matches) ;
117172 emit_unknown_print_request_help ( early_dcx, req, is_nightly)
@@ -136,41 +191,23 @@ pub(crate) fn collect_print_requests(
136191fn check_print_request_stability (
137192 early_dcx : & EarlyDiagCtxt ,
138193 unstable_opts : & UnstableOptions ,
139- ( print_name , print_kind) : ( & str , PrintKind ) ,
194+ print_kind : PrintKind ,
140195) {
141- if !is_print_request_stable ( print_kind) && !unstable_opts. unstable_options {
196+ if !print_kind. is_stable ( ) && !unstable_opts. unstable_options {
142197 early_dcx. early_fatal ( format ! (
143- "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
144- print option"
198+ "the `-Z unstable-options` flag must also be passed to enable the `{print_kind}` print option"
145199 ) ) ;
146200 }
147201}
148202
149- fn is_print_request_stable ( print_kind : PrintKind ) -> bool {
150- match print_kind {
151- PrintKind :: AllTargetSpecsJson
152- | PrintKind :: CheckCfg
153- | PrintKind :: CrateRootLintLevels
154- | PrintKind :: SupportedCrateTypes
155- | PrintKind :: TargetSpecJson
156- | PrintKind :: TargetSpecJsonSchema => false ,
157- _ => true ,
158- }
159- }
160-
161203fn emit_unknown_print_request_help ( early_dcx : & EarlyDiagCtxt , req : & str , is_nightly : bool ) -> ! {
162- let prints = PRINT_KINDS
204+ let prints = PrintKind :: ALL_VARIANTS
163205 . iter ( )
164- . filter_map ( |( name, kind) | {
165- // If we're not on nightly, we don't want to print unstable options
166- if !is_nightly && !is_print_request_stable ( * kind) {
167- None
168- } else {
169- Some ( format ! ( "`{name}`" ) )
170- }
171- } )
172- . collect :: < Vec < _ > > ( ) ;
173- let prints = prints. join ( ", " ) ;
206+ // If we're not on nightly, we don't want to print unstable options
207+ . filter ( |kind| is_nightly || kind. is_stable ( ) )
208+ . map ( |kind| format ! ( "`{kind}`" ) )
209+ . collect :: < Vec < _ > > ( )
210+ . join ( ", " ) ;
174211
175212 let mut diag = early_dcx. early_struct_fatal ( format ! ( "unknown print request: `{req}`" ) ) ;
176213 #[ allow( rustc:: diagnostic_outside_of_impl) ]
0 commit comments