@@ -7,16 +7,16 @@ use rustc_ast::{self as ast, visit};
77use rustc_codegen_ssa:: traits:: CodegenBackend ;
88use rustc_data_structures:: parallel;
99use rustc_data_structures:: steal:: Steal ;
10- use rustc_data_structures:: sync:: { Lrc , OnceLock , WorkerLocal } ;
11- use rustc_errors:: PResult ;
10+ use rustc_data_structures:: sync:: { AppendOnlyIndexVec , FreezeLock , Lrc , OnceLock , WorkerLocal } ;
1211use rustc_expand:: base:: { ExtCtxt , LintStoreExpand } ;
1312use rustc_feature:: Features ;
1413use rustc_fs_util:: try_canonicalize;
15- use rustc_hir:: def_id:: { StableCrateId , LOCAL_CRATE } ;
14+ use rustc_hir:: def_id:: { StableCrateId , StableCrateIdMap , LOCAL_CRATE } ;
15+ use rustc_hir:: definitions:: Definitions ;
16+ use rustc_incremental:: setup_dep_graph;
1617use rustc_lint:: { unerased_lint_store, BufferedEarlyLint , EarlyCheckNode , LintStore } ;
1718use rustc_metadata:: creader:: CStore ;
1819use rustc_middle:: arena:: Arena ;
19- use rustc_middle:: dep_graph:: DepGraph ;
2020use rustc_middle:: ty:: { self , GlobalCtxt , RegisteredTools , TyCtxt } ;
2121use rustc_middle:: util:: Providers ;
2222use rustc_parse:: {
@@ -28,6 +28,7 @@ use rustc_session::code_stats::VTableSizeInfo;
2828use rustc_session:: config:: { CrateType , Input , OutFileName , OutputFilenames , OutputType } ;
2929use rustc_session:: cstore:: Untracked ;
3030use rustc_session:: output:: filename_for_input;
31+ use rustc_session:: output:: { collect_crate_types, find_crate_name} ;
3132use rustc_session:: search_paths:: PathKind ;
3233use rustc_session:: { Limit , Session } ;
3334use rustc_span:: symbol:: { sym, Symbol } ;
@@ -39,20 +40,22 @@ use std::any::Any;
3940use std:: ffi:: OsString ;
4041use std:: io:: { self , BufWriter , Write } ;
4142use std:: path:: { Path , PathBuf } ;
42- use std:: sync:: LazyLock ;
43+ use std:: sync:: { Arc , LazyLock } ;
4344use std:: { env, fs, iter} ;
4445use tracing:: { info, instrument} ;
4546
46- pub fn parse < ' a > ( sess : & ' a Session ) -> PResult < ' a , ast:: Crate > {
47- let krate = sess. time ( "parse_crate" , || {
48- let mut parser = unwrap_or_emit_fatal ( match & sess. io . input {
49- Input :: File ( file) => new_parser_from_file ( & sess. psess , file, None ) ,
50- Input :: Str { input, name } => {
51- new_parser_from_source_str ( & sess. psess , name. clone ( ) , input. clone ( ) )
52- }
53- } ) ;
54- parser. parse_crate_mod ( )
55- } ) ?;
47+ pub ( crate ) fn parse < ' a > ( sess : & ' a Session ) -> Result < ast:: Crate > {
48+ let krate = sess
49+ . time ( "parse_crate" , || {
50+ let mut parser = unwrap_or_emit_fatal ( match & sess. io . input {
51+ Input :: File ( file) => new_parser_from_file ( & sess. psess , file, None ) ,
52+ Input :: Str { input, name } => {
53+ new_parser_from_source_str ( & sess. psess , name. clone ( ) , input. clone ( ) )
54+ }
55+ } ) ;
56+ parser. parse_crate_mod ( )
57+ } )
58+ . map_err ( |parse_error| parse_error. emit ( ) ) ?;
5659
5760 if sess. opts . unstable_opts . input_stats {
5861 eprintln ! ( "Lines of code: {}" , sess. source_map( ) . count_lines( ) ) ;
@@ -559,7 +562,7 @@ fn resolver_for_lowering_raw<'tcx>(
559562 ( tcx. arena . alloc ( Steal :: new ( ( untracked_resolver_for_lowering, Lrc :: new ( krate) ) ) ) , resolutions)
560563}
561564
562- pub ( crate ) fn write_dep_info ( tcx : TyCtxt < ' _ > ) {
565+ pub fn write_dep_info ( tcx : TyCtxt < ' _ > ) {
563566 // Make sure name resolution and macro expansion is run for
564567 // the side-effect of providing a complete set of all
565568 // accessed files and env vars.
@@ -640,22 +643,48 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
640643 * providers
641644} ) ;
642645
643- pub fn create_global_ctxt < ' tcx > (
646+ pub ( crate ) fn create_global_ctxt < ' tcx > (
644647 compiler : & ' tcx Compiler ,
645- crate_types : Vec < CrateType > ,
646- stable_crate_id : StableCrateId ,
647- dep_graph : DepGraph ,
648- untracked : Untracked ,
648+ mut krate : rustc_ast:: Crate ,
649649 gcx_cell : & ' tcx OnceLock < GlobalCtxt < ' tcx > > ,
650650 arena : & ' tcx WorkerLocal < Arena < ' tcx > > ,
651651 hir_arena : & ' tcx WorkerLocal < rustc_hir:: Arena < ' tcx > > ,
652- ) -> & ' tcx GlobalCtxt < ' tcx > {
652+ ) -> Result < & ' tcx GlobalCtxt < ' tcx > > {
653+ let sess = & compiler. sess ;
654+
655+ rustc_builtin_macros:: cmdline_attrs:: inject (
656+ & mut krate,
657+ & sess. psess ,
658+ & sess. opts . unstable_opts . crate_attr ,
659+ ) ;
660+
661+ let pre_configured_attrs = rustc_expand:: config:: pre_configure_attrs ( sess, & krate. attrs ) ;
662+
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) ;
665+ let crate_types = collect_crate_types ( sess, & pre_configured_attrs) ;
666+ let stable_crate_id = StableCrateId :: new (
667+ crate_name,
668+ crate_types. contains ( & CrateType :: Executable ) ,
669+ sess. opts . cg . metadata . clone ( ) ,
670+ sess. cfg_version ,
671+ ) ;
672+ let outputs = util:: build_output_filenames ( & pre_configured_attrs, sess) ;
673+ let dep_graph = setup_dep_graph ( sess) ?;
674+
675+ let cstore =
676+ FreezeLock :: new ( Box :: new ( CStore :: new ( compiler. codegen_backend . metadata_loader ( ) ) ) as _ ) ;
677+ let definitions = FreezeLock :: new ( Definitions :: new ( stable_crate_id) ) ;
678+
679+ let stable_crate_ids = FreezeLock :: new ( StableCrateIdMap :: default ( ) ) ;
680+ let untracked =
681+ Untracked { cstore, source_span : AppendOnlyIndexVec :: new ( ) , definitions, stable_crate_ids } ;
682+
653683 // We're constructing the HIR here; we don't care what we will
654684 // read, since we haven't even constructed the *input* to
655685 // incr. comp. yet.
656686 dep_graph. assert_ignored ( ) ;
657687
658- let sess = & compiler. sess ;
659688 let query_result_on_disk_cache = rustc_incremental:: load_query_result_cache ( sess) ;
660689
661690 let codegen_backend = & compiler. codegen_backend ;
@@ -669,7 +698,7 @@ pub fn create_global_ctxt<'tcx>(
669698 let incremental = dep_graph. is_fully_enabled ( ) ;
670699
671700 sess. time ( "setup_global_ctxt" , || {
672- gcx_cell. get_or_init ( move || {
701+ let qcx = gcx_cell. get_or_init ( move || {
673702 TyCtxt :: create_global_ctxt (
674703 sess,
675704 crate_types,
@@ -688,7 +717,23 @@ pub fn create_global_ctxt<'tcx>(
688717 providers. hooks ,
689718 compiler. current_gcx . clone ( ) ,
690719 )
691- } )
720+ } ) ;
721+
722+ qcx. enter ( |tcx| {
723+ let feed = tcx. create_crate_num ( stable_crate_id) . unwrap ( ) ;
724+ assert_eq ! ( feed. key( ) , LOCAL_CRATE ) ;
725+ feed. crate_name ( crate_name) ;
726+
727+ let feed = tcx. feed_unit_query ( ) ;
728+ feed. features_query ( tcx. arena . alloc ( rustc_expand:: config:: features (
729+ sess,
730+ & pre_configured_attrs,
731+ crate_name,
732+ ) ) ) ;
733+ feed. crate_for_resolver ( tcx. arena . alloc ( Steal :: new ( ( krate, pre_configured_attrs) ) ) ) ;
734+ feed. output_filenames ( Arc :: new ( outputs) ) ;
735+ } ) ;
736+ Ok ( qcx)
692737 } )
693738}
694739
@@ -924,12 +969,56 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
924969 Ok ( ( ) )
925970}
926971
972+ /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
973+ /// to write UI tests that actually test that compilation succeeds without reporting
974+ /// an error.
975+ fn check_for_rustc_errors_attr ( tcx : TyCtxt < ' _ > ) {
976+ let Some ( ( def_id, _) ) = tcx. entry_fn ( ( ) ) else { return } ;
977+ for attr in tcx. get_attrs ( def_id, sym:: rustc_error) {
978+ match attr. meta_item_list ( ) {
979+ // Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
980+ Some ( list)
981+ if list. iter ( ) . any ( |list_item| {
982+ matches ! (
983+ list_item. ident( ) . map( |i| i. name) ,
984+ Some ( sym:: delayed_bug_from_inside_query)
985+ )
986+ } ) =>
987+ {
988+ tcx. ensure ( ) . trigger_delayed_bug ( def_id) ;
989+ }
990+
991+ // Bare `#[rustc_error]`.
992+ None => {
993+ tcx. dcx ( ) . emit_fatal ( errors:: RustcErrorFatal { span : tcx. def_span ( def_id) } ) ;
994+ }
995+
996+ // Some other attribute.
997+ Some ( _) => {
998+ tcx. dcx ( ) . emit_warn ( errors:: RustcErrorUnexpectedAnnotation {
999+ span : tcx. def_span ( def_id) ,
1000+ } ) ;
1001+ }
1002+ }
1003+ }
1004+ }
1005+
9271006/// Runs the codegen backend, after which the AST and analysis can
9281007/// be discarded.
929- pub fn start_codegen < ' tcx > (
1008+ pub ( crate ) fn start_codegen < ' tcx > (
9301009 codegen_backend : & dyn CodegenBackend ,
9311010 tcx : TyCtxt < ' tcx > ,
932- ) -> Box < dyn Any > {
1011+ ) -> Result < Box < dyn Any > > {
1012+ // Don't do code generation if there were any errors. Likewise if
1013+ // there were any delayed bugs, because codegen will likely cause
1014+ // more ICEs, obscuring the original problem.
1015+ if let Some ( guar) = tcx. sess . dcx ( ) . has_errors_or_delayed_bugs ( ) {
1016+ return Err ( guar) ;
1017+ }
1018+
1019+ // Hook for UI tests.
1020+ check_for_rustc_errors_attr ( tcx) ;
1021+
9331022 info ! ( "Pre-codegen\n {:?}" , tcx. debug_stats( ) ) ;
9341023
9351024 let ( metadata, need_metadata_module) = rustc_metadata:: fs:: encode_and_write_metadata ( tcx) ;
@@ -952,7 +1041,7 @@ pub fn start_codegen<'tcx>(
9521041 }
9531042 }
9541043
955- codegen
1044+ Ok ( codegen)
9561045}
9571046
9581047fn get_recursion_limit ( krate_attrs : & [ ast:: Attribute ] , sess : & Session ) -> Limit {
0 commit comments