@@ -28,10 +28,12 @@ use rustc_passes::{abi_test, input_stats, layout_test};
2828use  rustc_resolve:: Resolver ; 
2929use  rustc_session:: config:: { CrateType ,  Input ,  OutFileName ,  OutputFilenames ,  OutputType } ; 
3030use  rustc_session:: cstore:: Untracked ; 
31- use  rustc_session:: output:: { collect_crate_types,  filename_for_input,  find_crate_name } ; 
31+ use  rustc_session:: output:: { collect_crate_types,  filename_for_input} ; 
3232use  rustc_session:: search_paths:: PathKind ; 
3333use  rustc_session:: { Limit ,  Session } ; 
34- use  rustc_span:: { ErrorGuaranteed ,  FileName ,  SourceFileHash ,  SourceFileHashAlgorithm ,  Symbol ,  sym} ; 
34+ use  rustc_span:: { 
35+     ErrorGuaranteed ,  FileName ,  SourceFileHash ,  SourceFileHashAlgorithm ,  Span ,  Symbol ,  sym, 
36+ } ; 
3537use  rustc_target:: spec:: PanicStrategy ; 
3638use  rustc_trait_selection:: traits; 
3739use  tracing:: { info,  instrument} ; 
@@ -725,8 +727,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
725727
726728    let  pre_configured_attrs = rustc_expand:: config:: pre_configure_attrs ( sess,  & krate. attrs ) ; 
727729
728-     // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. 
729-     let  crate_name = find_crate_name ( sess,  & pre_configured_attrs) ; 
730+     let  crate_name = get_crate_name ( sess,  & pre_configured_attrs) ; 
730731    let  crate_types = collect_crate_types ( sess,  & pre_configured_attrs) ; 
731732    let  stable_crate_id = StableCrateId :: new ( 
732733        crate_name, 
@@ -735,7 +736,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
735736        sess. cfg_version , 
736737    ) ; 
737738    let  outputs = util:: build_output_filenames ( & pre_configured_attrs,  sess) ; 
738-     let  dep_graph = setup_dep_graph ( sess) ; 
739+     let  dep_graph = setup_dep_graph ( sess,  crate_name ) ; 
739740
740741    let  cstore =
741742        FreezeLock :: new ( Box :: new ( CStore :: new ( compiler. codegen_backend . metadata_loader ( ) ) )  as  _ ) ; 
@@ -1080,23 +1081,85 @@ pub(crate) fn start_codegen<'tcx>(
10801081    codegen
10811082} 
10821083
1083- fn  get_recursion_limit ( krate_attrs :  & [ ast:: Attribute ] ,  sess :  & Session )  -> Limit  { 
1084-     if  let  Some ( attr)  = krate_attrs
1085-         . iter ( ) 
1086-         . find ( |attr| attr. has_name ( sym:: recursion_limit)  && attr. value_str ( ) . is_none ( ) ) 
1084+ /// Compute and validate the crate name. 
1085+ pub  fn  get_crate_name ( sess :  & Session ,  krate_attrs :  & [ ast:: Attribute ] )  -> Symbol  { 
1086+     // We validate *all* occurrences of `#![crate_name]`, pick the first find and 
1087+     // if a crate name was passed on the command line via `--crate-name` we enforce 
1088+     // that they match. 
1089+     // We perform the validation step here instead of later to ensure it gets run 
1090+     // in all code paths that require the crate name very early on, namely before 
1091+     // macro expansion. 
1092+ 
1093+     let  attr_crate_name =
1094+         validate_and_find_value_str_builtin_attr ( sym:: crate_name,  sess,  krate_attrs) ; 
1095+ 
1096+     let  validate = |name,  span| { 
1097+         rustc_session:: output:: validate_crate_name ( sess,  name,  span) ; 
1098+         name
1099+     } ; 
1100+ 
1101+     if  let  Some ( crate_name)  = & sess. opts . crate_name  { 
1102+         let  crate_name = Symbol :: intern ( crate_name) ; 
1103+         if  let  Some ( ( attr_crate_name,  span) )  = attr_crate_name
1104+             && attr_crate_name != crate_name
1105+         { 
1106+             sess. dcx ( ) . emit_err ( errors:: CrateNameDoesNotMatch  { 
1107+                 span, 
1108+                 crate_name, 
1109+                 attr_crate_name, 
1110+             } ) ; 
1111+         } 
1112+         return  validate ( crate_name,  None ) ; 
1113+     } 
1114+ 
1115+     if  let  Some ( ( crate_name,  span) )  = attr_crate_name { 
1116+         return  validate ( crate_name,  Some ( span) ) ; 
1117+     } 
1118+ 
1119+     if  let  Input :: File ( ref  path)  = sess. io . input 
1120+         && let  Some ( file_stem)  = path. file_stem ( ) . and_then ( |s| s. to_str ( ) ) 
10871121    { 
1088-         // This is here mainly to check for using a macro, such as 
1089-         // #![recursion_limit = foo!()]. That is not supported since that 
1090-         // would require expanding this while in the middle of expansion, 
1091-         // which needs to know the limit before expanding. Otherwise, 
1092-         // validation would normally be caught in AstValidator (via 
1093-         // `check_builtin_attribute`), but by the time that runs the macro 
1094-         // is expanded, and it doesn't give an error. 
1095-         validate_attr:: emit_fatal_malformed_builtin_attribute ( 
1096-             & sess. psess , 
1097-             attr, 
1098-             sym:: recursion_limit, 
1099-         ) ; 
1122+         if  file_stem. starts_with ( '-' )  { 
1123+             sess. dcx ( ) . emit_err ( errors:: CrateNameInvalid  {  crate_name :  file_stem } ) ; 
1124+         }  else  { 
1125+             return  validate ( Symbol :: intern ( & file_stem. replace ( '-' ,  "_" ) ) ,  None ) ; 
1126+         } 
11001127    } 
1128+ 
1129+     sym:: rust_out
1130+ } 
1131+ 
1132+ fn  get_recursion_limit ( krate_attrs :  & [ ast:: Attribute ] ,  sess :  & Session )  -> Limit  { 
1133+     // We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`]) 
1134+     // because that would require expanding this while in the middle of expansion, which needs to 
1135+     // know the limit before expanding. 
1136+     let  _ = validate_and_find_value_str_builtin_attr ( sym:: recursion_limit,  sess,  krate_attrs) ; 
11011137    rustc_middle:: middle:: limits:: get_recursion_limit ( krate_attrs,  sess) 
11021138} 
1139+ 
1140+ /// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find. 
1141+ /// 
1142+ /// This validator is intended for built-in attributes whose value needs to be known very early 
1143+ /// during compilation (namely, before macro expansion) and it mainly exists to reject macro calls 
1144+ /// inside of the attributes, such as in `#![name = expand!()]`. Normal attribute validation happens 
1145+ /// during semantic analysis via [`TyCtxt::check_mod_attrs`] which happens *after* macro expansion 
1146+ /// when such macro calls (here: `expand`) have already been expanded and we can no longer check for 
1147+ /// their presence. 
1148+ /// 
1149+ /// [value-str]: ast::Attribute::value_str 
1150+ fn  validate_and_find_value_str_builtin_attr ( 
1151+     name :  Symbol , 
1152+     sess :  & Session , 
1153+     krate_attrs :  & [ ast:: Attribute ] , 
1154+ )  -> Option < ( Symbol ,  Span ) >  { 
1155+     let  mut  result = None ; 
1156+     // Validate *all* relevant attributes, not just the first occurrence. 
1157+     for  attr in  ast:: attr:: filter_by_name ( krate_attrs,  name)  { 
1158+         let  Some ( value)  = attr. value_str ( )  else  { 
1159+             validate_attr:: emit_fatal_malformed_builtin_attribute ( & sess. psess ,  attr,  name) 
1160+         } ; 
1161+         // Choose the first occurrence as our result. 
1162+         result. get_or_insert ( ( value,  attr. span ) ) ; 
1163+     } 
1164+     result
1165+ } 
0 commit comments