diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index ee5895a6efd0f..c0db5b4d442a9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -94,12 +94,12 @@ impl NoArgsAttributeParser for DenyExplicitImplParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl; } -pub(crate) struct DoNotImplementViaObjectParser; -impl NoArgsAttributeParser for DoNotImplementViaObjectParser { - const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object]; +pub(crate) struct DynIncompatibleTraitParser; +impl NoArgsAttributeParser for DynIncompatibleTraitParser { + const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::DynIncompatibleTrait; } // Specialization diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index fa0162861abcc..614619bca3ec2 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -90,8 +90,8 @@ use crate::attributes::test_attrs::{ }; use crate::attributes::traits::{ AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser, - DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser, - PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser, + DynIncompatibleTraitParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser, + SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser, UnsafeSpecializationMarkerParser, }; use crate::attributes::transparency::TransparencyParser; @@ -255,7 +255,7 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs index 840f51c0685d7..c93a2e8f8da52 100644 --- a/compiler/rustc_codegen_gcc/src/back/lto.rs +++ b/compiler/rustc_codegen_gcc/src/back/lto.rs @@ -26,11 +26,11 @@ use std::sync::atomic::Ordering; use gccjit::{Context, OutputKind}; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput}; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; use rustc_data_structures::memmap::Mmap; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; @@ -112,10 +112,11 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// for further optimization. pub(crate) fn run_fat( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); /*let symbols_below_threshold = @@ -283,14 +284,13 @@ impl ModuleBufferMethods for ModuleBuffer { /// can simply be copied over from the incr. comp. cache. pub(crate) fn run_thin( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - let dcx = cgcx.create_dcx(); - let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); - if cgcx.opts.cg.linker_plugin_lto.enabled() { + if cgcx.use_linker_plugin_lto { unreachable!( "We should never reach this case if the LTO step \ is deferred to the linker" @@ -522,8 +522,6 @@ pub fn optimize_thin_module( thin_module: ThinModule, _cgcx: &CodegenContext, ) -> ModuleCodegen { - //let dcx = cgcx.create_dcx(); - //let module_name = &thin_module.shared.module_names[thin_module.idx]; /*let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap()); let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&dcx, e))?;*/ diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index eae0f2aa00f6a..b6223c5be370a 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -2,8 +2,11 @@ use std::{env, fs}; use gccjit::{Context, OutputKind}; use rustc_codegen_ssa::back::link::ensure_removed; -use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; +use rustc_codegen_ssa::back::write::{ + BitcodeSection, CodegenContext, EmitObj, ModuleConfig, SharedEmitter, +}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_errors::DiagCtxt; use rustc_fs_util::link_or_copy; use rustc_log::tracing::debug; use rustc_session::config::OutputType; @@ -15,10 +18,11 @@ use crate::{GccCodegenBackend, GccContext, LtoMode}; pub(crate) fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index cf1be18062355..00bea0222622a 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -84,7 +84,7 @@ use gccjit::{TargetInfo, Version}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, }; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; @@ -435,23 +435,25 @@ impl WriteBackendMethods for GccCodegenBackend { fn run_and_optimize_fat_lto( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - back::lto::run_fat(cgcx, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, Self::ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - back::lto::run_thin(cgcx, each_linked_rlib_for_lto, modules, cached_modules) + back::lto::run_thin(cgcx, dcx, each_linked_rlib_for_lto, modules, cached_modules) } fn print_pass_timings(&self) { @@ -464,7 +466,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize( _cgcx: &CodegenContext, - _dcx: DiagCtxtHandle<'_>, + _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { @@ -473,6 +475,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize_thin( cgcx: &CodegenContext, + _shared_emitter: &SharedEmitter, thin: ThinModule, ) -> ModuleCodegen { back::lto::optimize_thin_module(thin, cgcx) @@ -480,10 +483,11 @@ impl WriteBackendMethods for GccCodegenBackend { fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - back::write::codegen(cgcx, module, config) + back::write::codegen(cgcx, shared_emitter, module, config) } fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 52c2ca7b1696b..71327ed6d2d16 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -9,12 +9,12 @@ use std::{io, iter, slice}; use object::read::archive::ArchiveFile; use object::{Object, ObjectSection}; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput}; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_hir::attrs::SanitizerSet; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; @@ -150,17 +150,18 @@ fn get_bitcode_slice_from_object_data<'a>( /// for further optimization. pub(crate) fn run_fat( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx); let symbols_below_threshold = symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>(); - fat_lto(cgcx, dcx, modules, upstream_modules, &symbols_below_threshold) + fat_lto(cgcx, dcx, shared_emitter, modules, upstream_modules, &symbols_below_threshold) } /// Performs thin LTO by performing necessary global analysis and returning two @@ -168,18 +169,17 @@ pub(crate) fn run_fat( /// can simply be copied over from the incr. comp. cache. pub(crate) fn run_thin( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - let dcx = cgcx.create_dcx(); - let dcx = dcx.handle(); let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx); let symbols_below_threshold = symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>(); - if cgcx.opts.cg.linker_plugin_lto.enabled() { + if cgcx.use_linker_plugin_lto { unreachable!( "We should never reach this case if the LTO step \ is deferred to the linker" @@ -197,6 +197,7 @@ pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBu fn fat_lto( cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>, + shared_emitter: &SharedEmitter, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, symbols_below_threshold: &[*const libc::c_char], @@ -265,8 +266,13 @@ fn fat_lto( // The linking steps below may produce errors and diagnostics within LLVM // which we'd like to handle and print, so set up our diagnostic handlers // (which get unregistered when they go out of scope below). - let _handler = - DiagnosticHandlers::new(cgcx, dcx, llcx, &module, CodegenDiagnosticsStage::LTO); + let _handler = DiagnosticHandlers::new( + cgcx, + shared_emitter, + llcx, + &module, + CodegenDiagnosticsStage::LTO, + ); // For all other modules we codegened we'll need to link them into our own // bitcode. All modules were codegened in their own LLVM context, however, @@ -720,10 +726,11 @@ impl Drop for ThinBuffer { } pub(crate) fn optimize_thin_module( - thin_module: ThinModule, cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, + thin_module: ThinModule, ) -> ModuleCodegen { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let module_name = &thin_module.shared.module_names[thin_module.idx]; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 09d1ca1a59522..e66a4ab6b37b3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -9,7 +9,7 @@ use libc::{c_char, c_int, c_void, size_t}; use rustc_codegen_ssa::back::link::ensure_removed; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::back::write::{ - BitcodeSection, CodegenContext, EmitObj, InlineAsmError, ModuleConfig, + BitcodeSection, CodegenContext, EmitObj, InlineAsmError, ModuleConfig, SharedEmitter, TargetMachineFactoryConfig, TargetMachineFactoryFn, }; use rustc_codegen_ssa::base::wants_wasm_eh; @@ -18,7 +18,7 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{DiagCtxtHandle, Level}; +use rustc_errors::{DiagCtxt, DiagCtxtHandle, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -356,7 +356,7 @@ pub(crate) enum CodegenDiagnosticsStage { } pub(crate) struct DiagnosticHandlers<'a> { - data: *mut (&'a CodegenContext, DiagCtxtHandle<'a>), + data: *mut (&'a CodegenContext, &'a SharedEmitter), llcx: &'a llvm::Context, old_handler: Option<&'a llvm::DiagnosticHandler>, } @@ -364,7 +364,7 @@ pub(crate) struct DiagnosticHandlers<'a> { impl<'a> DiagnosticHandlers<'a> { pub(crate) fn new( cgcx: &'a CodegenContext, - dcx: DiagCtxtHandle<'a>, + shared_emitter: &'a SharedEmitter, llcx: &'a llvm::Context, module: &ModuleCodegen, stage: CodegenDiagnosticsStage, @@ -398,8 +398,8 @@ impl<'a> DiagnosticHandlers<'a> { }) .and_then(|dir| dir.to_str().and_then(|p| CString::new(p).ok())); - let pgo_available = cgcx.opts.cg.profile_use.is_some(); - let data = Box::into_raw(Box::new((cgcx, dcx))); + let pgo_available = cgcx.module_config.pgo_use.is_some(); + let data = Box::into_raw(Box::new((cgcx, shared_emitter))); unsafe { let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx); llvm::LLVMRustContextConfigureDiagnosticHandler( @@ -461,12 +461,16 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void if user.is_null() { return; } - let (cgcx, dcx) = - unsafe { *(user as *const (&CodegenContext, DiagCtxtHandle<'_>)) }; + let (cgcx, shared_emitter) = + unsafe { *(user as *const (&CodegenContext, &SharedEmitter)) }; + + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); + let dcx = dcx.handle(); match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } { llvm::diagnostic::InlineAsm(inline) => { - cgcx.diag_emitter.inline_asm_error(report_inline_asm( + // FIXME use dcx + shared_emitter.inline_asm_error(report_inline_asm( cgcx, inline.message, inline.level, @@ -776,7 +780,7 @@ pub(crate) unsafe fn llvm_optimize( &*module.module_llvm.tm.raw(), to_pass_builder_opt_level(opt_level), opt_stage, - cgcx.opts.cg.linker_plugin_lto.enabled(), + cgcx.use_linker_plugin_lto, config.no_prepopulate_passes, config.verify_llvm_ir, config.lint_llvm_ir, @@ -887,14 +891,18 @@ pub(crate) unsafe fn llvm_optimize( // Unsafe due to LLVM calls. pub(crate) fn optimize( cgcx: &CodegenContext, - dcx: DiagCtxtHandle<'_>, + shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); + let dcx = dcx.handle(); + let llcx = &*module.module_llvm.llcx; - let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt); + let _handlers = + DiagnosticHandlers::new(cgcx, shared_emitter, llcx, module, CodegenDiagnosticsStage::Opt); if config.emit_no_opt_bc { let out = cgcx.output_filenames.temp_path_ext_for_cgu( @@ -911,7 +919,7 @@ pub(crate) fn optimize( let opt_stage = match cgcx.lto { Lto::Fat => llvm::OptStage::PreLinkFatLTO, Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, - _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, + _ if cgcx.use_linker_plugin_lto => llvm::OptStage::PreLinkThinLTO, _ => llvm::OptStage::PreLinkNoLTO, }; @@ -974,19 +982,26 @@ pub(crate) fn optimize( pub(crate) fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - let dcx = cgcx.create_dcx(); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); + + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); { let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; let tm = &*module.module_llvm.tm; - let _handlers = - DiagnosticHandlers::new(cgcx, dcx, llcx, &module, CodegenDiagnosticsStage::Codegen); + let _handlers = DiagnosticHandlers::new( + cgcx, + shared_emitter, + llcx, + &module, + CodegenDiagnosticsStage::Codegen, + ); if cgcx.msvc_imps_needed { create_msvc_imps(cgcx, llcx, llmod); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index e0007f69828dc..5879132eb9fbd 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -30,12 +30,13 @@ use llvm_util::target_config; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryConfig, + TargetMachineFactoryFn, }; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; @@ -166,14 +167,20 @@ impl WriteBackendMethods for LlvmCodegenBackend { } fn run_and_optimize_fat_lto( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - let mut module = - back::lto::run_fat(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, modules); + let mut module = back::lto::run_fat( + cgcx, + shared_emitter, + exported_symbols_for_lto, + each_linked_rlib_for_lto, + modules, + ); - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); back::lto::run_pass_manager(cgcx, dcx, &mut module, false); @@ -181,6 +188,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { } fn run_thin_lto( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, Self::ThinBuffer)>, @@ -188,6 +196,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { ) -> (Vec>, Vec) { back::lto::run_thin( cgcx, + dcx, exported_symbols_for_lto, each_linked_rlib_for_lto, modules, @@ -196,24 +205,26 @@ impl WriteBackendMethods for LlvmCodegenBackend { } fn optimize( cgcx: &CodegenContext, - dcx: DiagCtxtHandle<'_>, + shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { - back::write::optimize(cgcx, dcx, module, config) + back::write::optimize(cgcx, shared_emitter, module, config) } fn optimize_thin( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, thin: ThinModule, ) -> ModuleCodegen { - back::lto::optimize_thin_module(thin, cgcx) + back::lto::optimize_thin_module(cgcx, shared_emitter, thin) } fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - back::write::codegen(cgcx, module, config) + back::write::codegen(cgcx, shared_emitter, module, config) } fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { back::lto::prepare_thin(module) diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index e6df6a2469f37..ef4c193c4c2a1 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::sync::Arc; use rustc_data_structures::memmap::Mmap; +use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportLevel}; use rustc_middle::ty::TyCtxt; @@ -124,28 +125,29 @@ pub(super) fn exported_symbols_for_lto( symbols_below_threshold } -pub(super) fn check_lto_allowed(cgcx: &CodegenContext) { +pub(super) fn check_lto_allowed( + cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, +) { if cgcx.lto == Lto::ThinLocal { // Crate local LTO is always allowed return; } - let dcx = cgcx.create_dcx(); - // Make sure we actually can run LTO for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { dcx.handle().emit_fatal(LtoDisallowed); } else if *crate_type == CrateType::Dylib { - if !cgcx.opts.unstable_opts.dylib_lto { + if !cgcx.dylib_lto { dcx.handle().emit_fatal(LtoDylib); } - } else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto { + } else if *crate_type == CrateType::ProcMacro && !cgcx.dylib_lto { dcx.handle().emit_fatal(LtoProcMacro); } } - if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { + if cgcx.prefer_dynamic && !cgcx.dylib_lto { dcx.handle().emit_fatal(DynamicLinkingWithLTO); } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 53121fc6275b8..af9c61e177682 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,8 +15,8 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; use rustc_errors::translation::Translator; use rustc_errors::{ - Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FatalErrorMarker, Level, - MultiSpan, Style, Suggestions, + Diag, DiagArgMap, DiagCtxt, DiagCtxtHandle, DiagMessage, ErrCode, FatalError, FatalErrorMarker, + Level, MultiSpan, Style, Suggestions, catch_fatal_errors, }; use rustc_fs_util::link_or_copy; use rustc_incremental::{ @@ -326,15 +326,16 @@ pub struct CodegenContext { // Resources needed when running LTO pub prof: SelfProfilerRef, pub lto: Lto, + pub use_linker_plugin_lto: bool, + pub dylib_lto: bool, + pub prefer_dynamic: bool, pub save_temps: bool, pub fewer_names: bool, pub time_trace: bool, - pub opts: Arc, pub crate_types: Vec, pub output_filenames: Arc, pub invocation_temp: Option, pub module_config: Arc, - pub allocator_config: Arc, pub tm_factory: TargetMachineFactoryFn, pub msvc_imps_needed: bool, pub is_pe_coff: bool, @@ -347,8 +348,6 @@ pub struct CodegenContext { pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, pub pointer_size: Size, - /// Emitter to use for diagnostics produced during codegen. - pub diag_emitter: SharedEmitter, /// LLVM optimizations for which we want to print remarks. pub remark: Passes, /// Directory into which should the LLVM optimization remarks be written. @@ -363,14 +362,9 @@ pub struct CodegenContext { pub parallel: bool, } -impl CodegenContext { - pub fn create_dcx(&self) -> DiagCtxt { - DiagCtxt::new(Box::new(self.diag_emitter.clone())) - } -} - fn generate_thin_lto_work( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], needs_thin_lto: Vec<(String, B::ThinBuffer)>, @@ -380,6 +374,7 @@ fn generate_thin_lto_work( let (lto_modules, copy_jobs) = B::run_thin_lto( cgcx, + dcx, exported_symbols_for_lto, each_linked_rlib_for_lto, needs_thin_lto, @@ -408,6 +403,29 @@ struct CompiledModules { allocator_module: Option, } +enum MaybeLtoModules { + NoLto { + modules: Vec, + allocator_module: Option, + }, + FatLto { + cgcx: CodegenContext, + exported_symbols_for_lto: Arc>, + each_linked_rlib_file_for_lto: Vec, + needs_fat_lto: Vec>, + lto_import_only_modules: + Vec<(SerializedModule<::ModuleBuffer>, WorkProduct)>, + }, + ThinLto { + cgcx: CodegenContext, + exported_symbols_for_lto: Arc>, + each_linked_rlib_file_for_lto: Vec, + needs_thin_lto: Vec<(String, ::ThinBuffer)>, + lto_import_only_modules: + Vec<(SerializedModule<::ModuleBuffer>, WorkProduct)>, + }, +} + fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool { let sess = tcx.sess; sess.opts.cg.embed_bitcode @@ -797,20 +815,12 @@ pub(crate) enum ComputedLtoType { pub(crate) fn compute_per_cgu_lto_type( sess_lto: &Lto, - opts: &config::Options, + linker_does_lto: bool, sess_crate_types: &[CrateType], - module_kind: ModuleKind, ) -> ComputedLtoType { // If the linker does LTO, we don't have to do it. Note that we // keep doing full LTO, if it is requested, as not to break the // assumption that the output will be a single module. - let linker_does_lto = opts.cg.linker_plugin_lto.enabled(); - - // When we're automatically doing ThinLTO for multi-codegen-unit - // builds we don't actually want to LTO the allocator module if - // it shows up. This is due to various linker shenanigans that - // we'll encounter later. - let is_allocator = module_kind == ModuleKind::Allocator; // We ignore a request for full crate graph LTO if the crate type // is only an rlib, as there is no full crate graph to process, @@ -823,7 +833,7 @@ pub(crate) fn compute_per_cgu_lto_type( let is_rlib = matches!(sess_crate_types, [CrateType::Rlib]); match sess_lto { - Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin, + Lto::ThinLocal if !linker_does_lto => ComputedLtoType::Thin, Lto::Thin if !linker_does_lto && !is_rlib => ComputedLtoType::Thin, Lto::Fat if !is_rlib => ComputedLtoType::Fat, _ => ComputedLtoType::No, @@ -832,30 +842,24 @@ pub(crate) fn compute_per_cgu_lto_type( fn execute_optimize_work_item( cgcx: &CodegenContext, + shared_emitter: SharedEmitter, mut module: ModuleCodegen, ) -> WorkItemResult { let _timer = cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*module.name); - let dcx = cgcx.create_dcx(); - let dcx = dcx.handle(); - - let module_config = match module.kind { - ModuleKind::Regular => &cgcx.module_config, - ModuleKind::Allocator => &cgcx.allocator_config, - }; - - B::optimize(cgcx, dcx, &mut module, module_config); + B::optimize(cgcx, &shared_emitter, &mut module, &cgcx.module_config); // After we've done the initial round of optimizations we need to // decide whether to synchronously codegen this module or ship it // back to the coordinator thread for further LTO processing (which // has to wait for all the initial modules to be optimized). - let lto_type = compute_per_cgu_lto_type(&cgcx.lto, &cgcx.opts, &cgcx.crate_types, module.kind); + let lto_type = + compute_per_cgu_lto_type(&cgcx.lto, cgcx.use_linker_plugin_lto, &cgcx.crate_types); // If we're doing some form of incremental LTO then we need to be sure to // save our module to disk first. - let bitcode = if module_config.emit_pre_lto_bc { + let bitcode = if cgcx.module_config.emit_pre_lto_bc { let filename = pre_lto_bitcode_filename(&module.name); cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename)) } else { @@ -864,7 +868,7 @@ fn execute_optimize_work_item( match lto_type { ComputedLtoType::No => { - let module = B::codegen(cgcx, module, module_config); + let module = B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config); WorkItemResult::Finished(module) } ComputedLtoType::Thin => { @@ -894,12 +898,16 @@ fn execute_optimize_work_item( fn execute_copy_from_cache_work_item( cgcx: &CodegenContext, + shared_emitter: SharedEmitter, module: CachedModuleCodegen, ) -> CompiledModule { let _timer = cgcx .prof .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*module.name); + let dcx = DiagCtxt::new(Box::new(shared_emitter)); + let dcx = dcx.handle(); + let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let mut links_from_incr_cache = Vec::new(); @@ -918,11 +926,7 @@ fn execute_copy_from_cache_work_item( Some(output_path) } Err(error) => { - cgcx.create_dcx().handle().emit_err(errors::CopyPathBuf { - source_file, - output_path, - error, - }); + dcx.emit_err(errors::CopyPathBuf { source_file, output_path, error }); None } } @@ -965,7 +969,7 @@ fn execute_copy_from_cache_work_item( let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode); let object = load_from_incr_cache(should_emit_obj, OutputType::Object); if should_emit_obj && object.is_none() { - cgcx.create_dcx().handle().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name }) + dcx.emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name }) } CompiledModule { @@ -982,6 +986,7 @@ fn execute_copy_from_cache_work_item( fn do_fat_lto( cgcx: &CodegenContext, + shared_emitter: SharedEmitter, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], mut needs_fat_lto: Vec>, @@ -989,7 +994,10 @@ fn do_fat_lto( ) -> CompiledModule { let _timer = cgcx.prof.verbose_generic_activity("LLVM_fatlto"); - check_lto_allowed(&cgcx); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); + let dcx = dcx.handle(); + + check_lto_allowed(&cgcx, dcx); for (module, wp) in import_only_modules { needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module }) @@ -997,15 +1005,17 @@ fn do_fat_lto( let module = B::run_and_optimize_fat_lto( cgcx, + &shared_emitter, exported_symbols_for_lto, each_linked_rlib_for_lto, needs_fat_lto, ); - B::codegen(cgcx, module, &cgcx.module_config) + B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config) } fn do_thin_lto<'a, B: ExtraBackendMethods>( cgcx: &'a CodegenContext, + shared_emitter: SharedEmitter, exported_symbols_for_lto: Arc>, each_linked_rlib_for_lto: Vec, needs_thin_lto: Vec<(String, ::ThinBuffer)>, @@ -1016,7 +1026,10 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( ) -> Vec { let _timer = cgcx.prof.verbose_generic_activity("LLVM_thinlto"); - check_lto_allowed(&cgcx); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); + let dcx = dcx.handle(); + + check_lto_allowed(&cgcx, dcx); let (coordinator_send, coordinator_receive) = channel(); @@ -1041,6 +1054,7 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( // we don't worry about tokens. for (work, cost) in generate_thin_lto_work( cgcx, + dcx, &exported_symbols_for_lto, &each_linked_rlib_for_lto, needs_thin_lto, @@ -1082,7 +1096,7 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( while used_token_count < tokens.len() + 1 && let Some((item, _)) = work_items.pop() { - spawn_thin_lto_work(&cgcx, coordinator_send.clone(), item); + spawn_thin_lto_work(&cgcx, shared_emitter.clone(), coordinator_send.clone(), item); used_token_count += 1; } } else { @@ -1106,7 +1120,7 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( } Err(e) => { let msg = &format!("failed to acquire jobserver token: {e}"); - cgcx.diag_emitter.fatal(msg); + shared_emitter.fatal(msg); codegen_aborted = Some(FatalError); } }, @@ -1144,12 +1158,13 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( fn execute_thin_lto_work_item( cgcx: &CodegenContext, + shared_emitter: SharedEmitter, module: lto::ThinModule, ) -> CompiledModule { let _timer = cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", module.name()); - let module = B::optimize_thin(cgcx, module); - B::codegen(cgcx, module, &cgcx.module_config) + let module = B::optimize_thin(cgcx, &shared_emitter, module); + B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config) } /// Messages sent to the coordinator. @@ -1245,9 +1260,9 @@ fn start_executing_work( coordinator_receive: Receiver>, regular_config: Arc, allocator_config: Arc, - allocator_module: Option>, + mut allocator_module: Option>, coordinator_send: Sender>, -) -> thread::JoinHandle> { +) -> thread::JoinHandle, ()>> { let sess = tcx.sess; let mut each_linked_rlib_for_lto = Vec::new(); @@ -1292,18 +1307,18 @@ fn start_executing_work( let cgcx = CodegenContext:: { crate_types: tcx.crate_types().to_vec(), lto: sess.lto(), + use_linker_plugin_lto: sess.opts.cg.linker_plugin_lto.enabled(), + dylib_lto: sess.opts.unstable_opts.dylib_lto, + prefer_dynamic: sess.opts.cg.prefer_dynamic, fewer_names: sess.fewer_names(), save_temps: sess.opts.cg.save_temps, time_trace: sess.opts.unstable_opts.llvm_time_trace, - opts: Arc::new(sess.opts.clone()), prof: sess.prof.clone(), remark: sess.opts.cg.remark.clone(), remark_dir, incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()), - diag_emitter: shared_emitter.clone(), output_filenames: Arc::clone(tcx.output_filenames(())), module_config: regular_config, - allocator_config, tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features), msvc_imps_needed: msvc_imps_needed(tcx), is_pe_coff: tcx.sess.target.is_like_windows, @@ -1497,16 +1512,9 @@ fn start_executing_work( let mut llvm_start_time: Option> = None; - let compiled_allocator_module = allocator_module.and_then(|allocator_module| { - match execute_optimize_work_item(&cgcx, allocator_module) { - WorkItemResult::Finished(compiled_module) => return Some(compiled_module), - WorkItemResult::NeedsFatLto(fat_lto_input) => needs_fat_lto.push(fat_lto_input), - WorkItemResult::NeedsThinLto(name, thin_buffer) => { - needs_thin_lto.push((name, thin_buffer)) - } - } - None - }); + if let Some(allocator_module) = &mut allocator_module { + B::optimize(&cgcx, &shared_emitter, allocator_module, &allocator_config); + } // Run the message loop while there's still anything that needs message // processing. Note that as soon as codegen is aborted we simply want to @@ -1543,7 +1551,13 @@ fn start_executing_work( let (item, _) = work_items.pop().expect("queue empty - queue_full_enough() broken?"); main_thread_state = MainThreadState::Lending; - spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item); + spawn_work( + &cgcx, + shared_emitter.clone(), + coordinator_send.clone(), + &mut llvm_start_time, + item, + ); } } } else if codegen_state == Completed { @@ -1561,7 +1575,13 @@ fn start_executing_work( MainThreadState::Idle => { if let Some((item, _)) = work_items.pop() { main_thread_state = MainThreadState::Lending; - spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item); + spawn_work( + &cgcx, + shared_emitter.clone(), + coordinator_send.clone(), + &mut llvm_start_time, + item, + ); } else { // There is no unstarted work, so let the main thread // take over for a running worker. Otherwise the @@ -1597,7 +1617,13 @@ fn start_executing_work( while running_with_own_token < tokens.len() && let Some((item, _)) = work_items.pop() { - spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item); + spawn_work( + &cgcx, + shared_emitter.clone(), + coordinator_send.clone(), + &mut llvm_start_time, + item, + ); running_with_own_token += 1; } } @@ -1733,36 +1759,51 @@ fn start_executing_work( assert!(compiled_modules.is_empty()); assert!(needs_thin_lto.is_empty()); - // This uses the implicit token - let module = do_fat_lto( - &cgcx, - &exported_symbols_for_lto, - &each_linked_rlib_file_for_lto, + if let Some(allocator_module) = allocator_module.take() { + needs_fat_lto.push(FatLtoInput::InMemory(allocator_module)); + } + + return Ok(MaybeLtoModules::FatLto { + cgcx, + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, needs_fat_lto, lto_import_only_modules, - ); - compiled_modules.push(module); + }); } else if !needs_thin_lto.is_empty() || !lto_import_only_modules.is_empty() { assert!(compiled_modules.is_empty()); assert!(needs_fat_lto.is_empty()); - compiled_modules.extend(do_thin_lto( - &cgcx, - exported_symbols_for_lto, - each_linked_rlib_file_for_lto, - needs_thin_lto, - lto_import_only_modules, - )); - } + if cgcx.lto == Lto::ThinLocal { + compiled_modules.extend(do_thin_lto( + &cgcx, + shared_emitter.clone(), + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, + needs_thin_lto, + lto_import_only_modules, + )); + } else { + if let Some(allocator_module) = allocator_module.take() { + let (name, thin_buffer) = B::prepare_thin(allocator_module); + needs_thin_lto.push((name, thin_buffer)); + } - // Regardless of what order these modules completed in, report them to - // the backend in the same order every time to ensure that we're handing - // out deterministic results. - compiled_modules.sort_by(|a, b| a.name.cmp(&b.name)); + return Ok(MaybeLtoModules::ThinLto { + cgcx, + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, + needs_thin_lto, + lto_import_only_modules, + }); + } + } - Ok(CompiledModules { + Ok(MaybeLtoModules::NoLto { modules: compiled_modules, - allocator_module: compiled_allocator_module, + allocator_module: allocator_module.map(|allocator_module| { + B::codegen(&cgcx, &shared_emitter, allocator_module, &allocator_config) + }), }) }) .expect("failed to spawn coordinator thread"); @@ -1831,6 +1872,7 @@ pub(crate) struct WorkerFatalError; fn spawn_work<'a, B: ExtraBackendMethods>( cgcx: &'a CodegenContext, + shared_emitter: SharedEmitter, coordinator_send: Sender>, llvm_start_time: &mut Option>, work: WorkItem, @@ -1843,10 +1885,10 @@ fn spawn_work<'a, B: ExtraBackendMethods>( B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || { let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work { - WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, m), - WorkItem::CopyPostLtoArtifacts(m) => { - WorkItemResult::Finished(execute_copy_from_cache_work_item(&cgcx, m)) - } + WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, shared_emitter, m), + WorkItem::CopyPostLtoArtifacts(m) => WorkItemResult::Finished( + execute_copy_from_cache_work_item(&cgcx, shared_emitter, m), + ), })); let msg = match result { @@ -1868,6 +1910,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>( fn spawn_thin_lto_work<'a, B: ExtraBackendMethods>( cgcx: &'a CodegenContext, + shared_emitter: SharedEmitter, coordinator_send: Sender, work: ThinLtoWorkItem, ) { @@ -1875,8 +1918,10 @@ fn spawn_thin_lto_work<'a, B: ExtraBackendMethods>( B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || { let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work { - ThinLtoWorkItem::CopyPostLtoArtifacts(m) => execute_copy_from_cache_work_item(&cgcx, m), - ThinLtoWorkItem::ThinLto(m) => execute_thin_lto_work_item(&cgcx, m), + ThinLtoWorkItem::CopyPostLtoArtifacts(m) => { + execute_copy_from_cache_work_item(&cgcx, shared_emitter, m) + } + ThinLtoWorkItem::ThinLto(m) => execute_thin_lto_work_item(&cgcx, shared_emitter, m), })); let msg = match result { @@ -2052,13 +2097,13 @@ impl SharedEmitterMain { pub struct Coordinator { sender: Sender>, - future: Option>>, + future: Option, ()>>>, // Only used for the Message type. phantom: PhantomData, } impl Coordinator { - fn join(mut self) -> std::thread::Result> { + fn join(mut self) -> std::thread::Result, ()>> { self.future.take().unwrap().join() } } @@ -2089,8 +2134,9 @@ pub struct OngoingCodegen { impl OngoingCodegen { pub fn join(self, sess: &Session) -> (CodegenResults, FxIndexMap) { self.shared_emitter_main.check(sess, true); - let compiled_modules = sess.time("join_worker_thread", || match self.coordinator.join() { - Ok(Ok(compiled_modules)) => compiled_modules, + + let maybe_lto_modules = sess.time("join_worker_thread", || match self.coordinator.join() { + Ok(Ok(maybe_lto_modules)) => maybe_lto_modules, Ok(Err(())) => { sess.dcx().abort_if_errors(); panic!("expected abort due to worker thread errors") @@ -2102,6 +2148,62 @@ impl OngoingCodegen { sess.dcx().abort_if_errors(); + let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); + + // Catch fatal errors to ensure shared_emitter_main.check() can emit the actual diagnostics + let compiled_modules = catch_fatal_errors(|| match maybe_lto_modules { + MaybeLtoModules::NoLto { modules, allocator_module } => { + drop(shared_emitter); + CompiledModules { modules, allocator_module } + } + MaybeLtoModules::FatLto { + cgcx, + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, + needs_fat_lto, + lto_import_only_modules, + } => CompiledModules { + modules: vec![do_fat_lto( + &cgcx, + shared_emitter, + &exported_symbols_for_lto, + &each_linked_rlib_file_for_lto, + needs_fat_lto, + lto_import_only_modules, + )], + allocator_module: None, + }, + MaybeLtoModules::ThinLto { + cgcx, + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, + needs_thin_lto, + lto_import_only_modules, + } => CompiledModules { + modules: do_thin_lto( + &cgcx, + shared_emitter, + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, + needs_thin_lto, + lto_import_only_modules, + ), + allocator_module: None, + }, + }); + + shared_emitter_main.check(sess, true); + + sess.dcx().abort_if_errors(); + + let mut compiled_modules = + compiled_modules.expect("fatal error emitted but not sent to SharedEmitter"); + + // Regardless of what order these modules completed in, report them to + // the backend in the same order every time to ensure that we're handing + // out deterministic results. + compiled_modules.modules.sort_by(|a, b| a.name.cmp(&b.name)); + let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules); produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index c8aa7c04585c8..982a814c1c86d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -49,9 +49,7 @@ use crate::meth::load_vtable; use crate::mir::operand::OperandValue; use crate::mir::place::PlaceRef; use crate::traits::*; -use crate::{ - CachedModuleCodegen, CodegenLintLevels, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir, -}; +use crate::{CachedModuleCodegen, CodegenLintLevels, CrateInfo, ModuleCodegen, errors, meth, mir}; pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { match (op, signed) { @@ -1126,9 +1124,8 @@ pub fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> // reuse pre-LTO artifacts match compute_per_cgu_lto_type( &tcx.sess.lto(), - &tcx.sess.opts, + tcx.sess.opts.cg.linker_plugin_lto.enabled(), tcx.crate_types(), - ModuleKind::Regular, ) { ComputedLtoType::No => CguReuse::PostLto, _ => CguReuse::PreLto, diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index 1ac1d7ef2e2eb..e1d23841118cb 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -4,7 +4,7 @@ use rustc_errors::DiagCtxtHandle; use rustc_middle::dep_graph::WorkProduct; use crate::back::lto::{SerializedModule, ThinModule}; -use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig}; +use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter}; use crate::{CompiledModule, ModuleCodegen}; pub trait WriteBackendMethods: Clone + 'static { @@ -19,6 +19,7 @@ pub trait WriteBackendMethods: Clone + 'static { /// if necessary and running any further optimizations fn run_and_optimize_fat_lto( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -28,6 +29,7 @@ pub trait WriteBackendMethods: Clone + 'static { /// can simply be copied over from the incr. comp. cache. fn run_thin_lto( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, Self::ThinBuffer)>, @@ -37,16 +39,18 @@ pub trait WriteBackendMethods: Clone + 'static { fn print_statistics(&self); fn optimize( cgcx: &CodegenContext, - dcx: DiagCtxtHandle<'_>, + shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ); fn optimize_thin( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, thin: ThinModule, ) -> ModuleCodegen; fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule; diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f425c26ba706f..5dee64b42f73f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -18,7 +18,7 @@ use std::ffi::OsString; use std::fmt::Write as _; use std::fs::{self, File}; use std::io::{self, IsTerminal, Read, Write}; -use std::panic::{self, PanicHookInfo, catch_unwind}; +use std::panic::{self, PanicHookInfo}; use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::sync::OnceLock; @@ -32,10 +32,11 @@ use rustc_codegen_ssa::{CodegenErrors, CodegenResults}; use rustc_data_structures::profiling::{ TimePassesFormat, get_resident_set_size, print_time_passes_entry, }; +pub use rustc_errors::catch_fatal_errors; use rustc_errors::emitter::stderr_destination; use rustc_errors::registry::Registry; use rustc_errors::translation::Translator; -use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown}; +use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown}; use rustc_feature::find_gated_cfg; // This avoids a false positive with `-Wunused_crate_dependencies`. // `rust_index` isn't used in this crate's code, but it must be named in the @@ -1377,21 +1378,6 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { parser.parse_inner_attributes() } -/// Runs a closure and catches unwinds triggered by fatal errors. -/// -/// The compiler currently unwinds with a special sentinel value to abort -/// compilation on fatal errors. This function catches that sentinel and turns -/// the panic into a `Result` instead. -pub fn catch_fatal_errors R, R>(f: F) -> Result { - catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { - if value.is::() { - FatalError - } else { - panic::resume_unwind(value); - } - }) -} - /// Variant of `catch_fatal_errors` for the `interface::Result` return type /// that also computes the exit code. pub fn catch_with_exit_code(f: impl FnOnce()) -> i32 { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ead7af9b39eb9..60cd4e0a91ca4 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -66,7 +66,7 @@ use rustc_lint_defs::LintExpectationId; pub use rustc_lint_defs::{Applicability, listify, pluralize}; use rustc_macros::{Decodable, Encodable}; pub use rustc_span::ErrorGuaranteed; -pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; +pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors}; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, DUMMY_SP, Loc, Span}; pub use snippet::Style; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 97dc9dd21a654..ded8a5a4ae51c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1315,13 +1315,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls" ), rustc_attr!( - rustc_do_not_implement_via_object, + rustc_dyn_incompatible_trait, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \ - (`impl Trait for dyn Trait`)" + "`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \ + even if it otherwise satisfies the requirements to be dyn-compatible." ), rustc_attr!( rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index f32e69f61d082..21f7c4ae7c108 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -728,9 +728,6 @@ pub enum AttributeKind { /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute). Deprecation { deprecation: Deprecation, span: Span }, - /// Represents `#[rustc_do_not_implement_via_object]`. - DoNotImplementViaObject(Span), - /// Represents `#[diagnostic::do_not_recommend]`. DoNotRecommend { attr_span: Span }, @@ -746,6 +743,9 @@ pub enum AttributeKind { /// Represents `#[rustc_dummy]`. Dummy, + /// Represents `#[rustc_dyn_incompatible_trait]`. + DynIncompatibleTrait(Span), + /// Implementation detail of `#[eii]` EiiDeclaration(EiiDecl), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 712775eef6de1..640554dc81cd6 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -43,11 +43,11 @@ impl AttributeKind { DebuggerVisualizer(..) => No, DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, - DoNotImplementViaObject(..) => No, DoNotRecommend { .. } => Yes, Doc(_) => Yes, DocComment { .. } => Yes, Dummy => No, + DynIncompatibleTrait(..) => No, EiiDeclaration(_) => Yes, EiiForeignItem => No, EiiImpls(..) => No, diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index bc3231cff9b47..58483dc44fe91 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -211,9 +211,7 @@ fn check_object_overlap<'tcx>( // This is a WF error tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`. } else { let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id); - if supertrait_def_ids - .any(|d| d == trait_def_id && tcx.trait_def(d).implement_via_object) - { + if supertrait_def_ids.any(|d| d == trait_def_id) { let span = tcx.def_span(impl_def_id); return Err(struct_span_code_err!( tcx.dcx(), diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9c0b638c14828..dd399f9d90def 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -924,7 +924,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { ); let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_)); - let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_)); + let force_dyn_incompatible = + find_attr!(attrs, AttributeKind::DynIncompatibleTrait(span) => *span); ty::TraitDef { def_id: def_id.to_def_id(), @@ -939,7 +940,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { skip_boxed_slice_during_method_dispatch, specialization_kind, must_implement_one_of, - implement_via_object, + force_dyn_incompatible, deny_explicit_impl, } } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 1b2a283a1a0d1..e93cba2c8d0fc 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -91,10 +91,7 @@ fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) { work_product::delete_workproduct_files(sess, &swp.work_product); } -fn load_dep_graph( - sess: &Session, - deps: &DepsType, -) -> LoadResult<(Arc, WorkProductMap)> { +fn load_dep_graph(sess: &Session) -> LoadResult<(Arc, WorkProductMap)> { let prof = sess.prof.clone(); if sess.opts.incremental.is_none() { @@ -174,7 +171,7 @@ fn load_dep_graph( return LoadResult::DataOutOfDate; } - let dep_graph = SerializedDepGraph::decode::(&mut decoder, deps); + let dep_graph = SerializedDepGraph::decode::(&mut decoder); LoadResult::Ok { data: (dep_graph, prev_work_products) } } @@ -212,12 +209,11 @@ pub fn setup_dep_graph( sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId, - deps: &DepsType, ) -> DepGraph { // `load_dep_graph` can only be called after `prepare_session_directory`. prepare_session_directory(sess, crate_name, stable_crate_id); - let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess, deps)); + let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess)); if sess.opts.incremental.is_some() { sess.time("incr_comp_garbage_collect_session_directories", || { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 12a6a616d64f9..a7e94e1c01550 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -26,7 +26,6 @@ use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_sto use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; -use rustc_middle::dep_graph::DepsType; use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; use rustc_parse::lexer::StripTokens; @@ -940,8 +939,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( let outputs = util::build_output_filenames(&pre_configured_attrs, sess); - let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() }; - let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id, &dep_type); + let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id); let cstore = FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _); diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 3ee1db67911ff..f5ed0570667cc 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -24,15 +24,6 @@ macro_rules! define_dep_nodes { ($mod:ident) => {[ $($mod::$variant()),* ]}; } - #[macro_export] - macro_rules! make_dep_kind_name_array { - ($mod:ident) => { - vec! { - $(*$mod::$variant().name),* - } - }; - } - /// This enum serves as an index into arrays built by `make_dep_kind_array`. // This enum has more than u8::MAX variants so we need some kind of multi-byte // encoding. The derived Encodable/Decodable uses leb128 encoding which is @@ -68,20 +59,24 @@ macro_rules! define_dep_nodes { deps.len() as u16 }; + /// List containing the name of each dep kind as a static string, + /// indexable by `DepKind`. + pub(crate) const DEP_KIND_NAMES: &[&str] = &[ + $( self::label_strs::$variant, )* + ]; + pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { - $(stringify!($variant) => Ok(dep_kinds::$variant),)* + $( self::label_strs::$variant => Ok(self::dep_kinds::$variant), )* _ => Err(()), } } /// Contains variant => str representations for constructing /// DepNode groups for tests. - #[allow(dead_code, non_upper_case_globals)] + #[expect(non_upper_case_globals)] pub mod label_strs { - $( - pub const $variant: &str = stringify!($variant); - )* + $( pub const $variant: &str = stringify!($variant); )* } }; } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index b24ea4acc6b72..049e868879e96 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -20,10 +20,7 @@ pub type DepGraph = rustc_query_system::dep_graph::DepGraph; pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct>; -#[derive(Clone)] -pub struct DepsType { - pub dep_names: Vec<&'static str>, -} +pub struct DepsType; impl Deps for DepsType { fn with_deps(task_deps: TaskDepsRef<'_>, op: OP) -> R @@ -47,8 +44,8 @@ impl Deps for DepsType { }) } - fn name(&self, dep_kind: DepKind) -> &'static str { - self.dep_names[dep_kind.as_usize()] + fn name(dep_kind: DepKind) -> &'static str { + dep_node::DEP_KIND_NAMES[dep_kind.as_usize()] } const DEP_KIND_NULL: DepKind = dep_kinds::Null; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c064313f67b23..d71df36684f5c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -764,6 +764,9 @@ pub enum DynCompatibilityViolation { /// `Self: Sized` declared on the trait. SizedSelf(SmallVec<[Span; 1]>), + /// Trait is marked `#[rustc_dyn_incompatible_trait]`. + ExplicitlyDynIncompatible(SmallVec<[Span; 1]>), + /// Supertrait reference references `Self` an in illegal location /// (e.g., `trait Foo : Bar`). SupertraitSelf(SmallVec<[Span; 1]>), @@ -788,6 +791,9 @@ impl DynCompatibilityViolation { pub fn error_msg(&self) -> Cow<'static, str> { match self { DynCompatibilityViolation::SizedSelf(_) => "it requires `Self: Sized`".into(), + DynCompatibilityViolation::ExplicitlyDynIncompatible(_) => { + "it opted out of dyn-compatibility".into() + } DynCompatibilityViolation::SupertraitSelf(spans) => { if spans.iter().any(|sp| *sp != DUMMY_SP) { "it uses `Self` as a type parameter".into() @@ -861,6 +867,7 @@ impl DynCompatibilityViolation { pub fn solution(&self) -> DynCompatibilityViolationSolution { match self { DynCompatibilityViolation::SizedSelf(_) + | DynCompatibilityViolation::ExplicitlyDynIncompatible(_) | DynCompatibilityViolation::SupertraitSelf(_) | DynCompatibilityViolation::SupertraitNonLifetimeBinder(..) | DynCompatibilityViolation::SupertraitConst(_) => { @@ -894,6 +901,7 @@ impl DynCompatibilityViolation { match self { DynCompatibilityViolation::SupertraitSelf(spans) | DynCompatibilityViolation::SizedSelf(spans) + | DynCompatibilityViolation::ExplicitlyDynIncompatible(spans) | DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans) | DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(), DynCompatibilityViolation::AssocConst(_, span) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index fb515cf7f778e..2f7a31a957bc8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -709,10 +709,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(def_id).is_fundamental } - fn trait_may_be_implemented_via_object(self, trait_def_id: DefId) -> bool { - self.trait_def(trait_def_id).implement_via_object - } - fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { self.trait_def(trait_def_id).safety.is_unsafe() } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 2f6b38a619d26..0553561fac2cb 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -7,6 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::{self as hir, find_attr}; use rustc_macros::{Decodable, Encodable, HashStable}; +use rustc_span::Span; use tracing::debug; use crate::query::LocalCrate; @@ -69,10 +70,9 @@ pub struct TraitDef { /// must be implemented. pub must_implement_one_of: Option>, - /// Whether to add a builtin `dyn Trait: Trait` implementation. - /// This is enabled for all traits except ones marked with - /// `#[rustc_do_not_implement_via_object]`. - pub implement_via_object: bool, + /// Whether the trait should be considered dyn-incompatible, even if it otherwise + /// satisfies the requirements to be dyn-compatible. + pub force_dyn_incompatible: Option, /// Whether a trait is fully built-in, and any implementation is disallowed. /// This only applies to built-in traits, and is marked via diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index d27d80a086ad1..63f246db8a5fb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -792,7 +792,9 @@ where candidates: &mut Vec>, ) { let cx = self.cx(); - if !cx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(cx)) { + if cx.is_sizedness_trait(goal.predicate.trait_def_id(cx)) { + // `dyn MetaSized` is valid, but should get its `MetaSized` impl from + // being `dyn` (SizedCandidate), not from the object candidate. return; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 659e5535ca50a..b6141bf7db535 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -244,7 +244,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::SkipDuringMethodDispatch { .. } | AttributeKind::Coinductive(..) | AttributeKind::DenyExplicitImpl(..) - | AttributeKind::DoNotImplementViaObject(..) + | AttributeKind::DynIncompatibleTrait(..) | AttributeKind::SpecializationTrait(..) | AttributeKind::UnsafeSpecializationMarker(..) | AttributeKind::ParenSugar(..) diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index 14656a2e594ad..f0a18ef08fc68 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -1395,7 +1395,7 @@ pub struct TraitDecl { pub skip_boxed_slice_during_method_dispatch: bool, pub specialization_kind: TraitSpecializationKind, pub must_implement_one_of: Option>, - pub implement_via_object: bool, + pub force_dyn_incompatible: Option, pub deny_explicit_impl: bool, } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index ca8234280be85..34662c9ca0234 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -597,7 +597,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { .must_implement_one_of .as_ref() .map(|idents| idents.iter().map(|ident| opaque(ident)).collect()), - implement_via_object: self.implement_via_object, + force_dyn_incompatible: self.force_dyn_incompatible.stable(tables, cx), deny_explicit_impl: self.deny_explicit_impl, } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 67ab1114af62b..d6d1dc781f3e2 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -921,9 +921,5 @@ macro_rules! define_queries { pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] { arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(query_callbacks)) } - - pub fn dep_kind_names() -> Vec<&'static str> { - rustc_middle::make_dep_kind_name_array!(query_callbacks) - } } } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index f32f3f78c04b2..f0cc9636b75c2 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -28,7 +28,6 @@ use crate::dep_graph::edges::EdgesVec; use crate::ich::StableHashingContext; use crate::query::{QueryContext, QuerySideEffect}; -#[derive(Clone)] pub struct DepGraph { data: Option>>, @@ -39,6 +38,17 @@ pub struct DepGraph { virtual_dep_node_index: Arc, } +/// Manual clone impl that does not require `D: Clone`. +impl Clone for DepGraph { + fn clone(&self) -> Self { + let Self { data, virtual_dep_node_index } = self; + Self { + data: Option::>::clone(data), + virtual_dep_node_index: Arc::clone(virtual_dep_node_index), + } + } +} + rustc_index::newtype_index! { pub struct DepNodeIndex {} } diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index d648415c9fc67..8b9e4fe1bf29b 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -103,7 +103,7 @@ pub trait Deps: DynSync { where OP: for<'a> FnOnce(TaskDepsRef<'a>); - fn name(&self, dep_kind: DepKind) -> &'static str; + fn name(dep_kind: DepKind) -> &'static str; /// We use this for most things when incr. comp. is turned off. const DEP_KIND_NULL: DepKind; diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 0012bf79a1f5d..403394674a027 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -191,8 +191,8 @@ fn mask(bits: usize) -> usize { } impl SerializedDepGraph { - #[instrument(level = "debug", skip(d, deps))] - pub fn decode(d: &mut MemDecoder<'_>, deps: &D) -> Arc { + #[instrument(level = "debug", skip(d))] + pub fn decode(d: &mut MemDecoder<'_>) -> Arc { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); @@ -280,7 +280,7 @@ impl SerializedDepGraph { if index[node.kind.as_usize()].insert(node.hash, idx).is_some() { // Empty nodes and side effect nodes can have duplicates if node.kind != D::DEP_KIND_NULL && node.kind != D::DEP_KIND_SIDE_EFFECT { - let name = deps.name(node.kind); + let name = D::name(node.kind); panic!( "Error: A dep graph node ({name}) does not have an unique index. \ Running a clean build on a nightly compiler with `-Z incremental-verify-ich` \ diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs index 26c5711099c6d..5e2d82681a11a 100644 --- a/compiler/rustc_span/src/fatal_error.rs +++ b/compiler/rustc_span/src/fatal_error.rs @@ -3,6 +3,8 @@ #[must_use] pub struct FatalError; +use std::panic; + pub use rustc_data_structures::FatalErrorMarker; // Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`. @@ -22,3 +24,18 @@ impl std::fmt::Display for FatalError { } impl std::error::Error for FatalError {} + +/// Runs a closure and catches unwinds triggered by fatal errors. +/// +/// The compiler currently unwinds with a special sentinel value to abort +/// compilation on fatal errors. This function catches that sentinel and turns +/// the panic into a `Result` instead. +pub fn catch_fatal_errors R, R>(f: F) -> Result { + panic::catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { + if value.is::() { + FatalError + } else { + panic::resume_unwind(value); + } + }) +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e5949a979074a..d6d6ebb49e106 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1950,7 +1950,6 @@ symbols! { rustc_diagnostic_macros, rustc_dirty, rustc_do_not_const_check, - rustc_do_not_implement_via_object, rustc_doc_primitive, rustc_driver, rustc_dummy, @@ -1959,6 +1958,7 @@ symbols! { rustc_dump_predicates, rustc_dump_user_args, rustc_dump_vtable, + rustc_dyn_incompatible_trait, rustc_effective_visibility, rustc_eii_foreign_item, rustc_evaluate_where_clauses, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 6ab92531e4eff..13acdad8aad7d 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -93,7 +93,10 @@ fn dyn_compatibility_violations_for_trait( // We don't want to include the requirement from `Sized` itself to be `Sized` in the list. let spans = get_sized_bounds(tcx, trait_def_id); violations.push(DynCompatibilityViolation::SizedSelf(spans)); + } else if let Some(span) = tcx.trait_def(trait_def_id).force_dyn_incompatible { + violations.push(DynCompatibilityViolation::ExplicitlyDynIncompatible([span].into())); } + let spans = predicates_reference_self(tcx, trait_def_id, false); if !spans.is_empty() { violations.push(DynCompatibilityViolation::SupertraitSelf(spans)); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e5c2adaa261d3..5bbbad0b5bbfa 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -799,10 +799,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( let tcx = selcx.tcx(); - if !tcx.trait_def(obligation.predicate.trait_def_id(tcx)).implement_via_object { - return; - } - let self_ty = obligation.predicate.self_ty(); let object_ty = selcx.infcx.shallow_resolve(self_ty); let data = match object_ty.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d0833f0308350..f5bf74a799192 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -904,7 +904,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { "assemble_candidates_from_object_ty", ); - if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object { + if self.tcx().is_sizedness_trait(obligation.predicate.def_id()) { + // `dyn MetaSized` is valid, but should get its `MetaSized` impl from + // being `dyn` (SizedCandidate), not from the object candidate. return; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 03cf738c05987..0ab27a65c6879 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -378,8 +378,6 @@ pub trait Interner: fn trait_is_fundamental(self, def_id: Self::TraitId) -> bool; - fn trait_may_be_implemented_via_object(self, trait_def_id: Self::TraitId) -> bool; - /// Returns `true` if this is an `unsafe trait`. fn trait_is_unsafe(self, trait_def_id: Self::TraitId) -> bool; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index da7ba167ef74e..57416455e9de8 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -153,7 +153,7 @@ unsafe impl Send for &T {} #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable #[rustc_specialization_trait] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] // `Sized` being coinductive, despite having supertraits, is okay as there are no user-written impls, // and we know that the supertraits are always implemented if the subtrait is just by looking at // the builtin impls. @@ -172,7 +172,6 @@ pub trait Sized: MetaSized { #[fundamental] #[rustc_specialization_trait] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] // `MetaSized` being coinductive, despite having supertraits, is okay for the same reasons as // `Sized` above. #[rustc_coinductive] @@ -190,7 +189,6 @@ pub trait MetaSized: PointeeSized { #[fundamental] #[rustc_specialization_trait] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] #[rustc_coinductive] pub trait PointeeSized { // Empty @@ -236,7 +234,7 @@ pub trait PointeeSized { #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] pub trait Unsize: PointeeSized { // Empty. } @@ -509,7 +507,7 @@ impl Copy for &T {} #[unstable(feature = "bikeshed_guaranteed_no_drop", issue = "none")] #[lang = "bikeshed_guaranteed_no_drop"] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] #[doc(hidden)] pub trait BikeshedGuaranteedNoDrop {} @@ -884,7 +882,7 @@ impl StructuralPartialEq for PhantomData {} )] #[lang = "discriminant_kind"] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] pub trait DiscriminantKind { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. @@ -1054,7 +1052,7 @@ marker_impls! { #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] pub const trait Destruct: PointeeSized {} /// A marker for tuple types. @@ -1065,7 +1063,7 @@ pub const trait Destruct: PointeeSized {} #[lang = "tuple_trait"] #[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] pub trait Tuple {} /// A marker for types which can be used as types of `const` generic parameters. @@ -1123,7 +1121,7 @@ marker_impls! { )] #[lang = "fn_ptr_trait"] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] pub trait FnPtr: Copy + Clone { /// Returns the address of the function pointer. #[lang = "fn_ptr_addr"] diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index f36cb8cddb837..e26c1b8fa1e19 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -86,7 +86,7 @@ use crate::marker::ConstParamTy_; #[unstable_feature_bound(transmutability)] #[lang = "transmute_trait"] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] #[rustc_coinductive] pub unsafe trait TransmuteFrom where diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 1a58643168332..1eeadf1217b5f 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -55,7 +55,7 @@ use crate::ptr::NonNull; /// [`to_raw_parts`]: *const::to_raw_parts #[lang = "pointee_trait"] #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] pub trait Pointee: PointeeSized { /// The type for metadata in pointers and references to `Self`. #[lang = "metadata_type"] diff --git a/tests/ui/dyn-compatibility/metasized.rs b/tests/ui/dyn-compatibility/metasized.rs new file mode 100644 index 0000000000000..ff233c5ca7647 --- /dev/null +++ b/tests/ui/dyn-compatibility/metasized.rs @@ -0,0 +1,25 @@ +//@ run-pass +//! This test and `sized-*.rs` and `pointeesized.rs` test that dyn-compatibility correctly +//! handles sizedness traits, which are special in several parts of the compiler. +#![feature(sized_hierarchy)] +use std::marker::MetaSized; + +trait Foo: std::fmt::Debug + MetaSized {} + +impl Foo for T {} + +fn unsize_sized(x: Box) -> Box { + x +} + +fn unsize_subtrait(x: Box) -> Box { + x +} + +fn main() { + let _bx = unsize_sized(Box::new(vec![1, 2, 3])); + + let bx: Box = Box::new(vec![1, 2, 3]); + let _ = format!("{bx:?}"); + let _bx = unsize_subtrait(bx); +} diff --git a/tests/ui/dyn-compatibility/pointeesized.rs b/tests/ui/dyn-compatibility/pointeesized.rs new file mode 100644 index 0000000000000..863abd704eadc --- /dev/null +++ b/tests/ui/dyn-compatibility/pointeesized.rs @@ -0,0 +1,17 @@ +//@ run-pass +//! This test and `sized-*.rs` and `metasized.rs` test that dyn-compatibility correctly +//! handles sizedness traits, which are special in several parts of the compiler. +#![feature(sized_hierarchy)] +// PointeeSized is effectively removed before reaching the trait solver, +// so it's as though it wasn't even mentioned in the trait list. +use std::marker::PointeeSized; + +fn main() { + let dyn_ref: &(dyn PointeeSized + Send) = &42; + let dyn_ref: &dyn Send = dyn_ref; + let _dyn_ref: &(dyn PointeeSized + Send) = dyn_ref; + assert_eq!( + std::any::TypeId::of::(), + std::any::TypeId::of::(), + ); +} diff --git a/tests/ui/dyn-compatibility/sized-3.rs b/tests/ui/dyn-compatibility/sized-3.rs new file mode 100644 index 0000000000000..84ee391445e7e --- /dev/null +++ b/tests/ui/dyn-compatibility/sized-3.rs @@ -0,0 +1,29 @@ +//! This test and `metasized.rs` and `pointeesized.rs` test that dyn-compatibility correctly +//! handles the different sizedness traits, which are special in several parts of the compiler. + +trait Foo: std::fmt::Debug + Sized {} + +impl Foo for T {} + +fn unsize_sized(x: Box) -> Box { + //~^ ERROR the trait `Sized` is not dyn compatible + x +} + +fn unsize_subtrait(x: Box) -> Box { + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Sized` is not dyn compatible + x +} + +fn main() { + let _bx = unsize_sized(Box::new(vec![1, 2, 3])); + //~^ ERROR the trait `Sized` is not dyn compatible + + let bx: Box = Box::new(vec![1, 2, 3]); + //~^ ERROR the trait `Foo` is not dyn compatible + let _ = format!("{bx:?}"); + let _bx = unsize_subtrait(bx); + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Sized` is not dyn compatible +} diff --git a/tests/ui/dyn-compatibility/sized-3.stderr b/tests/ui/dyn-compatibility/sized-3.stderr new file mode 100644 index 0000000000000..88d3bb5810fe2 --- /dev/null +++ b/tests/ui/dyn-compatibility/sized-3.stderr @@ -0,0 +1,88 @@ +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/sized-3.rs:8:47 + | +LL | fn unsize_sized(x: Box) -> Box { + | ^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/sized-3.rs:13:27 + | +LL | fn unsize_subtrait(x: Box) -> Box { + | ^^^^^^^ `Foo` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/sized-3.rs:4:30 + | +LL | trait Foo: std::fmt::Debug + Sized {} + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait is not dyn compatible... + +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/sized-3.rs:13:44 + | +LL | fn unsize_subtrait(x: Box) -> Box { + | ^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/sized-3.rs:20:15 + | +LL | let _bx = unsize_sized(Box::new(vec![1, 2, 3])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/sized-3.rs:23:21 + | +LL | let bx: Box = Box::new(vec![1, 2, 3]); + | ^^^ `Foo` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/sized-3.rs:4:30 + | +LL | trait Foo: std::fmt::Debug + Sized {} + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait is not dyn compatible... + +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/sized-3.rs:26:31 + | +LL | let _bx = unsize_subtrait(bx); + | ^^ `Foo` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/sized-3.rs:4:30 + | +LL | trait Foo: std::fmt::Debug + Sized {} + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait is not dyn compatible... + +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/sized-3.rs:26:15 + | +LL | let _bx = unsize_subtrait(bx); + | ^^^^^^^^^^^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/deny-builtin-object-impl.current.stderr b/tests/ui/traits/deny-builtin-object-impl.current.stderr index d6f4762d09966..928d16aa43297 100644 --- a/tests/ui/traits/deny-builtin-object-impl.current.stderr +++ b/tests/ui/traits/deny-builtin-object-impl.current.stderr @@ -4,41 +4,67 @@ error[E0322]: explicit impls for the `NotImplYesObject` trait are not permitted LL | impl NotImplYesObject for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `NotImplYesObject` not allowed -error[E0277]: the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied - --> $DIR/deny-builtin-object-impl.rs:37:32 +error[E0038]: the trait `YesImplNotObject2` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:23:28 + | +LL | impl YesImplNotObject2 for dyn YesImplNotObject2 {} + | ^^^^^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:17:1 + | +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility +LL | trait YesImplNotObject2 {} + | ----------------- this trait is not dyn compatible... + +error[E0038]: the trait `NotImplNotObject` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:37:36 | LL | test_not_impl_not_object::(); - | ^^^^^^^^^^^^^^^^^^^^ the trait `NotImplNotObject` is not implemented for `dyn NotImplNotObject` + | ^^^^^^^^^^^^^^^^ `NotImplNotObject` is not dyn compatible | -help: this trait has no implementations, consider adding one - --> $DIR/deny-builtin-object-impl.rs:12:1 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:11:1 | +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility LL | trait NotImplNotObject {} - | ^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `test_not_impl_not_object` - --> $DIR/deny-builtin-object-impl.rs:28:32 - | -LL | fn test_not_impl_not_object() {} - | ^^^^^^^^^^^^^^^^ required by this bound in `test_not_impl_not_object` + | ---------------- this trait is not dyn compatible... -error[E0277]: the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied - --> $DIR/deny-builtin-object-impl.rs:40:32 +error[E0038]: the trait `YesImplNotObject` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:40:36 | LL | test_yes_impl_not_object::(); - | ^^^^^^^^^^^^^^^^^^^^ the trait `YesImplNotObject` is not implemented for `dyn YesImplNotObject` + | ^^^^^^^^^^^^^^^^ `YesImplNotObject` is not dyn compatible | -help: this trait has no implementations, consider adding one - --> $DIR/deny-builtin-object-impl.rs:15:1 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:14:1 | +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility LL | trait YesImplNotObject {} - | ^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `test_yes_impl_not_object` - --> $DIR/deny-builtin-object-impl.rs:30:32 + | ---------------- this trait is not dyn compatible... + +error[E0038]: the trait `YesImplNotObject2` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:43:37 + | +LL | test_yes_impl_not_object2::(); + | ^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:17:1 | -LL | fn test_yes_impl_not_object() {} - | ^^^^^^^^^^^^^^^^ required by this bound in `test_yes_impl_not_object` +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility +LL | trait YesImplNotObject2 {} + | ----------------- this trait is not dyn compatible... -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0322. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0038, E0322. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/deny-builtin-object-impl.next.stderr b/tests/ui/traits/deny-builtin-object-impl.next.stderr index d6f4762d09966..928d16aa43297 100644 --- a/tests/ui/traits/deny-builtin-object-impl.next.stderr +++ b/tests/ui/traits/deny-builtin-object-impl.next.stderr @@ -4,41 +4,67 @@ error[E0322]: explicit impls for the `NotImplYesObject` trait are not permitted LL | impl NotImplYesObject for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `NotImplYesObject` not allowed -error[E0277]: the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied - --> $DIR/deny-builtin-object-impl.rs:37:32 +error[E0038]: the trait `YesImplNotObject2` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:23:28 + | +LL | impl YesImplNotObject2 for dyn YesImplNotObject2 {} + | ^^^^^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:17:1 + | +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility +LL | trait YesImplNotObject2 {} + | ----------------- this trait is not dyn compatible... + +error[E0038]: the trait `NotImplNotObject` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:37:36 | LL | test_not_impl_not_object::(); - | ^^^^^^^^^^^^^^^^^^^^ the trait `NotImplNotObject` is not implemented for `dyn NotImplNotObject` + | ^^^^^^^^^^^^^^^^ `NotImplNotObject` is not dyn compatible | -help: this trait has no implementations, consider adding one - --> $DIR/deny-builtin-object-impl.rs:12:1 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:11:1 | +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility LL | trait NotImplNotObject {} - | ^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `test_not_impl_not_object` - --> $DIR/deny-builtin-object-impl.rs:28:32 - | -LL | fn test_not_impl_not_object() {} - | ^^^^^^^^^^^^^^^^ required by this bound in `test_not_impl_not_object` + | ---------------- this trait is not dyn compatible... -error[E0277]: the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied - --> $DIR/deny-builtin-object-impl.rs:40:32 +error[E0038]: the trait `YesImplNotObject` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:40:36 | LL | test_yes_impl_not_object::(); - | ^^^^^^^^^^^^^^^^^^^^ the trait `YesImplNotObject` is not implemented for `dyn YesImplNotObject` + | ^^^^^^^^^^^^^^^^ `YesImplNotObject` is not dyn compatible | -help: this trait has no implementations, consider adding one - --> $DIR/deny-builtin-object-impl.rs:15:1 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:14:1 | +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility LL | trait YesImplNotObject {} - | ^^^^^^^^^^^^^^^^^^^^^^ -note: required by a bound in `test_yes_impl_not_object` - --> $DIR/deny-builtin-object-impl.rs:30:32 + | ---------------- this trait is not dyn compatible... + +error[E0038]: the trait `YesImplNotObject2` is not dyn compatible + --> $DIR/deny-builtin-object-impl.rs:43:37 + | +LL | test_yes_impl_not_object2::(); + | ^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/deny-builtin-object-impl.rs:17:1 | -LL | fn test_yes_impl_not_object() {} - | ^^^^^^^^^^^^^^^^ required by this bound in `test_yes_impl_not_object` +LL | #[rustc_dyn_incompatible_trait] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility +LL | trait YesImplNotObject2 {} + | ----------------- this trait is not dyn compatible... -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0322. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0038, E0322. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/deny-builtin-object-impl.rs b/tests/ui/traits/deny-builtin-object-impl.rs index 9d02ab7bd469e..5924b3fa2857a 100644 --- a/tests/ui/traits/deny-builtin-object-impl.rs +++ b/tests/ui/traits/deny-builtin-object-impl.rs @@ -8,20 +8,20 @@ trait NotImplYesObject {} #[rustc_deny_explicit_impl] -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] trait NotImplNotObject {} -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] trait YesImplNotObject {} -#[rustc_do_not_implement_via_object] +#[rustc_dyn_incompatible_trait] trait YesImplNotObject2 {} impl NotImplYesObject for () {} //~^ ERROR explicit impls for the `NotImplYesObject` trait are not permitted -// If there is no automatic impl then we can add a manual impl: impl YesImplNotObject2 for dyn YesImplNotObject2 {} +//~^ ERROR the trait `YesImplNotObject2` is not dyn compatible fn test_not_impl_yes_object() {} @@ -35,10 +35,11 @@ fn main() { test_not_impl_yes_object::(); test_not_impl_not_object::(); - //~^ ERROR the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied + //~^ ERROR the trait `NotImplNotObject` is not dyn compatible test_yes_impl_not_object::(); - //~^ ERROR the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied + //~^ ERROR the trait `YesImplNotObject` is not dyn compatible test_yes_impl_not_object2::(); + //~^ ERROR the trait `YesImplNotObject2` is not dyn compatible } diff --git a/tests/ui/traits/ice-with-dyn-pointee-errors.rs b/tests/ui/traits/ice-with-dyn-pointee-errors.rs index 46cef2c8bc094..bb89f103e3f95 100644 --- a/tests/ui/traits/ice-with-dyn-pointee-errors.rs +++ b/tests/ui/traits/ice-with-dyn-pointee-errors.rs @@ -6,10 +6,12 @@ use core::ptr::Pointee; fn unknown_sized_object_ptr_in(_: &(impl Pointee + ?Sized)) {} fn raw_pointer_in(x: &dyn Pointee) { + //~^ ERROR the trait `Pointee` is not dyn compatible unknown_sized_object_ptr_in(x) - //~^ ERROR type mismatch resolving ` as Pointee>::Metadata == ()` + //~^ ERROR the trait `Pointee` is not dyn compatible } fn main() { raw_pointer_in(&42) + //~^ ERROR the trait `Pointee` is not dyn compatible } diff --git a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr index 5299236026d7e..9ff0445cda09b 100644 --- a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr +++ b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr @@ -1,19 +1,39 @@ -error[E0271]: type mismatch resolving ` as Pointee>::Metadata == ()` - --> $DIR/ice-with-dyn-pointee-errors.rs:9:33 +error[E0038]: the trait `Pointee` is not dyn compatible + --> $DIR/ice-with-dyn-pointee-errors.rs:8:23 + | +LL | fn raw_pointer_in(x: &dyn Pointee) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `Pointee` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL + | + = note: the trait is not dyn compatible because it opted out of dyn-compatibility + +error[E0038]: the trait `Pointee` is not dyn compatible + --> $DIR/ice-with-dyn-pointee-errors.rs:10:5 | LL | unknown_sized_object_ptr_in(x) - | --------------------------- ^ expected `()`, found `DynMetadata>` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Pointee` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL + | + = note: the trait is not dyn compatible because it opted out of dyn-compatibility + +error[E0038]: the trait `Pointee` is not dyn compatible + --> $DIR/ice-with-dyn-pointee-errors.rs:15:20 + | +LL | raw_pointer_in(&42) + | ^^^ `Pointee` is not dyn compatible | - = note: expected unit type `()` - found struct `DynMetadata>` -note: required by a bound in `unknown_sized_object_ptr_in` - --> $DIR/ice-with-dyn-pointee-errors.rs:6:50 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL | -LL | fn unknown_sized_object_ptr_in(_: &(impl Pointee + ?Sized)) {} - | ^^^^^^^^^^^^^ required by this bound in `unknown_sized_object_ptr_in` + = note: the trait is not dyn compatible because it opted out of dyn-compatibility -error: aborting due to 1 previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/ice-with-dyn-pointee.rs b/tests/ui/traits/ice-with-dyn-pointee.rs deleted file mode 100644 index 45361cc44600d..0000000000000 --- a/tests/ui/traits/ice-with-dyn-pointee.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -#![feature(ptr_metadata)] -// Address issue #112737 -- ICE with dyn Pointee -extern crate core; -use core::ptr::Pointee; - -fn raw_pointer_in(_: &dyn Pointee) {} - -fn main() { - raw_pointer_in(&42) -} diff --git a/tests/ui/unsized/issue-71659.current.stderr b/tests/ui/unsized/issue-71659.current.stderr index f7de668ba3a56..22e43e07dbda5 100644 --- a/tests/ui/unsized/issue-71659.current.stderr +++ b/tests/ui/unsized/issue-71659.current.stderr @@ -1,18 +1,22 @@ -error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied - --> $DIR/issue-71659.rs:34:15 +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/issue-71659.rs:33:17 | -LL | let x = x.cast::<[i32]>(); - | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` +LL | let x: &dyn Foo = &[]; + | ^^^ `Foo` is not dyn compatible | -note: required by a bound in `Cast::cast` - --> $DIR/issue-71659.rs:23:15 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/marker.rs:LL:COL | -LL | fn cast(&self) -> &T - | ---- required by a bound in this associated function -LL | where -LL | Self: CastTo, - | ^^^^^^^^^ required by this bound in `Cast::cast` + = note: ...because it opted out of dyn-compatibility + | + ::: $DIR/issue-71659.rs:29:11 + | +LL | pub trait Foo: CastTo<[i32]> {} + | --- this trait is not dyn compatible... + = help: only type `[i32; 0]` implements `Foo` within this crate; consider using it directly instead. + = note: `Foo` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/unsized/issue-71659.next.stderr b/tests/ui/unsized/issue-71659.next.stderr index f7de668ba3a56..22e43e07dbda5 100644 --- a/tests/ui/unsized/issue-71659.next.stderr +++ b/tests/ui/unsized/issue-71659.next.stderr @@ -1,18 +1,22 @@ -error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied - --> $DIR/issue-71659.rs:34:15 +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/issue-71659.rs:33:17 | -LL | let x = x.cast::<[i32]>(); - | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` +LL | let x: &dyn Foo = &[]; + | ^^^ `Foo` is not dyn compatible | -note: required by a bound in `Cast::cast` - --> $DIR/issue-71659.rs:23:15 +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/marker.rs:LL:COL | -LL | fn cast(&self) -> &T - | ---- required by a bound in this associated function -LL | where -LL | Self: CastTo, - | ^^^^^^^^^ required by this bound in `Cast::cast` + = note: ...because it opted out of dyn-compatibility + | + ::: $DIR/issue-71659.rs:29:11 + | +LL | pub trait Foo: CastTo<[i32]> {} + | --- this trait is not dyn compatible... + = help: only type `[i32; 0]` implements `Foo` within this crate; consider using it directly instead. + = note: `Foo` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/unsized/issue-71659.rs b/tests/ui/unsized/issue-71659.rs index c463ed125bb6a..9e1387fa84434 100644 --- a/tests/ui/unsized/issue-71659.rs +++ b/tests/ui/unsized/issue-71659.rs @@ -31,6 +31,6 @@ impl Foo for [i32; 0] {} fn main() { let x: &dyn Foo = &[]; + //~^ ERROR: the trait `Foo` is not dyn compatible let x = x.cast::<[i32]>(); - //~^ ERROR: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied } diff --git a/triagebot.toml b/triagebot.toml index a25c2a0a388ce..1572c4c8d0456 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -499,6 +499,7 @@ trigger_files = [ "bootstrap.example.toml", "src/bootstrap", "src/build_helper", + "src/tools/build-manifest", "src/tools/rust-installer", "src/tools/x", "src/stage0", @@ -1656,6 +1657,7 @@ dep-bumps = [ "/tests/rustdoc-json" = ["@aDotInTheVoid"] "/tests/rustdoc-ui" = ["rustdoc"] "/tests/ui" = ["compiler"] +"/src/tools/build-manifest" = ["bootstrap"] "/src/tools/cargo" = ["@ehuss"] "/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@jieyouxu"] "/src/tools/linkchecker" = ["@ehuss"]