diff options
Diffstat (limited to 'compiler/rustc_interface')
| -rw-r--r-- | compiler/rustc_interface/Cargo.toml | 1 | ||||
| -rw-r--r-- | compiler/rustc_interface/messages.ftl | 5 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/errors.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 154 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/util.rs | 38 | 
7 files changed, 120 insertions, 142 deletions
| diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index dcb9c5d22d6..295a988d2da 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # tidy-alphabetical-start rustc-rayon = { version = "0.5.0" } rustc-rayon-core = { version = "0.5.0" } +rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index 47dfbc1d7fb..31123625369 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -1,3 +1,8 @@ +interface_abi_required_feature = + target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly + .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +interface_abi_required_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344> + interface_cant_emit_mir = could not emit MIR: {$error} diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 939980a932f..b62950d6709 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -103,3 +103,12 @@ pub struct IgnoringOutDir; #[derive(Diagnostic)] #[diag(interface_multiple_output_types_to_stdout)] pub struct MultipleOutputTypesToStdout; + +#[derive(Diagnostic)] +#[diag(interface_abi_required_feature)] +#[note] +#[note(interface_abi_required_feature_issue)] +pub(crate) struct AbiRequiredTargetFeature<'a> { + pub feature: &'a str, + pub enabled: &'a str, +} diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 308d669cf35..b35703d8e73 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -7,7 +7,6 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::jobserver; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; @@ -309,6 +308,11 @@ pub struct Config { pub output_dir: Option<PathBuf>, pub output_file: Option<OutFileName>, pub ice_file: Option<PathBuf>, + /// Load files from sources other than the file system. + /// + /// Has no uses within this repository, but may be used in the future by + /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for + /// running rustc without having to save". (See #102759.) pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>, /// The list of fluent resources, used for lints declared with /// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic). @@ -337,6 +341,11 @@ pub struct Config { pub override_queries: Option<fn(&Session, &mut Providers)>, /// This is a callback from the driver that is called to create a codegen backend. + /// + /// Has no uses within this repository, but is used by bjorn3 for "the + /// hotswapping branch of cg_clif" for "setting the codegen backend from a + /// custom driver where the custom codegen backend has arbitrary data." + /// (See #102759.) pub make_codegen_backend: Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>, @@ -346,8 +355,7 @@ pub struct Config { /// The inner atomic value is set to true when a feature marked as `internal` is /// enabled. Makes it so that "please report a bug" is hidden, as ICEs with /// internal features are wontfix, and they are usually the cause of the ICEs. - /// None signifies that this is not tracked. - pub using_internal_features: Arc<std::sync::atomic::AtomicBool>, + pub using_internal_features: &'static std::sync::atomic::AtomicBool, /// All commandline args used to invoke the compiler, with @file args fully expanded. /// This will only be used within debug info, e.g. in the pdb file on windows @@ -434,7 +442,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se locale_resources.push(codegen_backend.locale_resource()); let mut sess = rustc_session::build_session( - early_dcx, config.opts, CompilerIO { input: config.input, @@ -482,7 +489,9 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se if let Some(register_lints) = config.register_lints.as_deref() { register_lints(&sess, &mut lint_store); } - sess.lint_store = Some(Lrc::new(lint_store)); + sess.lint_store = Some(Arc::new(lint_store)); + + util::check_abi_required_features(&sess); let compiler = Compiler { sess, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 241bc35857a..e5adcdb244f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -9,7 +9,7 @@ use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; use rustc_fs_util::try_canonicalize; @@ -26,7 +26,6 @@ use rustc_parse::{ }; use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_resolve::Resolver; -use rustc_session::code_stats::VTableSizeInfo; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name}; @@ -269,6 +268,7 @@ fn configure_and_expand( resolver.resolve_crate(&krate); + CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate); krate } @@ -602,7 +602,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) { +) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) { let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); @@ -624,7 +624,7 @@ fn resolver_for_lowering_raw<'tcx>( } = resolver.into_outputs(); let resolutions = tcx.arena.alloc(untracked_resolutions); - (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions) + (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Arc::new(krate)))), resolutions) } pub fn write_dep_info(tcx: TyCtxt<'_>) { @@ -827,26 +827,28 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { if tcx.sess.opts.unstable_opts.input_stats { rustc_passes::input_stats::print_hir_stats(tcx); } - #[cfg(debug_assertions)] + // When using rustdoc's "jump to def" feature, it enters this code and `check_crate` + // is not defined. So we need to cfg it out. + #[cfg(all(not(doc), debug_assertions))] rustc_passes::hir_id_validator::check_crate(tcx); let sess = tcx.sess; sess.time("misc_checking_1", || { parallel!( { - sess.time("looking_for_entry_point", || tcx.ensure().entry_fn(())); + sess.time("looking_for_entry_point", || tcx.ensure_ok().entry_fn(())); sess.time("looking_for_derive_registrar", || { - tcx.ensure().proc_macro_decls_static(()) + tcx.ensure_ok().proc_macro_decls_static(()) }); CStore::from_tcx(tcx).report_unused_deps(tcx); }, { tcx.hir().par_for_each_module(|module| { - tcx.ensure().check_mod_loops(module); - tcx.ensure().check_mod_attrs(module); - tcx.ensure().check_mod_naked_functions(module); - tcx.ensure().check_mod_unstable_api_usage(module); + tcx.ensure_ok().check_mod_loops(module); + tcx.ensure_ok().check_mod_attrs(module); + tcx.ensure_ok().check_mod_naked_functions(module); + tcx.ensure_ok().check_mod_unstable_api_usage(module); }); }, { @@ -859,8 +861,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // since they might not otherwise get called. // This marks the corresponding crate-level attributes // as used, and ensures that their values are valid. - tcx.ensure().limits(()); - tcx.ensure().stability_index(()); + tcx.ensure_ok().limits(()); + tcx.ensure_ok().stability_index(()); } ); }); @@ -869,7 +871,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { sess.time("MIR_coroutine_by_move_body", || { tcx.hir().par_body_owners(|def_id| { if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { - tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id); + tcx.ensure_done().coroutine_by_move_body_def_id(def_id); } }); }); @@ -884,13 +886,13 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.hir().par_body_owners(|def_id| { // Run unsafety check because it's responsible for stealing and // deallocating THIR. - tcx.ensure().check_unsafety(def_id); - tcx.ensure().mir_borrowck(def_id) + tcx.ensure_ok().check_unsafety(def_id); + tcx.ensure_ok().mir_borrowck(def_id) }); }); sess.time("MIR_effect_checking", || { tcx.hir().par_body_owners(|def_id| { - tcx.ensure().has_ffi_unwind_calls(def_id); + tcx.ensure_ok().has_ffi_unwind_calls(def_id); // If we need to codegen, ensure that we emit all errors from // `mir_drops_elaborated_and_const_checked` now, to avoid discovering @@ -898,17 +900,22 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { if tcx.sess.opts.output_types.should_codegen() || tcx.hir().body_const_context(def_id).is_some() { - tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); + tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } }); }); sess.time("coroutine_obligations", || { tcx.hir().par_body_owners(|def_id| { if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure().mir_coroutine_witnesses(def_id); - tcx.ensure().check_coroutine_obligations( + tcx.ensure_ok().mir_coroutine_witnesses(def_id); + tcx.ensure_ok().check_coroutine_obligations( tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), ); + // Eagerly check the unsubstituted layout for cycles. + tcx.ensure_ok().layout_of( + ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) + .as_query_input(tcx.type_of(def_id).instantiate_identity()), + ); } }); }); @@ -951,15 +958,16 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().effective_visibilities(()); + tcx.ensure_ok().effective_visibilities(()); parallel!( { - tcx.ensure().check_private_in_public(()); + tcx.ensure_ok().check_private_in_public(()); }, { - tcx.hir() - .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module)); + tcx.hir().par_for_each_module(|module| { + tcx.ensure_ok().check_mod_deathness(module) + }); }, { sess.time("lint_checking", || { @@ -967,14 +975,14 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { }); }, { - tcx.ensure().clashing_extern_declarations(()); + tcx.ensure_ok().clashing_extern_declarations(()); } ); }, { sess.time("privacy_checking_modules", || { tcx.hir().par_for_each_module(|module| { - tcx.ensure().check_mod_privacy(module); + tcx.ensure_ok().check_mod_privacy(module); }); }); } @@ -982,97 +990,13 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { // This check has to be run after all lints are done processing. We don't // define a lint filter, as all lint checks should have finished at this point. - sess.time("check_lint_expectations", || tcx.ensure().check_expectations(None)); + sess.time("check_lint_expectations", || tcx.ensure_ok().check_expectations(None)); // This query is only invoked normally if a diagnostic is emitted that needs any // diagnostic item. If the crate compiles without checking any diagnostic items, // we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally. let _ = tcx.all_diagnostic_items(()); }); - - if sess.opts.unstable_opts.print_vtable_sizes { - let traits = tcx.traits(LOCAL_CRATE); - - for &tr in traits { - if !tcx.is_dyn_compatible(tr) { - continue; - } - - let name = ty::print::with_no_trimmed_paths!(tcx.def_path_str(tr)); - - let mut first_dsa = true; - - // Number of vtable entries, if we didn't have upcasting - let mut entries_ignoring_upcasting = 0; - // Number of vtable entries needed solely for upcasting - let mut entries_for_upcasting = 0; - - let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr)); - - // A slightly edited version of the code in - // `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self - // type and just counts number of entries. - // - // Note that this is technically wrong, for traits which have associated types in - // supertraits: - // - // trait A: AsRef<Self::T> + AsRef<()> { type T; } - // - // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>` - // and `AsRef<()>` are the same trait, thus we assume that those are different, and - // potentially over-estimate how many vtable entries there are. - // - // Similarly this is wrong for traits that have methods with possibly-impossible bounds. - // For example: - // - // trait B<T> { fn f(&self) where T: Copy; } - // - // Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3. - // However, since we don't know `T`, we can't know if `T: Copy` holds or not, - // thus we lean on the bigger side and say it has 4 entries. - traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| { - match segment { - traits::vtable::VtblSegment::MetadataDSA => { - // If this is the first dsa, it would be included either way, - // otherwise it's needed for upcasting - if std::mem::take(&mut first_dsa) { - entries_ignoring_upcasting += 3; - } else { - entries_for_upcasting += 3; - } - } - - traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - // Lookup the shape of vtable for the trait. - let own_existential_entries = - tcx.own_existential_vtable_entries(trait_ref.def_id()); - - // The original code here ignores the method if its predicates are - // impossible. We can't really do that as, for example, all not trivial - // bounds on generic parameters are impossible (since we don't know the - // parameters...), see the comment above. - entries_ignoring_upcasting += own_existential_entries.len(); - - if emit_vptr { - entries_for_upcasting += 1; - } - } - } - - std::ops::ControlFlow::Continue::<std::convert::Infallible>(()) - }); - - sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo { - trait_name: name.clone(), - entries: entries_ignoring_upcasting + entries_for_upcasting, - entries_ignoring_upcasting, - entries_for_upcasting, - upcasting_cost_percent: entries_for_upcasting as f64 - / entries_ignoring_upcasting as f64 - * 100., - }) - } - } } /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used @@ -1091,7 +1015,7 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { ) }) => { - tcx.ensure().trigger_delayed_bug(def_id); + tcx.ensure_ok().trigger_delayed_bug(def_id); } // Bare `#[rustc_error]`. @@ -1153,12 +1077,6 @@ pub(crate) fn start_codegen<'tcx>( tcx.sess.code_stats.print_type_sizes(); } - if tcx.sess.opts.unstable_opts.print_vtable_sizes { - let crate_name = tcx.crate_name(LOCAL_CRATE); - - tcx.sess.code_stats.print_vtable_sizes(crate_name); - } - codegen } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index d7370c1ff53..233bfcb5297 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -2,18 +2,19 @@ use std::collections::{BTreeMap, BTreeSet}; use std::num::NonZero; use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::sync::atomic::AtomicBool; +use rustc_abi::Align; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, registry}; use rustc_session::config::{ - BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, - FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, - LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, - OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, - PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, + AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, + CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, + Externs, FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, + InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, + NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, + Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, build_configuration, build_session_options, rustc_optgroups, }; @@ -24,7 +25,6 @@ use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, filesearc use rustc_span::edition::{DEFAULT_EDITION, Edition}; use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::{FileName, SourceFileHashAlgorithm, sym}; -use rustc_target::abi::Align; use rustc_target::spec::{ CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, WasmCAbi, @@ -62,8 +62,9 @@ where temps_dir, }; + static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false); + let sess = build_session( - early_dcx, sessopts, io, None, @@ -74,7 +75,7 @@ where sysroot, "", None, - Arc::default(), + &USING_INTERNAL_FEATURES, Default::default(), ); let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg")); @@ -758,6 +759,7 @@ fn test_unstable_options_tracking_hash() { tracked!(allow_features, Some(vec![String::from("lang_items")])); tracked!(always_encode_mir, true); tracked!(assume_incomplete_release, true); + tracked!(autodiff, vec![AutoDiff::Print]); tracked!(binary_dep_depinfo, true); tracked!(box_noalias, false); tracked!( @@ -768,11 +770,14 @@ fn test_unstable_options_tracking_hash() { }) ); tracked!(codegen_backend, Some("abc".to_string())); - tracked!(coverage_options, CoverageOptions { - level: CoverageLevel::Mcdc, - no_mir_spans: true, - discard_all_spans_in_codegen: true - }); + tracked!( + coverage_options, + CoverageOptions { + level: CoverageLevel::Mcdc, + no_mir_spans: true, + discard_all_spans_in_codegen: true + } + ); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); @@ -795,7 +800,6 @@ fn test_unstable_options_tracking_hash() { tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(incremental_ignore_spans, true); - tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); tracked!(inline_mir_hint_threshold, Some(123)); tracked!(inline_mir_threshold, Some(123)); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 984b8104f53..e900ec14fca 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -18,21 +18,25 @@ use rustc_session::{EarlyDiagCtxt, Session, filesearch}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; -use rustc_span::sym; +use rustc_span::{Symbol, sym}; use rustc_target::spec::Target; use tracing::info; use crate::errors; /// Function pointer type that constructs a new CodegenBackend. -pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; +type MakeBackendFn = fn() -> Box<dyn CodegenBackend>; /// Adds `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). /// /// This is performed by checking whether a set of permitted features /// is available on the target machine, by querying the codegen backend. -pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) { +pub(crate) fn add_configuration( + cfg: &mut Cfg, + sess: &mut Session, + codegen_backend: &dyn CodegenBackend, +) { let tf = sym::target_feature; let unstable_target_features = codegen_backend.target_features_cfg(sess, true); @@ -48,6 +52,34 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy } } +/// Ensures that all target features required by the ABI are present. +/// Must be called after `unstable_target_features` has been populated! +pub(crate) fn check_abi_required_features(sess: &Session) { + let abi_feature_constraints = sess.target.abi_required_features(); + // We check this against `unstable_target_features` as that is conveniently already + // back-translated to rustc feature names, taking into account `-Ctarget-cpu` and `-Ctarget-feature`. + // Just double-check that the features we care about are actually on our list. + for feature in + abi_feature_constraints.required.iter().chain(abi_feature_constraints.incompatible.iter()) + { + assert!( + sess.target.rust_target_features().iter().any(|(name, ..)| feature == name), + "target feature {feature} is required/incompatible for the current ABI but not a recognized feature for this target" + ); + } + + for feature in abi_feature_constraints.required { + if !sess.unstable_target_features.contains(&Symbol::intern(feature)) { + sess.dcx().emit_warn(errors::AbiRequiredTargetFeature { feature, enabled: "enabled" }); + } + } + for feature in abi_feature_constraints.incompatible { + if sess.unstable_target_features.contains(&Symbol::intern(feature)) { + sess.dcx().emit_warn(errors::AbiRequiredTargetFeature { feature, enabled: "disabled" }); + } + } +} + pub static STACK_SIZE: OnceLock<usize> = OnceLock::new(); pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024; | 
