@@ -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