diff options
Diffstat (limited to 'compiler/rustc_interface')
| -rw-r--r-- | compiler/rustc_interface/Cargo.toml | 5 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 65 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 120 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/queries.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 144 |
7 files changed, 233 insertions, 141 deletions
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 07af2201f5f..e31119c1292 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -8,9 +8,10 @@ doctest = false [dependencies] libc = "0.2" +libloading = "0.7.1" tracing = "0.1" -rustc-rayon-core = "0.3.1" -rayon = { version = "0.3.1", package = "rustc-rayon" } +rustc-rayon-core = "0.3.2" +rayon = { version = "0.3.2", package = "rustc-rayon" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 7a6a643e3d0..26343561959 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -11,7 +11,7 @@ use rustc_errors::registry::Registry; use rustc_errors::{ErrorReported, Handler}; use rustc_lint::LintStore; use rustc_middle::ty; -use rustc_parse::new_parser_from_source_str; +use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; use rustc_session::early_error; @@ -36,6 +36,7 @@ pub struct Compiler { pub(crate) input_path: Option<PathBuf>, pub(crate) output_dir: Option<PathBuf>, pub(crate) output_file: Option<PathBuf>, + pub(crate) temps_dir: Option<PathBuf>, pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>, pub(crate) override_queries: Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>, @@ -57,6 +58,9 @@ impl Compiler { pub fn output_file(&self) -> &Option<PathBuf> { &self.output_file } + pub fn temps_dir(&self) -> &Option<PathBuf> { + &self.temps_dir + } pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> { &self.register_lints } @@ -65,7 +69,14 @@ impl Compiler { sess: &Session, attrs: &[ast::Attribute], ) -> OutputFilenames { - util::build_output_filenames(&self.input, &self.output_dir, &self.output_file, attrs, sess) + util::build_output_filenames( + &self.input, + &self.output_dir, + &self.output_file, + &self.temps_dir, + attrs, + sess, + ) } } @@ -80,7 +91,6 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String s ))); let filename = FileName::cfg_spec_source_code(&s); - let mut parser = new_parser_from_source_str(&sess, filename, s.to_string()); macro_rules! error { ($reason: expr) => { @@ -91,29 +101,39 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String }; } - match &mut parser.parse_meta_item() { - Ok(meta_item) if parser.token == token::Eof => { - if meta_item.path.segments.len() != 1 { - error!("argument key must be an identifier"); - } - match &meta_item.kind { - MetaItemKind::List(..) => { - error!(r#"expected `key` or `key="value"`"#); - } - MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { - error!("argument value must be a string"); + match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(mut parser) => match &mut parser.parse_meta_item() { + Ok(meta_item) if parser.token == token::Eof => { + if meta_item.path.segments.len() != 1 { + error!("argument key must be an identifier"); } - MetaItemKind::NameValue(..) | MetaItemKind::Word => { - let ident = meta_item.ident().expect("multi-segment cfg key"); - return (ident.name, meta_item.value_str()); + match &meta_item.kind { + MetaItemKind::List(..) => {} + MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { + error!("argument value must be a string"); + } + MetaItemKind::NameValue(..) | MetaItemKind::Word => { + let ident = meta_item.ident().expect("multi-segment cfg key"); + return (ident.name, meta_item.value_str()); + } } } - } - Ok(..) => {} - Err(err) => err.cancel(), + Ok(..) => {} + Err(err) => err.cancel(), + }, + Err(errs) => errs.into_iter().for_each(|mut err| err.cancel()), } - error!(r#"expected `key` or `key="value"`"#); + // If the user tried to use a key="value" flag, but is missing the quotes, provide + // a hint about how to resolve this. + if s.contains("=") && !s.contains("=\"") && !s.ends_with("\"") { + error!(concat!( + r#"expected `key` or `key="value"`, ensure escaping is appropriate"#, + r#" for your shell, try 'key="value"' or key=\"value\""# + )); + } else { + error!(r#"expected `key` or `key="value"`"#); + } }) .collect::<CrateConfig>(); cfg.into_iter().map(|(a, b)| (a.to_string(), b.map(|b| b.to_string()))).collect() @@ -186,6 +206,8 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R ); } + let temps_dir = sess.opts.debugging_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o)); + let compiler = Compiler { sess, codegen_backend, @@ -193,6 +215,7 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R input_path: config.input_path, output_dir: config.output_dir, output_file: config.output_file, + temps_dir, register_lints: config.register_lints, override_queries: config.override_queries, }; diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 2fc3759968f..b911b108a73 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,5 +1,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] +#![feature(let_else)] #![feature(internal_output_capture)] #![feature(thread_spawn_unchecked)] #![feature(nll)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 62f5f09aa48..be31eb89f1b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -10,17 +10,17 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{ErrorReported, PResult}; -use rustc_expand::base::ExtCtxt; +use rustc_errors::{Applicability, ErrorReported, PResult}; +use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; -use rustc_lint::LintStore; +use rustc_lint::{EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_metadata::{encode_metadata, EncodedMetadata}; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::query::{ExternProviders, Providers}; -use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; +use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, ResolverOutputs, TyCtxt}; use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; use rustc_passes::{self, hir_stats, layout_test}; @@ -34,8 +34,8 @@ use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; -use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::FileName; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{FileName, MultiSpan}; use rustc_trait_selection::traits; use rustc_typeck as typeck; use tempfile::Builder as TempFileBuilder; @@ -47,7 +47,7 @@ use std::ffi::OsString; use std::io::{self, BufWriter, Write}; use std::lazy::SyncLazy; use std::marker::PhantomPinned; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::pin::Pin; use std::rc::Rc; use std::{env, fs, iter}; @@ -233,26 +233,43 @@ pub fn register_plugins<'a>( Ok((krate, lint_store)) } -fn pre_expansion_lint( +fn pre_expansion_lint<'a>( sess: &Session, lint_store: &LintStore, - krate: &ast::Crate, - crate_attrs: &[ast::Attribute], - crate_name: &str, + registered_tools: &RegisteredTools, + check_node: impl EarlyCheckNode<'a>, + node_name: &str, ) { - sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", crate_name).run(|| { - rustc_lint::check_ast_crate( + sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| { + rustc_lint::check_ast_node( sess, - lint_store, - krate, - crate_attrs, true, + lint_store, + registered_tools, None, rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), + check_node, ); }); } +// Cannot implement directly for `LintStore` due to trait coherence. +struct LintStoreExpandImpl<'a>(&'a LintStore); + +impl LintStoreExpand for LintStoreExpandImpl<'_> { + fn pre_expansion_lint( + &self, + sess: &Session, + registered_tools: &RegisteredTools, + node_id: ast::NodeId, + attrs: &[ast::Attribute], + items: &[rustc_ast::ptr::P<ast::Item>], + name: &str, + ) { + pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name); + } +} + /// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the @@ -265,7 +282,7 @@ pub fn configure_and_expand( resolver: &mut Resolver<'_>, ) -> Result<ast::Crate> { tracing::trace!("configure_and_expand"); - pre_expansion_lint(sess, lint_store, &krate, &krate.attrs, crate_name); + pre_expansion_lint(sess, lint_store, resolver.registered_tools(), &krate, crate_name); rustc_builtin_macros::register_builtin_macros(resolver); krate = sess.time("crate_injection", || { @@ -321,13 +338,8 @@ pub fn configure_and_expand( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; - let crate_attrs = krate.attrs.clone(); - let extern_mod_loaded = |ident: Ident, attrs, items, span| { - let krate = ast::Crate { attrs, items, span }; - pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str()); - (krate.attrs, krate.items) - }; - let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&extern_mod_loaded)); + let lint_store = LintStoreExpandImpl(lint_store); + let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); @@ -450,6 +462,35 @@ pub fn configure_and_expand( }); } + // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. + sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { + let mut identifiers: Vec<_> = identifiers.drain().collect(); + identifiers.sort_by_key(|&(key, _)| key); + for (ident, mut spans) in identifiers.into_iter() { + spans.sort(); + if ident == sym::ferris { + let first_span = spans[0]; + sess.diagnostic() + .struct_span_err( + MultiSpan::from(spans), + "Ferris cannot be used as an identifier", + ) + .span_suggestion( + first_span, + "try using their name instead", + "ferris".to_string(), + Applicability::MaybeIncorrect, + ) + .emit(); + } else { + sess.diagnostic().span_err( + MultiSpan::from(spans), + &format!("identifiers cannot contain emoji: `{}`", ident), + ); + } + } + }); + Ok(krate) } @@ -470,14 +511,15 @@ pub fn lower_to_hir<'res, 'tcx>( ); sess.time("early_lint_checks", || { - rustc_lint::check_ast_crate( + let lint_buffer = Some(std::mem::take(resolver.lint_buffer())); + rustc_lint::check_ast_node( sess, - lint_store, - &krate, - &krate.attrs, false, - Some(std::mem::take(resolver.lint_buffer())), + lint_store, + resolver.registered_tools(), + lint_buffer, rustc_lint::BuiltinCombinedEarlyLintPass::new(), + &*krate, ) }); @@ -536,7 +578,7 @@ where None } -fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool { +fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool { let input_path = input_path.canonicalize().ok(); if input_path.is_none() { return false; @@ -552,10 +594,10 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> { check_output(output_paths, check) } -fn escape_dep_filename(filename: &String) -> String { +fn escape_dep_filename(filename: &str) -> String { // Apparently clang and gcc *only* escape spaces: // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 - filename.replace(" ", "\\ ") + filename.replace(' ', "\\ ") } // Makefile comments only need escaping newlines and `\`. @@ -602,7 +644,7 @@ fn write_out_deps( // (e.g. accessed in proc macros). let file_depinfo = sess.parse_sess.file_depinfo.borrow(); let extra_tracked_files = file_depinfo.iter().map(|path_sym| { - let path = PathBuf::from(&*path_sym.as_str()); + let path = PathBuf::from(path_sym.as_str()); let file = FileName::from(path); escape_dep_filename(&file.prefer_local().to_string()) }); @@ -692,6 +734,7 @@ pub fn prepare_outputs( &compiler.input, &compiler.output_dir, &compiler.output_file, + &compiler.temps_dir, &krate.attrs, sess, ); @@ -722,6 +765,13 @@ pub fn prepare_outputs( } } + if let Some(ref dir) = compiler.temps_dir { + if fs::create_dir_all(dir).is_err() { + sess.err("failed to find or create the directory specified by `--temps-dir`"); + return Err(ErrorReported); + } + } + write_out_deps(sess, boxed_resolver, &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) @@ -1012,8 +1062,8 @@ fn encode_and_write_metadata( let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); if need_metadata_file { - let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str(); - let out_filename = filename_for_metadata(tcx.sess, crate_name, outputs); + let crate_name = tcx.crate_name(LOCAL_CRATE); + let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index f188ad35605..e635ee1e0ec 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -335,8 +335,11 @@ pub struct Linker { impl Linker { pub fn link(self) -> Result<()> { - let (codegen_results, work_products) = - self.codegen_backend.join_codegen(self.ongoing_codegen, &self.sess)?; + let (codegen_results, work_products) = self.codegen_backend.join_codegen( + self.ongoing_codegen, + &self.sess, + &self.prepare_outputs, + )?; self.sess.compile_status()?; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2d3cb52f5fd..44acbd3cf21 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -8,10 +8,11 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate use rustc_session::config::{ rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes, }; -use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{ - Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel, + BranchProtection, Externs, OutputType, OutputTypes, PAuthKey, PacRet, SymbolManglingVersion, + WasiExecModel, }; +use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; @@ -20,7 +21,9 @@ use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}; -use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, TlsModel}; +use rustc_target::spec::{ + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, +}; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -551,6 +554,7 @@ fn test_codegen_options_tracking_hash() { untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")])); untracked!(rpath, true); untracked!(save_temps, true); + untracked!(strip, Strip::Debuginfo); macro_rules! tracked { ($name: ident, $non_default_value: expr) => { @@ -590,6 +594,7 @@ fn test_codegen_options_tracking_hash() { tracked!(relocation_model, Some(RelocModel::Pic)); tracked!(soft_float, true); tracked!(split_debuginfo, Some(SplitDebuginfo::Packed)); + tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); } @@ -635,11 +640,13 @@ fn test_debugging_options_tracking_hash() { // Make sure that changing an [UNTRACKED] option leaves the hash unchanged. // This list is in alphabetical order. + untracked!(assert_incr_state, Some(String::from("loaded"))); untracked!(ast_json, true); untracked!(ast_json_noexpand, true); untracked!(borrowck, String::from("other")); untracked!(deduplicate_diagnostics, false); untracked!(dep_tasks, true); + untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe"))); untracked!(dont_buffer_diagnostics, true); untracked!(dump_dep_graph, true); untracked!(dump_mir, Some(String::from("abc"))); @@ -647,7 +654,6 @@ fn test_debugging_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); - untracked!(emit_future_incompat_report, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); untracked!(hir_stats, true); @@ -672,7 +678,6 @@ fn test_debugging_options_tracking_hash() { // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(profile_closures, true); - untracked!(print_link_args, true); untracked!(print_llvm_passes, true); untracked!(print_mono_items, Some(String::from("abc"))); untracked!(print_type_sizes, true); @@ -684,7 +689,7 @@ fn test_debugging_options_tracking_hash() { untracked!(self_profile_events, Some(vec![String::new()])); untracked!(span_debug, true); untracked!(span_free_formats, true); - untracked!(strip, Strip::Debuginfo); + untracked!(temps_dir, Some(String::from("abc"))); untracked!(terminal_width, Some(80)); untracked!(threads, 99); untracked!(time, true); @@ -711,9 +716,13 @@ fn test_debugging_options_tracking_hash() { // This list is in alphabetical order. tracked!(allow_features, Some(vec![String::from("lang_items")])); tracked!(always_encode_mir, true); - tracked!(assume_incomplete_release, true); tracked!(asm_comments, true); + tracked!(assume_incomplete_release, true); tracked!(binary_dep_depinfo, true); + tracked!( + branch_protection, + BranchProtection { bti: true, pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B }) } + ); tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); @@ -722,15 +731,14 @@ fn test_debugging_options_tracking_hash() { tracked!(dep_info_omit_d_target, true); tracked!(dual_proc_macros, true); tracked!(fewer_names, Some(true)); - tracked!(force_overflow_checks, Some(true)); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); - tracked!(inline_mir_threshold, Some(123)); tracked!(inline_mir_hint_threshold, Some(123)); + tracked!(inline_mir_threshold, Some(123)); tracked!(instrument_coverage, Some(InstrumentCoverage::All)); tracked!(instrument_mcount, true); tracked!(link_only, true); @@ -750,6 +758,7 @@ fn test_debugging_options_tracking_hash() { tracked!(panic_abort_tests, true); tracked!(panic_in_drop, PanicStrategy::Abort); tracked!(partially_uninit_const_threshold, Some(123)); + tracked!(pick_stable_methods_before_any_unstable, false); tracked!(plt, Some(true)); tracked!(polonius, true); tracked!(precise_enum_drop_elaboration, false); @@ -761,7 +770,6 @@ fn test_debugging_options_tracking_hash() { tracked!(relax_elf_relocations, Some(true)); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); - tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(report_delayed_bugs, true); tracked!(sanitizer, SanitizerSet::ADDRESS); tracked!(sanitizer_memory_track_origins, 2); @@ -769,15 +777,17 @@ fn test_debugging_options_tracking_hash() { tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); + tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); + tracked!(stack_protector, StackProtector::All); tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(teach, true); tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); - tracked!(tune_cpu, Some(String::from("abc"))); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); + tracked!(tune_cpu, Some(String::from("abc"))); tracked!(unleash_the_miri_inside_of_you, true); tracked!(use_ctors_section, Some(true)); tracked!(verify_llvm_ir, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index cffb087af18..6d9183eda9d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,13 +1,13 @@ +use libloading::Library; use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AttrVec, BlockCheckMode}; +use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Term}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] use rustc_data_structures::jobserver; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; -use rustc_metadata::dynamic_lib::DynamicLibrary; #[cfg(parallel_compiler)] use rustc_middle::ty::tls; use rustc_parse::validate_attr; @@ -39,6 +39,9 @@ use std::sync::{Arc, Mutex}; use std::thread; use tracing::info; +/// Function pointer type that constructs a new CodegenBackend. +pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; + /// Adds `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). /// @@ -211,28 +214,24 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se }) } -fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> { - let lib = DynamicLibrary::open(path).unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); +fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { + let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { + let err = format!("couldn't load codegen backend {:?}: {}", path, err); early_error(ErrorOutputType::default(), &err); }); - unsafe { - match lib.symbol("__rustc_codegen_backend") { - Ok(f) => { - mem::forget(lib); - mem::transmute::<*mut u8, _>(f) - } - Err(e) => { - let err = format!( - "couldn't load codegen backend as it \ - doesn't export the `__rustc_codegen_backend` \ - symbol: {:?}", - e - ); - early_error(ErrorOutputType::default(), &err); - } - } - } + + let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") } + .unwrap_or_else(|e| { + let err = format!("couldn't load codegen backend: {}", e); + early_error(ErrorOutputType::default(), &err); + }); + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + let backend_sym = unsafe { backend_sym.into_raw() }; + mem::forget(lib); + + *backend_sym } /// Get the codegen backend based on the name and specified sysroot. @@ -380,10 +379,7 @@ fn sysroot_candidates() -> Vec<PathBuf> { } } -pub fn get_codegen_sysroot( - maybe_sysroot: &Option<PathBuf>, - backend_name: &str, -) -> fn() -> Box<dyn CodegenBackend> { +pub fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> MakeBackendFn { // For now we only allow this function to be called once as it'll dlopen a // few things, which seems to work best if we only do that once. In // general this assertion never trips due to the once guard in `get_codegen_backend`, @@ -488,7 +484,7 @@ pub(crate) fn check_attr_crate_type( return; } - if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { + if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() { let span = spanned.span; let lev_candidate = find_best_match_for_name( &CRATE_TYPES.iter().map(|(k, _)| *k).collect::<Vec<_>>(), @@ -604,6 +600,7 @@ pub fn build_output_filenames( input: &Input, odir: &Option<PathBuf>, ofile: &Option<PathBuf>, + temps_dir: &Option<PathBuf>, attrs: &[ast::Attribute], sess: &Session, ) -> OutputFilenames { @@ -626,6 +623,7 @@ pub fn build_output_filenames( dirpath, stem, None, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -654,6 +652,7 @@ pub fn build_output_filenames( out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(), out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(), ofile, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -718,52 +717,57 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { } fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool { - if let ast::FnRetTy::Ty(ref ty) = ret_ty { - fn involves_impl_trait(ty: &ast::Ty) -> bool { - match ty.kind { - ast::TyKind::ImplTrait(..) => true, - ast::TyKind::Slice(ref subty) - | ast::TyKind::Array(ref subty, _) - | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) - | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) - | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), - ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()), - ast::TyKind::Path(_, ref path) => { - path.segments.iter().any(|seg| match seg.args.as_deref() { - None => false, - Some(&ast::GenericArgs::AngleBracketed(ref data)) => { - data.args.iter().any(|arg| match arg { - ast::AngleBracketedArg::Arg(arg) => match arg { - ast::GenericArg::Type(ty) => involves_impl_trait(ty), - ast::GenericArg::Lifetime(_) - | ast::GenericArg::Const(_) => false, - }, - ast::AngleBracketedArg::Constraint(c) => match c.kind { - ast::AssocTyConstraintKind::Bound { .. } => true, - ast::AssocTyConstraintKind::Equality { ref ty } => { - involves_impl_trait(ty) + let ast::FnRetTy::Ty(ref ty) = ret_ty else { + return false; + }; + fn involves_impl_trait(ty: &ast::Ty) -> bool { + match ty.kind { + ast::TyKind::ImplTrait(..) => true, + ast::TyKind::Slice(ref subty) + | ast::TyKind::Array(ref subty, _) + | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) + | ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) + | ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), + ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()), + ast::TyKind::Path(_, ref path) => { + path.segments.iter().any(|seg| match seg.args.as_deref() { + None => false, + Some(&ast::GenericArgs::AngleBracketed(ref data)) => { + data.args.iter().any(|arg| match arg { + ast::AngleBracketedArg::Arg(arg) => match arg { + ast::GenericArg::Type(ty) => involves_impl_trait(ty), + ast::GenericArg::Lifetime(_) | ast::GenericArg::Const(_) => { + false + } + }, + ast::AngleBracketedArg::Constraint(c) => match c.kind { + ast::AssocConstraintKind::Bound { .. } => true, + ast::AssocConstraintKind::Equality { ref term } => { + match term { + Term::Ty(ty) => involves_impl_trait(ty), + // FIXME(...): This should check if the constant + // involves a trait impl, but for now ignore. + Term::Const(_) => false, } - }, - }) - } - Some(&ast::GenericArgs::Parenthesized(ref data)) => { - any_involves_impl_trait(data.inputs.iter()) - || ReplaceBodyWithLoop::should_ignore_fn(&data.output) - } - }) - } - _ => false, + } + }, + }) + } + Some(&ast::GenericArgs::Parenthesized(ref data)) => { + any_involves_impl_trait(data.inputs.iter()) + || ReplaceBodyWithLoop::should_ignore_fn(&data.output) + } + }) } + _ => false, } + } - fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool { - it.any(|subty| involves_impl_trait(subty)) - } - - involves_impl_trait(ty) - } else { - false + fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool { + it.any(|subty| involves_impl_trait(subty)) } + + involves_impl_trait(ty) } fn is_sig_const(sig: &ast::FnSig) -> bool { @@ -776,7 +780,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn visit_item_kind(&mut self, i: &mut ast::ItemKind) { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, - ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig), + ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_visit_item_kind(i, s)) @@ -785,7 +789,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) |
