Auto merge of #126834 - bjorn3:interface_refactor, r=michaelwoerister

Various refactorings to rustc_interface

This should make it easier to move the driver interface away from queries in the future. Many custom drivers call queries like `queries.global_ctxt()` before they are supposed to be called, breaking some things like certain `--print` and `-Zunpretty` options, `-Zparse-only` and emitting the dep info at the wrong point in time. They are also not actually necessary at all. Passing around the query output manually would avoid recomputation too and would be just as easy. Removing driver queries would also reduce the amount of global mutable state of the compiler. I'm not removing driver queries in this PR to avoid breaking the aforementioned custom drivers.
This commit is contained in:
bors 2024-06-25 09:35:53 +00:00
commit c2d2bb38c9
8 changed files with 163 additions and 183 deletions

View File

@ -30,7 +30,7 @@ use rustc_errors::{
}; };
use rustc_feature::find_gated_cfg; use rustc_feature::find_gated_cfg;
use rustc_interface::util::{self, get_codegen_backend}; use rustc_interface::util::{self, get_codegen_backend};
use rustc_interface::{interface, Queries}; use rustc_interface::{interface, passes, Queries};
use rustc_lint::unerased_lint_store; use rustc_lint::unerased_lint_store;
use rustc_metadata::creader::MetadataLoader; use rustc_metadata::creader::MetadataLoader;
use rustc_metadata::locator; use rustc_metadata::locator;
@ -367,18 +367,17 @@ fn run_compiler(
return early_exit(); return early_exit();
} }
let early_dcx = EarlyDiagCtxt::new(sess.opts.error_format); if print_crate_info(codegen_backend, sess, has_input) == Compilation::Stop {
if print_crate_info(&early_dcx, codegen_backend, sess, has_input) == Compilation::Stop {
return early_exit(); return early_exit();
} }
if !has_input { if !has_input {
early_dcx.early_fatal("no input filename given"); // this is fatal #[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal("no input filename given"); // this is fatal
} }
if !sess.opts.unstable_opts.ls.is_empty() { if !sess.opts.unstable_opts.ls.is_empty() {
list_metadata(&early_dcx, sess, &*codegen_backend.metadata_loader()); list_metadata(sess, &*codegen_backend.metadata_loader());
return early_exit(); return early_exit();
} }
@ -399,7 +398,9 @@ fn run_compiler(
Ok(()) Ok(())
})?; })?;
queries.write_dep_info()?; queries.global_ctxt()?.enter(|tcx| {
passes::write_dep_info(tcx);
});
} else { } else {
let krate = queries.parse()?; let krate = queries.parse()?;
pretty::print( pretty::print(
@ -427,7 +428,9 @@ fn run_compiler(
return early_exit(); return early_exit();
} }
queries.write_dep_info()?; queries.global_ctxt()?.enter(|tcx| {
passes::write_dep_info(tcx);
});
if sess.opts.output_types.contains_key(&OutputType::DepInfo) if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1 && sess.opts.output_types.len() == 1
@ -670,7 +673,7 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
} }
} }
fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dyn MetadataLoader) { fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) {
match sess.io.input { match sess.io.input {
Input::File(ref ifile) => { Input::File(ref ifile) => {
let path = &(*ifile); let path = &(*ifile);
@ -687,13 +690,13 @@ fn list_metadata(early_dcx: &EarlyDiagCtxt, sess: &Session, metadata_loader: &dy
safe_println!("{}", String::from_utf8(v).unwrap()); safe_println!("{}", String::from_utf8(v).unwrap());
} }
Input::Str { .. } => { Input::Str { .. } => {
early_dcx.early_fatal("cannot list metadata for stdin"); #[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal("cannot list metadata for stdin");
} }
} }
} }
fn print_crate_info( fn print_crate_info(
early_dcx: &EarlyDiagCtxt,
codegen_backend: &dyn CodegenBackend, codegen_backend: &dyn CodegenBackend,
sess: &Session, sess: &Session,
parse_attrs: bool, parse_attrs: bool,
@ -877,8 +880,8 @@ fn print_crate_info(
.expect("unknown Apple target OS"); .expect("unknown Apple target OS");
println_info!("deployment_target={}", format!("{major}.{minor}")) println_info!("deployment_target={}", format!("{major}.{minor}"))
} else { } else {
early_dcx #[allow(rustc::diagnostic_outside_of_impl)]
.early_fatal("only Apple targets currently support deployment version info") sess.dcx().fatal("only Apple targets currently support deployment version info")
} }
} }
} }

