@@ -27,12 +27,12 @@ use rustc_resolve::Resolver;
2727use rustc_session:: code_stats:: VTableSizeInfo ;
2828use rustc_session:: config:: { CrateType , Input , OutFileName , OutputFilenames , OutputType } ;
2929use rustc_session:: cstore:: Untracked ;
30+ use rustc_session:: output:: collect_crate_types;
3031use rustc_session:: output:: filename_for_input;
31- use rustc_session:: output:: { collect_crate_types, find_crate_name} ;
3232use rustc_session:: search_paths:: PathKind ;
3333use rustc_session:: { Limit , Session } ;
34- use rustc_span:: symbol:: { sym, Symbol } ;
3534use rustc_span:: FileName ;
35+ use rustc_span:: { sym, Span , Symbol } ;
3636use rustc_target:: spec:: PanicStrategy ;
3737use rustc_trait_selection:: traits;
3838
@@ -660,8 +660,7 @@ pub(crate) fn create_global_ctxt<'tcx>(
660660
661661 let pre_configured_attrs = rustc_expand:: config:: pre_configure_attrs ( sess, & krate. attrs ) ;
662662
663- // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
664- let crate_name = find_crate_name ( sess, & pre_configured_attrs) ;
663+ let crate_name = get_crate_name ( sess, & pre_configured_attrs) ;
665664 let crate_types = collect_crate_types ( sess, & pre_configured_attrs) ;
666665 let stable_crate_id = StableCrateId :: new (
667666 crate_name,
@@ -670,7 +669,7 @@ pub(crate) fn create_global_ctxt<'tcx>(
670669 sess. cfg_version ,
671670 ) ;
672671 let outputs = util:: build_output_filenames ( & pre_configured_attrs, sess) ;
673- let dep_graph = setup_dep_graph ( sess) ?;
672+ let dep_graph = setup_dep_graph ( sess, crate_name ) ?;
674673
675674 let cstore =
676675 FreezeLock :: new ( Box :: new ( CStore :: new ( compiler. codegen_backend . metadata_loader ( ) ) ) as _ ) ;
@@ -1044,23 +1043,83 @@ pub(crate) fn start_codegen<'tcx>(
10441043 Ok ( codegen)
10451044}
10461045
1047- fn get_recursion_limit ( krate_attrs : & [ ast:: Attribute ] , sess : & Session ) -> Limit {
1048- if let Some ( attr) = krate_attrs
1049- . iter ( )
1050- . find ( |attr| attr. has_name ( sym:: recursion_limit) && attr. value_str ( ) . is_none ( ) )
1046+ /// Compute and validate the crate name.
1047+ pub fn get_crate_name ( sess : & Session , krate_attrs : & [ ast:: Attribute ] ) -> Symbol {
1048+ // We unconditionally validate all `#![crate_name]`s even if a crate name was
1049+ // set on the command line via `--crate-name` which we prioritize over the
1050+ // crate attributes. We perform the validation here instead of later to ensure
1051+ // it gets run in all code paths requiring the crate name very early on.
1052+ // Namely, print requests (`--print`).
1053+ let attr_crate_name =
1054+ validate_and_find_value_str_builtin_attr ( sym:: crate_name, sess, krate_attrs) ;
1055+
1056+ let validate = |name, span| {
1057+ rustc_session:: output:: validate_crate_name ( sess, name, span) ;
1058+ name
1059+ } ;
1060+
1061+ if let Some ( crate_name) = & sess. opts . crate_name {
1062+ let crate_name = Symbol :: intern ( crate_name) ;
1063+ if let Some ( ( attr_crate_name, span) ) = attr_crate_name
1064+ && attr_crate_name != crate_name
1065+ {
1066+ sess. dcx ( ) . emit_err ( errors:: CrateNameDoesNotMatch {
1067+ span,
1068+ crate_name,
1069+ attr_crate_name,
1070+ } ) ;
1071+ }
1072+ return validate ( crate_name, None ) ;
1073+ }
1074+
1075+ if let Some ( ( crate_name, span) ) = attr_crate_name {
1076+ return validate ( crate_name, Some ( span) ) ;
1077+ }
1078+
1079+ if let Input :: File ( ref path) = sess. io . input
1080+ && let Some ( file_stem) = path. file_stem ( ) . and_then ( |s| s. to_str ( ) )
10511081 {
1052- // This is here mainly to check for using a macro, such as
1053- // #![recursion_limit = foo!()]. That is not supported since that
1054- // would require expanding this while in the middle of expansion,
1055- // which needs to know the limit before expanding. Otherwise,
1056- // validation would normally be caught in AstValidator (via
1057- // `check_builtin_attribute`), but by the time that runs the macro
1058- // is expanded, and it doesn't give an error.
1059- validate_attr:: emit_fatal_malformed_builtin_attribute (
1060- & sess. psess ,
1061- attr,
1062- sym:: recursion_limit,
1063- ) ;
1082+ if file_stem. starts_with ( '-' ) {
1083+ sess. dcx ( ) . emit_err ( errors:: CrateNameInvalid { crate_name : file_stem } ) ;
1084+ } else {
1085+ return validate ( Symbol :: intern ( & file_stem. replace ( '-' , "_" ) ) , None ) ;
1086+ }
10641087 }
1088+
1089+ Symbol :: intern ( "rust_out" )
1090+ }
1091+
1092+ fn get_recursion_limit ( krate_attrs : & [ ast:: Attribute ] , sess : & Session ) -> Limit {
1093+ // We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
1094+ // because that would require expanding this while in the middle of expansion, which needs to
1095+ // know the limit before expanding.
1096+ let _ = validate_and_find_value_str_builtin_attr ( sym:: recursion_limit, sess, krate_attrs) ;
10651097 rustc_middle:: middle:: limits:: get_recursion_limit ( krate_attrs, sess)
10661098}
1099+
1100+ /// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find.
1101+ ///
1102+ /// This validator is intended for built-in attributes whose value needs to be known very early
1103+ /// during compilation (namely, before macro expansion) and it mainly exists to reject macro calls
1104+ /// inside of the attributes, such as in `#![name = expand!()]`. Normal attribute validation happens
1105+ /// during semantic analysis via [`TyCtxt::check_mod_attrs`] which happens *after* macro expansion
1106+ /// when such macro calls (here: `expand`) have already been expanded and we can no longer check for
1107+ /// their presence.
1108+ ///
1109+ /// [value-str]: ast::Attribute::value_str
1110+ fn validate_and_find_value_str_builtin_attr (
1111+ name : Symbol ,
1112+ sess : & Session ,
1113+ krate_attrs : & [ ast:: Attribute ] ,
1114+ ) -> Option < ( Symbol , Span ) > {
1115+ let mut result = None ;
1116+ // Validate *all* relevant attributes, not just the first occurrence.
1117+ for attr in ast:: attr:: filter_by_name ( krate_attrs, name) {
1118+ let Some ( value) = attr. value_str ( ) else {
1119+ validate_attr:: emit_fatal_malformed_builtin_attribute ( & sess. psess , attr, name)
1120+ } ;
1121+ // Choose the first occurrence as our result.
1122+ result. get_or_insert ( ( value, attr. span ) ) ;
1123+ }
1124+ result
1125+ }
0 commit comments