@@ -29,11 +29,10 @@ use rustc_resolve::Resolver;
29
29
use rustc_session:: code_stats:: VTableSizeInfo ;
30
30
use rustc_session:: config:: { CrateType , Input , OutFileName , OutputFilenames , OutputType } ;
31
31
use rustc_session:: cstore:: Untracked ;
32
- use rustc_session:: output:: { collect_crate_types, filename_for_input, find_crate_name } ;
32
+ use rustc_session:: output:: { collect_crate_types, filename_for_input} ;
33
33
use rustc_session:: search_paths:: PathKind ;
34
34
use rustc_session:: { Limit , Session } ;
35
- use rustc_span:: symbol:: { Symbol , sym} ;
36
- use rustc_span:: { FileName , SourceFileHash , SourceFileHashAlgorithm } ;
35
+ use rustc_span:: { FileName , SourceFileHash , SourceFileHashAlgorithm , Span , Symbol , sym} ;
37
36
use rustc_target:: spec:: PanicStrategy ;
38
37
use rustc_trait_selection:: traits;
39
38
use tracing:: { info, instrument} ;
@@ -740,8 +739,7 @@ pub(crate) fn create_global_ctxt<'tcx>(
740
739
741
740
let pre_configured_attrs = rustc_expand:: config:: pre_configure_attrs ( sess, & krate. attrs ) ;
742
741
743
- // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
744
- let crate_name = find_crate_name ( sess, & pre_configured_attrs) ;
742
+ let crate_name = get_crate_name ( sess, & pre_configured_attrs) ;
745
743
let crate_types = collect_crate_types ( sess, & pre_configured_attrs) ;
746
744
let stable_crate_id = StableCrateId :: new (
747
745
crate_name,
@@ -750,7 +748,7 @@ pub(crate) fn create_global_ctxt<'tcx>(
750
748
sess. cfg_version ,
751
749
) ;
752
750
let outputs = util:: build_output_filenames ( & pre_configured_attrs, sess) ;
753
- let dep_graph = setup_dep_graph ( sess) ?;
751
+ let dep_graph = setup_dep_graph ( sess, crate_name ) ?;
754
752
755
753
let cstore =
756
754
FreezeLock :: new ( Box :: new ( CStore :: new ( compiler. codegen_backend . metadata_loader ( ) ) ) as _ ) ;
@@ -1147,23 +1145,83 @@ pub(crate) fn start_codegen<'tcx>(
1147
1145
Ok ( codegen)
1148
1146
}
1149
1147
1150
- fn get_recursion_limit ( krate_attrs : & [ ast:: Attribute ] , sess : & Session ) -> Limit {
1151
- if let Some ( attr) = krate_attrs
1152
- . iter ( )
1153
- . find ( |attr| attr. has_name ( sym:: recursion_limit) && attr. value_str ( ) . is_none ( ) )
1148
+ /// Compute and validate the crate name.
1149
+ pub fn get_crate_name ( sess : & Session , krate_attrs : & [ ast:: Attribute ] ) -> Symbol {
1150
+ // We unconditionally validate all `#![crate_name]`s even if a crate name was
1151
+ // set on the command line via `--crate-name` which we prioritize over the
1152
+ // crate attributes. We perform the validation here instead of later to ensure
1153
+ // it gets run in all code paths requiring the crate name very early on.
1154
+ // Namely, print requests (`--print`).
1155
+ let attr_crate_name =
1156
+ validate_and_find_value_str_builtin_attr ( sym:: crate_name, sess, krate_attrs) ;
1157
+
1158
+ let validate = |name, span| {
1159
+ rustc_session:: output:: validate_crate_name ( sess, name, span) ;
1160
+ name
1161
+ } ;
1162
+
1163
+ if let Some ( crate_name) = & sess. opts . crate_name {
1164
+ let crate_name = Symbol :: intern ( crate_name) ;
1165
+ if let Some ( ( attr_crate_name, span) ) = attr_crate_name
1166
+ && attr_crate_name != crate_name
1167
+ {
1168
+ sess. dcx ( ) . emit_err ( errors:: CrateNameDoesNotMatch {
1169
+ span,
1170
+ crate_name,
1171
+ attr_crate_name,
1172
+ } ) ;
1173
+ }
1174
+ return validate ( crate_name, None ) ;
1175
+ }
1176
+
1177
+ if let Some ( ( crate_name, span) ) = attr_crate_name {
1178
+ return validate ( crate_name, Some ( span) ) ;
1179
+ }
1180
+
1181
+ if let Input :: File ( ref path) = sess. io . input
1182
+ && let Some ( file_stem) = path. file_stem ( ) . and_then ( |s| s. to_str ( ) )
1154
1183
{
1155
- // This is here mainly to check for using a macro, such as
1156
- // #![recursion_limit = foo!()]. That is not supported since that
1157
- // would require expanding this while in the middle of expansion,
1158
- // which needs to know the limit before expanding. Otherwise,
1159
- // validation would normally be caught in AstValidator (via
1160
- // `check_builtin_attribute`), but by the time that runs the macro
1161
- // is expanded, and it doesn't give an error.
1162
- validate_attr:: emit_fatal_malformed_builtin_attribute (
1163
- & sess. psess ,
1164
- attr,
1165
- sym:: recursion_limit,
1166
- ) ;
1184
+ if file_stem. starts_with ( '-' ) {
1185
+ sess. dcx ( ) . emit_err ( errors:: CrateNameInvalid { crate_name : file_stem } ) ;
1186
+ } else {
1187
+ return validate ( Symbol :: intern ( & file_stem. replace ( '-' , "_" ) ) , None ) ;
1188
+ }
1167
1189
}
1190
+
1191
+ Symbol :: intern ( "rust_out" )
1192
+ }
1193
+
1194
+ fn get_recursion_limit ( krate_attrs : & [ ast:: Attribute ] , sess : & Session ) -> Limit {
1195
+ // We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
1196
+ // because that would require expanding this while in the middle of expansion, which needs to
1197
+ // know the limit before expanding.
1198
+ let _ = validate_and_find_value_str_builtin_attr ( sym:: recursion_limit, sess, krate_attrs) ;
1168
1199
rustc_middle:: middle:: limits:: get_recursion_limit ( krate_attrs, sess)
1169
1200
}
1201
+
1202
+ /// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find.
1203
+ ///
1204
+ /// This validator is intended for built-in attributes whose value needs to be known very early
1205
+ /// during compilation (namely, before macro expansion) and it mainly exists to reject macro calls
1206
+ /// inside of the attributes, such as in `#![name = expand!()]`. Normal attribute validation happens
1207
+ /// during semantic analysis via [`TyCtxt::check_mod_attrs`] which happens *after* macro expansion
1208
+ /// when such macro calls (here: `expand`) have already been expanded and we can no longer check for
1209
+ /// their presence.
1210
+ ///
1211
+ /// [value-str]: ast::Attribute::value_str
1212
+ fn validate_and_find_value_str_builtin_attr (
1213
+ name : Symbol ,
1214
+ sess : & Session ,
1215
+ krate_attrs : & [ ast:: Attribute ] ,
1216
+ ) -> Option < ( Symbol , Span ) > {
1217
+ let mut result = None ;
1218
+ // Validate *all* relevant attributes, not just the first occurrence.
1219
+ for attr in ast:: attr:: filter_by_name ( krate_attrs, name) {
1220
+ let Some ( value) = attr. value_str ( ) else {
1221
+ validate_attr:: emit_fatal_malformed_builtin_attribute ( & sess. psess , attr, name)
1222
+ } ;
1223
+ // Choose the first occurrence as our result.
1224
+ result. get_or_insert ( ( value, attr. span ) ) ;
1225
+ }
1226
+ result
1227
+ }
0 commit comments