View File

@ -495,9 +495,8 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
let res = { let res = {
// If `f` panics, `finish_diagnostics` will run during // If `f` panics, `finish_diagnostics` will run during
// unwinding because of the `defer`. // unwinding because of the `defer`.
let mut guar = None;
let sess_abort_guard = defer(|| { let sess_abort_guard = defer(|| {
guar = compiler.sess.finish_diagnostics(&config.registry); compiler.sess.finish_diagnostics(&config.registry);
}); });
let res = f(&compiler); let res = f(&compiler);
@ -506,16 +505,14 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
// normally when `sess_abort_guard` is dropped. // normally when `sess_abort_guard` is dropped.
drop(sess_abort_guard); drop(sess_abort_guard);
// If `finish_diagnostics` emits errors (e.g. stashed // If error diagnostics have been emitted, we can't return an
// errors) we can't return an error directly, because the // error directly, because the return type of this function
// return type of this function is `R`, not `Result<R, E>`. // is `R`, not `Result<R, E>`. But we need to communicate the
// But we need to communicate the errors' existence to the // errors' existence to the caller, otherwise the caller might
// caller, otherwise the caller might mistakenly think that // mistakenly think that no errors occurred and return a zero
// no errors occurred and return a zero exit code. So we // exit code. So we abort (panic) instead, similar to if `f`
// abort (panic) instead, similar to if `f` had panicked. // had panicked.
if guar.is_some() {
compiler.sess.dcx().abort_if_errors(); compiler.sess.dcx().abort_if_errors();
}
res res
}; };

View File

@ -8,7 +8,7 @@
mod callbacks; mod callbacks;
mod errors; mod errors;
pub mod interface; pub mod interface;
mod passes; pub mod passes;
mod proc_macro_decls; mod proc_macro_decls;
mod queries; mod queries;
pub mod util; pub mod util;

View File

@ -7,16 +7,16 @@ use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel; use rustc_data_structures::parallel;
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{Lrc, OnceLock, WorkerLocal}; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
use rustc_errors::PResult;
use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_feature::Features; use rustc_feature::Features;
use rustc_fs_util::try_canonicalize; use rustc_fs_util::try_canonicalize;
use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore; use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena; use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers; use rustc_middle::util::Providers;
use rustc_parse::{ use rustc_parse::{
@ -28,6 +28,7 @@ use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked; use rustc_session::cstore::Untracked;
use rustc_session::output::filename_for_input; use rustc_session::output::filename_for_input;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::search_paths::PathKind; use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session}; use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
@ -39,12 +40,13 @@ use std::any::Any;
use std::ffi::OsString; use std::ffi::OsString;
use std::io::{self, BufWriter, Write}; use std::io::{self, BufWriter, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock; use std::sync::{Arc, LazyLock};
use std::{env, fs, iter}; use std::{env, fs, iter};
use tracing::{info, instrument}; use tracing::{info, instrument};
pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
let krate = sess.time("parse_crate", || { let krate = sess
.time("parse_crate", || {
let mut parser = unwrap_or_emit_fatal(match &sess.io.input { let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
Input::File(file) => new_parser_from_file(&sess.psess, file, None), Input::File(file) => new_parser_from_file(&sess.psess, file, None),
Input::Str { input, name } => { Input::Str { input, name } => {
@ -52,7 +54,8 @@ pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
} }
}); });
parser.parse_crate_mod() parser.parse_crate_mod()
})?; })
.map_err(|parse_error| parse_error.emit())?;
if sess.opts.unstable_opts.input_stats { if sess.opts.unstable_opts.input_stats {
eprintln!("Lines of code: {}", sess.source_map().count_lines()); eprintln!("Lines of code: {}", sess.source_map().count_lines());
@ -559,7 +562,7 @@ fn resolver_for_lowering_raw<'tcx>(
(tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions) (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions)
} }
pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) { pub fn write_dep_info(tcx: TyCtxt<'_>) {
// Make sure name resolution and macro expansion is run for // Make sure name resolution and macro expansion is run for
// the side-effect of providing a complete set of all // the side-effect of providing a complete set of all
// accessed files and env vars. // accessed files and env vars.
@ -640,22 +643,48 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
*providers *providers
}); });
pub fn create_global_ctxt<'tcx>( pub(crate) fn create_global_ctxt<'tcx>(
compiler: &'tcx Compiler, compiler: &'tcx Compiler,
crate_types: Vec<CrateType>, mut krate: rustc_ast::Crate,
stable_crate_id: StableCrateId,
dep_graph: DepGraph,
untracked: Untracked,
gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>, gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
arena: &'tcx WorkerLocal<Arena<'tcx>>, arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
) -> &'tcx GlobalCtxt<'tcx> { ) -> Result<&'tcx GlobalCtxt<'tcx>> {
let sess = &compiler.sess;
rustc_builtin_macros::cmdline_attrs::inject(
&mut krate,
&sess.psess,
&sess.opts.unstable_opts.crate_attr,
);
let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
let stable_crate_id = StableCrateId::new(
crate_name,
crate_types.contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess)?;
let cstore =
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
let untracked =
Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions, stable_crate_ids };
// We're constructing the HIR here; we don't care what we will // We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to // read, since we haven't even constructed the *input* to
// incr. comp. yet. // incr. comp. yet.
dep_graph.assert_ignored(); dep_graph.assert_ignored();
let sess = &compiler.sess;
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
let codegen_backend = &compiler.codegen_backend; let codegen_backend = &compiler.codegen_backend;
@ -669,7 +698,7 @@ pub fn create_global_ctxt<'tcx>(
let incremental = dep_graph.is_fully_enabled(); let incremental = dep_graph.is_fully_enabled();
sess.time("setup_global_ctxt", || { sess.time("setup_global_ctxt", || {
gcx_cell.get_or_init(move || { let qcx = gcx_cell.get_or_init(move || {
TyCtxt::create_global_ctxt( TyCtxt::create_global_ctxt(
sess, sess,
crate_types, crate_types,
@ -688,7 +717,23 @@ pub fn create_global_ctxt<'tcx>(
providers.hooks, providers.hooks,
compiler.current_gcx.clone(), compiler.current_gcx.clone(),
) )
}) });
qcx.enter(|tcx| {
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
assert_eq!(feed.key(), LOCAL_CRATE);
feed.crate_name(crate_name);
let feed = tcx.feed_unit_query();
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
sess,
&pre_configured_attrs,
crate_name,
)));
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
feed.output_filenames(Arc::new(outputs));
});
Ok(qcx)
}) })
} }
@ -924,12 +969,56 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
Ok(()) Ok(())
} }
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
/// to write UI tests that actually test that compilation succeeds without reporting
/// an error.
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
match attr.meta_item_list() {
// Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
Some(list)
if list.iter().any(|list_item| {
matches!(
list_item.ident().map(|i| i.name),
Some(sym::delayed_bug_from_inside_query)
)
}) =>
{
tcx.ensure().trigger_delayed_bug(def_id);
}
// Bare `#[rustc_error]`.
None => {
tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) });
}
// Some other attribute.
Some(_) => {
tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation {
span: tcx.def_span(def_id),
});
}
}
}
}
/// Runs the codegen backend, after which the AST and analysis can /// Runs the codegen backend, after which the AST and analysis can
/// be discarded. /// be discarded.
pub fn start_codegen<'tcx>( pub(crate) fn start_codegen<'tcx>(
codegen_backend: &dyn CodegenBackend, codegen_backend: &dyn CodegenBackend,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
) -> Box<dyn Any> { ) -> Result<Box<dyn Any>> {
// Don't do code generation if there were any errors. Likewise if
// there were any delayed bugs, because codegen will likely cause
// more ICEs, obscuring the original problem.
if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() {
return Err(guar);
}
// Hook for UI tests.
check_for_rustc_errors_attr(tcx);
info!("Pre-codegen\n{:?}", tcx.debug_stats()); info!("Pre-codegen\n{:?}", tcx.debug_stats());
let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx); let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
@ -952,7 +1041,7 @@ pub fn start_codegen<'tcx>(
} }
} }
codegen Ok(codegen)
} }
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit { fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {

View File

@ -1,26 +1,20 @@
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation}; use crate::errors::FailedWritingFile;
use crate::interface::{Compiler, Result}; use crate::interface::{Compiler, Result};
use crate::{errors, passes, util}; use crate::{errors, passes};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults; use rustc_codegen_ssa::CodegenResults;
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; use rustc_data_structures::sync::{OnceLock, WorkerLocal};
use rustc_hir::def_id::{StableCrateId, StableCrateIdMap, LOCAL_CRATE}; use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena; use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph; use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_middle::ty::{GlobalCtxt, TyCtxt};
use rustc_serialize::opaque::FileEncodeResult; use rustc_serialize::opaque::FileEncodeResult;
use rustc_session::config::{self, CrateType, OutputFilenames, OutputType}; use rustc_session::config::{self, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::sym;
use std::any::Any; use std::any::Any;
use std::cell::{RefCell, RefMut}; use std::cell::{RefCell, RefMut};
use std::sync::Arc; use std::sync::Arc;
@ -106,133 +100,26 @@ impl<'tcx> Queries<'tcx> {
} }
pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> { pub fn parse(&self) -> Result<QueryResult<'_, ast::Crate>> {
self.parse.compute(|| { self.parse.compute(|| passes::parse(&self.compiler.sess))
passes::parse(&self.compiler.sess).map_err(|parse_error| parse_error.emit())
})
} }
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
self.gcx.compute(|| { self.gcx.compute(|| {
let sess = &self.compiler.sess; let krate = self.parse()?.steal();
let mut krate = self.parse()?.steal(); passes::create_global_ctxt(
rustc_builtin_macros::cmdline_attrs::inject(
&mut krate,
&sess.psess,
&sess.opts.unstable_opts.crate_attr,
);
let pre_configured_attrs =
rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
let stable_crate_id = StableCrateId::new(
crate_name,
crate_types.contains(&CrateType::Executable),
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess)?;
let cstore = FreezeLock::new(Box::new(CStore::new(
self.compiler.codegen_backend.metadata_loader(),
)) as _);
let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
let untracked = Untracked {
cstore,
source_span: AppendOnlyIndexVec::new(),
definitions,
stable_crate_ids,
};
let qcx = passes::create_global_ctxt(
self.compiler, self.compiler,
crate_types, krate,
stable_crate_id,
dep_graph,
untracked,
&self.gcx_cell, &self.gcx_cell,
&self.arena, &self.arena,
&self.hir_arena, &self.hir_arena,
);
qcx.enter(|tcx| {
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
assert_eq!(feed.key(), LOCAL_CRATE);
feed.crate_name(crate_name);
let feed = tcx.feed_unit_query();
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
sess,
&pre_configured_attrs,
crate_name,
)));
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
feed.output_filenames(Arc::new(outputs));
});
Ok(qcx)
})
}
pub fn write_dep_info(&'tcx self) -> Result<()> {
self.global_ctxt()?.enter(|tcx| {
passes::write_dep_info(tcx);
});
Ok(())
}
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
/// to write UI tests that actually test that compilation succeeds without reporting
/// an error.
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
match attr.meta_item_list() {
// Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`.
Some(list)
if list.iter().any(|list_item| {
matches!(
list_item.ident().map(|i| i.name),
Some(sym::delayed_bug_from_inside_query)
) )
}) => })
{
tcx.ensure().trigger_delayed_bug(def_id);
}
// Bare `#[rustc_error]`.
None => {
tcx.dcx().emit_fatal(RustcErrorFatal { span: tcx.def_span(def_id) });
}
// Some other attribute.
Some(_) => {
tcx.dcx()
.emit_warn(RustcErrorUnexpectedAnnotation { span: tcx.def_span(def_id) });
}
}
}
} }
pub fn codegen_and_build_linker(&'tcx self) -> Result<Linker> { pub fn codegen_and_build_linker(&'tcx self) -> Result<Linker> {
self.global_ctxt()?.enter(|tcx| { self.global_ctxt()?.enter(|tcx| {
// Don't do code generation if there were any errors. Likewise if let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx)?;
// there were any delayed bugs, because codegen will likely cause
// more ICEs, obscuring the original problem.
if let Some(guar) = self.compiler.sess.dcx().has_errors_or_delayed_bugs() {
return Err(guar);
}
// Hook for UI tests.
Self::check_for_rustc_errors_attr(tcx);
let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx);
Ok(Linker { Ok(Linker {
dep_graph: tcx.dep_graph.clone(), dep_graph: tcx.dep_graph.clone(),

View File

@ -4,3 +4,5 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--
error: no input filename given error: no input filename given
error: aborting due to 1 previous error

View File

@ -1,9 +1,9 @@
use run_make_support::rustc; use run_make_support::rustc;
fn main() { fn main() {
rustc() rustc().print("crate-name").run_fail().assert_exit_code(1).assert_stderr_equals(
.print("crate-name") "error: no input filename given
.run_fail()
.assert_exit_code(1) error: aborting due to 1 previous error",
.assert_stderr_equals("error: no input filename given"); );
} }

View File

@ -1,2 +1,4 @@
error: only Apple targets currently support deployment version info error: only Apple targets currently support deployment version info
error: aborting due to 1 previous error