diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index bc8bfacba1923..b83354ee49fb9 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-08" +channel = "nightly-2026-09-10" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 1bdb3efefa1aa..d31c8fc810b2c 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -5,8 +5,9 @@ use rustc_index::IndexVec; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, + codegen_handle_fn_abi_err, }; -use rustc_span::{Spanned, Symbol}; +use rustc_span::Symbol; use rustc_target::callconv::FnAbi; use rustc_target::spec::{Arch, HasTargetSpec, Target}; @@ -453,23 +454,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) = - err - { - self.0.sess.dcx().emit_fatal(Spanned { span, node: err }) - } else { - match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}"); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}" - ); - } - } - } + codegen_handle_fn_abi_err(self.0, err, span, fn_abi_request).raise_fatal() } } diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 19fbe37c27b9e..64f9982ac7de6 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -10,16 +10,15 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::interpret::Allocation; use rustc_middle::mono::CodegenUnit; -use rustc_middle::span_bug; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, - LayoutOfHelpers, + LayoutOfHelpers, codegen_handle_fn_abi_err, }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; #[cfg(feature = "master")] use rustc_session::config::DebugInfo; use rustc_session::{PointerAuthSchema, Session}; -use rustc_span::{DUMMY_SP, Span, Symbol, respan}; +use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; #[cfg(feature = "master")] @@ -562,23 +561,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) = - err - { - self.tcx.dcx().emit_fatal(respan(span, err)) - } else { - match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}"); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}" - ); - } - } - } + codegen_handle_fn_abi_err(self.tcx, err, span, fn_abi_request).raise_fatal() } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 9e127edbd2ff9..3b58a7f00146b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -14,18 +14,19 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_middle::bug; use rustc_middle::mono::CodegenUnit; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, + codegen_handle_fn_abi_err, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_sanitizers::ignorelist::{SanitizerIgnoreList, typename_for_ignore_list}; use rustc_session::config::{ BranchProtection, CFGuard, CFProtection, DebugInfo, FunctionReturn, PAuthKey, PacRet, }; use rustc_session::{PointerAuthSchema, Session}; -use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_structures::CrateType; use rustc_target::spec::{ Arch, CfgAbi, Env, FramePointer, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, @@ -1316,21 +1317,6 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - match err { - FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => { - self.tcx.dcx().emit_fatal(Spanned { span, node: err }); - } - _ => match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}", - ); - } - }, - } + codegen_handle_fn_abi_err(self.tcx, err, span, fn_abi_request).raise_fatal() } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1844a8e5c0bca..743145a0e5baf 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -231,11 +231,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::offload => { if tcx.sess.opts.unstable_opts.offload.is_empty() { - let _ = tcx.dcx().emit_almost_fatal(OffloadWithoutEnable); + let _ = tcx.dcx().emit_err(OffloadWithoutEnable); } if tcx.sess.lto() != rustc_session::config::Lto::Fat { - let _ = tcx.dcx().emit_almost_fatal(OffloadWithoutFatLTO); + let _ = tcx.dcx().emit_err(OffloadWithoutFatLTO); } codegen_offload(self, tcx, instance, args); @@ -1752,18 +1752,18 @@ fn codegen_autodiff<'ll, 'tcx>( ) -> IntrinsicResult<'tcx, &'ll Value> { let tcx = bx.tcx; if !tcx.sess.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable) { - let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutEnable); + let _ = tcx.dcx().emit_err(AutoDiffWithoutEnable); } let ct = tcx.crate_types(); let lto = tcx.sess.lto(); if ct.len() == 1 && ct.contains(&CrateType::Executable) { if lto != rustc_session::config::Lto::Fat { - let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutLto); + let _ = tcx.dcx().emit_err(AutoDiffWithoutLto); } } else { if lto != rustc_session::config::Lto::Fat && !tcx.sess.opts.cg.linker_plugin_lto.enabled() { - let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutLto); + let _ = tcx.dcx().emit_err(AutoDiffWithoutLto); } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 2874b85e9b67a..54904f4944262 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -73,13 +73,6 @@ impl EmissionGuarantee for FatalAbort { } } -impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult { - diag.emit_producing_nothing(); - rustc_span::fatal_error::FatalError - } -} - /// Trait implemented by error types. This is rarely implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. /// diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 98a5b32e5d902..0fdd0f80e0433 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1025,19 +1025,6 @@ impl<'a> DiagCtxtHandle<'a> { self.create_fatal(fatal).emit() } - #[track_caller] - pub fn create_almost_fatal( - self, - fatal: impl Diagnostic<'a, FatalError>, - ) -> Diag<'a, FatalError> { - fatal.into_diag(self, Fatal) - } - - #[track_caller] - pub fn emit_almost_fatal(self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError { - self.create_almost_fatal(fatal).emit() - } - // FIXME: This method should be removed (every error should have an associated error code). #[track_caller] pub fn struct_err(self, msg: impl Into) -> Diag<'a> { @@ -1577,24 +1564,21 @@ impl DelayedDiagInner { } } -/// | Level | is_error | EmissionGuarantee | Top-level | Sub | Used in lints? -/// | ----- | -------- | ----------------- | --------- | --- | -------------- -/// | Bug | yes | BugAbort | yes | - | - -/// | Fatal | yes | FatalAbort/FatalError[^star] | yes | - | - -/// | Error | yes | ErrorGuaranteed | yes | - | yes -/// | DelayedBug | yes | ErrorGuaranteed | yes | - | - -/// | ForceWarning | - | () | yes | - | lint-only -/// | Warning | - | () | yes | yes | yes -/// | Note | - | () | rare | yes | - -/// | OnceNote | - | () | - | yes | lint-only -/// | Help | - | () | rare | yes | - -/// | OnceHelp | - | () | - | yes | lint-only -/// | FailureNote | - | () | rare | - | - -/// | Allow | - | () | yes | - | lint-only -/// | Expect | - | () | yes | - | lint-only -/// -/// [^star]: `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is -/// occasionally used. +/// | Level | is_error | EmissionGuarantee | Top-level | Sub | Used in lints? +/// | ----- | -------- | ----------------- | --------- | --- | -------------- +/// | Bug | yes | BugAbort | yes | - | - +/// | Fatal | yes | FatalAbort | yes | - | - +/// | Error | yes | ErrorGuaranteed | yes | - | yes +/// | DelayedBug | yes | ErrorGuaranteed | yes | - | - +/// | ForceWarning | - | () | yes | - | lint-only +/// | Warning | - | () | yes | yes | yes +/// | Note | - | () | rare | yes | - +/// | OnceNote | - | () | - | yes | lint-only +/// | Help | - | () | rare | yes | - +/// | OnceHelp | - | () | - | yes | lint-only +/// | FailureNote | - | () | rare | - | - +/// | Allow | - | () | yes | - | lint-only +/// | Expect | - | () | yes | - | lint-only /// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 68af061769437..12f3140a8c7b3 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1302,7 +1302,10 @@ pub(crate) fn start_codegen<'tcx>( info!("Pre-codegen\n{:?}", tcx.debug_stats()); - let metadata = rustc_metadata::fs::encode_and_write_metadata(tcx); + let metadata = match rustc_metadata::fs::encode_and_write_metadata(tcx) { + Ok(metadata) => metadata, + Err(guar) => guar.raise_fatal(), + }; let is_host_metadata = tcx .sess diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 535197b3dc51a..ed177708facc0 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -7,6 +7,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; +use rustc_span::ErrorGuaranteed; use rustc_structures::CrateType; use crate::diagnostics::{ @@ -34,7 +35,7 @@ pub fn emit_wrapper_file(sess: &Session, data: &[u8], tmpdir: &Path, name: &str) out_filename } -pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { +pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> Result { let out_filename = filename_for_metadata(tcx.sess, tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its @@ -70,6 +71,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { } } + if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() { + return Err(guar); + } + let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata"); // If the user requests metadata as output, rename `metadata_filename` @@ -109,7 +114,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); }); - metadata + Ok(metadata) } #[cfg(not(target_os = "linux"))] diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 87e0902b1f7f8..eff464bcfc526 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -274,7 +274,8 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibUnsupportedAbi { span }); + return None; } } } else { @@ -283,7 +284,8 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::C } _ => { - self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibUnsupportedAbi { span }); + return None; } } }; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 713671c3a5b47..dc4a41ace6b88 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1571,8 +1571,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Static { .. } = def_kind { if !self.tcx.is_foreign_item(def_id) { - let data = self.tcx.eval_static_initializer(def_id).unwrap(); - record!(self.tables.eval_static_initializer[def_id] <- data); + match self.tcx.eval_static_initializer(def_id) { + Ok(data) => record!(self.tables.eval_static_initializer[def_id] <- data), + Err(err) => match err { + interpret::ErrorHandled::Reported(_, _) => { + self.tcx.dcx().delayed_bug(format!( + "eval_static_initializer returned an error in metadata emission" + )); + } + interpret::ErrorHandled::TooGeneric(span) => { + span_bug!(span, "generic static???"); + } + }, + }; } } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c18bf81121377..85e1df8b057a0 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -14,7 +14,7 @@ use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; use rustc_session::config::OptLevel; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Spanned, Symbol, sym}; use rustc_structures::Limit; use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; @@ -1374,6 +1374,8 @@ pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { /// but this hook allows e.g. codegen to return only `&FnAbi` from its /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with /// (and any `FnAbiError`s are turned into fatal errors or ICEs). + /// + /// Codegen backends should use [`codegen_handle_fn_abi_err`] as implementation. fn handle_fn_abi_err( &self, err: FnAbiError<'tcx>, @@ -1382,6 +1384,28 @@ pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { ) -> >>>::Error; } +/// Implementation of [`FnAbiOfHelpers::handle_fn_abi_err`] for codegen backends. +pub fn codegen_handle_fn_abi_err<'tcx>( + tcx: TyCtxt<'tcx>, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, +) -> ErrorGuaranteed { + match err { + FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => { + tcx.dcx().emit_err(Spanned { span, node: err }) + } + _ => match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!(span, "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",); + } + }, + } +} + /// Blanket extension trait for contexts that can compute `FnAbi`s. pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 885ad6071d91c..1ba48e6829070 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -3,6 +3,7 @@ use rustc_abi::{BackendRepr, CanonAbi, ExternAbi, RegKind, X86Call}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_middle::mir::{self, Location, traversal}; +use rustc_middle::ty::layout::{FnAbiRequest, codegen_handle_fn_abi_err}; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -173,12 +174,19 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // LLVM intrinsics return; } - let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) - else { - // An error will be reported during codegen if we cannot determine the ABI of this - // function. - tcx.dcx().delayed_bug("ABI computation failure should lead to compilation failure"); - return; + let abi = match tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + { + Ok(abi) => abi, + Err(err) => { + codegen_handle_fn_abi_err( + tcx, + *err, + tcx.def_span(instance.def_id()), + FnAbiRequest::OfInstance { instance, extra_args: ty::List::empty() }, + ); + // ABI failed to compute; this will not get through codegen. + return; + } }; // Unlike the call-site check, we do also check "Rust" ABI functions here. This can actually // trigger due to scalable vectors being require for the "Rust" ABI for some types. @@ -214,7 +222,20 @@ fn check_call_site_abi<'tcx>( let typing_env = ty::TypingEnv::fully_monomorphized(); let callee_abi = match *callee.kind() { ty::FnPtr(..) => { - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((callee.fn_sig(tcx), ty::List::empty()))) + let sig = callee.fn_sig(tcx); + match tcx.fn_abi_of_fn_ptr(typing_env.as_query_input((sig, ty::List::empty()))) { + Ok(callee_abi) => callee_abi, + Err(err) => { + codegen_handle_fn_abi_err( + tcx, + *err, + loc().0, + FnAbiRequest::OfFnPtr { sig, extra_args: ty::List::empty() }, + ); + // ABI failed to compute; this will not get through codegen. + return; + } + } } ty::FnDef(def_id, args) => { // Intrinsics are handled separately by the compiler. @@ -232,17 +253,25 @@ fn check_call_site_abi<'tcx>( // LLVM intrinsics don't have an ABI, so there is nothing to check. return; } - tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + match tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) { + Ok(callee_abi) => callee_abi, + Err(err) => { + codegen_handle_fn_abi_err( + tcx, + *err, + loc().0, + FnAbiRequest::OfInstance { instance, extra_args: ty::List::empty() }, + ); + // ABI failed to compute; this will not get through codegen. + return; + } + } } _ => { panic!("Invalid function call"); } }; - let Ok(callee_abi) = callee_abi else { - // ABI failed to compute; this will not get through codegen. - return; - }; do_check_unsized_params(tcx, callee_abi, /*is_call*/ true, loc); do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc); } 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 51e1aea3850e4..30e9c1a84c4ad 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -86,7 +86,15 @@ where goal: Goal, assumption: I::Clause, ) -> Result, NoSolutionOrRerunNonErased> { - Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { + // We inline much of `probe_and_match_goal_against_assumption` and + // `TraitPredicate::match_assumption` here, as we never encounter + // `Sized` or `MetaSized` goals here, and we need to equate `goal` + // and `assumption`'s trait refs directly inside this function in + // order to prevent unsoundness (see below). + + Self::fast_reject_assumption(ecx, goal, assumption)?; + + ecx.probe_trait_candidate(source).enter(|ecx| { let cx = ecx.cx(); let ty::Dynamic(bounds, _) = goal.predicate.self_ty().kind() else { panic!("expected object type in `probe_and_consider_object_bound_candidate`"); @@ -107,6 +115,37 @@ where } }); + // If we need to prove `dyn for<'x> Trait<'x> + '?temp: Trait<'static>` with + // + // ```rs + // trait Trait<'a>: 'a {} + // ``` + // + // we have the goal's trait ref as `Trait<'static>` and a theoretical impl + // resembling: + // + // ```rs + // impl<'s, 'hr> Trait<'hr> for dyn for<'x> Trait<'x> + 's + // where + // dyn for<'a> Trait<'a> + 's: 'hr + // {} + // ``` + // + // where 'hr is our bound var. The where-clause elaborates to `'s: 'hr`; + // in this case we have 's := '?temp. Instantiating the binder gives us + // 'hr := '?infer, and our goal has 'hr := 'static, so we need to equate + // the instantiated trait ref to the goal in order to get '?infer := 'static, + // since what we want is the constraint `'?temp: 'static`. + // + // If we instead passed the binder to predicates_for_object_candidate and let + // it instantiate the binder itself, we would lose '?infer := 'static, since + // predicates_for_object_candidate has no way of equating the trait ref with + // the goal. We would simply have 'hr := '?infer, giving us the constraint + // `?temp: '?infer`, which is satisfiable for any lifetime, leading to + // unsoundness: trait-system-refactor-initiative#295. + let trait_ref = ecx.instantiate_binder_with_infer(trait_ref); + ecx.eq(goal.param_env, goal.predicate.trait_ref(cx), trait_ref)?; + match structural_traits::predicates_for_object_candidate( ecx, goal.param_env, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 17172c5333502..4f061956765b8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -8,7 +8,7 @@ use rustc_type_ir::lang_items::{SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; use rustc_type_ir::{ - self as ty, Binder, FallibleTypeFolder, Interner, Movability, Mutability, Region, TypeFoldable, + self as ty, FallibleTypeFolder, Interner, Movability, Mutability, Region, TypeFoldable, TypeSuperFoldable, Unnormalized, Upcast as _, elaborate, }; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; @@ -891,7 +891,7 @@ pub(in crate::solve) fn const_conditions_for_destruct( pub(in crate::solve) fn predicates_for_object_candidate( ecx: &mut EvalCtxt<'_, D>, param_env: I::ParamEnv, - trait_ref: Binder>, + trait_ref: ty::TraitRef, object_bounds: I::BoundExistentialPredicates, ) -> Result>, AmbiguousOrRerunNonErased> where @@ -899,7 +899,6 @@ where I: Interner, { let cx = ecx.cx(); - let trait_ref = ecx.instantiate_binder_with_infer(trait_ref); let mut requirements = vec![]; // Elaborating all supertrait outlives obligations here is not soundness critical, // since if we just used the unelaborated set, then the transitive supertraits would diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 4f5d93a2fe286..95bb2fd7e40c5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5158,6 +5158,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind() && let ty::Uint(ty::UintTy::Usize) = inner_ty.kind() { + // If the index is written as `&i`, suggest removing the borrow instead of + // dereferencing it, i.e. `v[&i]` -> `v[i]` rather than `v[*&i]`. + let span = obligation.cause.span; + if !span.from_expansion() + && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) + && let Some(expr) = { + let mut finder = FindExprBySpan::new(span, self.tcx); + finder.visit_expr(body.value); + finder.result + } + && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, borrowed) = + expr.kind + && let Some(amp_span) = borrowed + .span + .find_ancestor_inside_same_ctxt(expr.span) + .map(|borrowed_span| expr.span.until(borrowed_span)) + && self + .tcx + .sess + .source_map() + .span_to_snippet(amp_span) + .is_ok_and(|snippet| snippet.starts_with('&')) + { + err.span_suggestion_verbose( + amp_span, + "remove this reference", + "", + Applicability::MachineApplicable, + ); + return; + } + err.span_suggestion_verbose( obligation.cause.span.shrink_to_lo(), "dereference this index", diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 93dd52198f488..db05d7fdc5087 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -594,7 +594,7 @@ impl f128 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// #![feature(f128)] @@ -620,7 +620,7 @@ impl f128 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// #![feature(f128)] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index cb79c0736c608..273ef3688ca5f 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -588,7 +588,7 @@ impl f16 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// #![feature(f16)] @@ -616,7 +616,7 @@ impl f16 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// #![feature(f16)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 8a02aa7517474..d3dea38dc2fcf 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -811,7 +811,7 @@ impl f32 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// let f = 7.0_f32; @@ -836,7 +836,7 @@ impl f32 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// let f = 7.0f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index e0bb0e35415b6..7c5082749cd11 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -810,7 +810,7 @@ impl f64 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -835,7 +835,7 @@ impl f64 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (will return NaN for all NaNs). /// /// ``` /// let f = 7.0_f64; diff --git a/src/ci/scripts/disable-git-crlf-conversion.sh b/src/ci/scripts/disable-git-crlf-conversion.sh index 6de080a9fde00..856c2fa03700e 100755 --- a/src/ci/scripts/disable-git-crlf-conversion.sh +++ b/src/ci/scripts/disable-git-crlf-conversion.sh @@ -10,4 +10,8 @@ set -euo pipefail IFS=$'\n\t' +# Workaround for issue where the home dir of `msys64` sometimes doesn't exist on github runners +echo $HOME +mkdir -p $HOME + git config --replace-all --global core.autocrlf false diff --git a/tests/crashes/152204.rs b/tests/crashes/152204.rs deleted file mode 100644 index 8c9be213d9ea5..0000000000000 --- a/tests/crashes/152204.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #152204 -//@ compile-flags: -Copt-level=0 -#![feature(portable_simd)] - -fn main() { - if false { - let _ = core::simd::Simd::::splat(0); - } -} diff --git a/tests/run-make/prune-link-args/rmake.rs b/tests/run-make/prune-link-args/rmake.rs index ea4ffa732bf3f..6702984d2e85a 100644 --- a/tests/run-make/prune-link-args/rmake.rs +++ b/tests/run-make/prune-link-args/rmake.rs @@ -6,12 +6,10 @@ // See https://github.com/rust-lang/rust/pull/10749 //@ ignore-cross-compile -//@ ignore-windows-gnu -// Reason: The space is parsed as an empty linker argument on windows-gnu. use run_make_support::rustc; fn main() { - // Notice the space at the end of -lc, which emulates the output of pkg-config. - rustc().arg("-Clink-args=-lc ").input("empty.rs").run(); + // Notice the space at the end of -lm, which emulates the output of pkg-config. + rustc().arg("-Clink-args=-lm ").input("empty.rs").run(); } diff --git a/tests/ui/abi/no_delayed_bug.rs b/tests/ui/abi/no_delayed_bug.rs new file mode 100644 index 0000000000000..9b378ba9d25a7 --- /dev/null +++ b/tests/ui/abi/no_delayed_bug.rs @@ -0,0 +1,15 @@ +// Used to ICE due to the ABI checker emitting a delayed bug when failing to get +// the FnAbi due to a const assert, while codegen skipped the call due to being +// unreachable. +//@ compile-flags: -Copt-level=0 +//@ build-fail + +//~? ERROR the SIMD type `Simd` has more elements than the limit 64 + +#![feature(portable_simd)] + +fn main() { + if false { + let _ = core::simd::Simd::::splat(0); + } +} diff --git a/tests/ui/abi/no_delayed_bug.stderr b/tests/ui/abi/no_delayed_bug.stderr new file mode 100644 index 0000000000000..c21256b86a6c4 --- /dev/null +++ b/tests/ui/abi/no_delayed_bug.stderr @@ -0,0 +1,11 @@ +error: the SIMD type `Simd` has more elements than the limit 64 + --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:COL + +note: the above error was encountered while instantiating `fn Simd::::splat` + --> $DIR/no_delayed_bug.rs:13:17 + | +LL | let _ = core::simd::Simd::::splat(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/limits/issue-17913.32bit.stderr b/tests/ui/limits/issue-17913.32bit.stderr index 1e3e3a9f32295..6ddde4b891836 100644 --- a/tests/ui/limits/issue-17913.32bit.stderr +++ b/tests/ui/limits/issue-17913.32bit.stderr @@ -1,3 +1,6 @@ +error: values of the type `[&usize; usize::MAX]` are too big for the target architecture + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | @@ -9,6 +12,6 @@ note: the above error was encountered while instantiating `fn Box::<[&usize; usi LL | let a: Box<_> = Box::new([&n; SIZE]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-17913.64bit.stderr b/tests/ui/limits/issue-17913.64bit.stderr index 5e92c70a764c4..d35d697d5f3f3 100644 --- a/tests/ui/limits/issue-17913.64bit.stderr +++ b/tests/ui/limits/issue-17913.64bit.stderr @@ -1,3 +1,6 @@ +error: values of the type `[&usize; usize::MAX]` are too big for the target architecture + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | @@ -9,6 +12,6 @@ note: the above error was encountered while instantiating `fn Box::<[&usize; usi LL | let a: Box<_> = Box::new([&n; SIZE]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs index 9448358edba00..d804b64ab330e 100644 --- a/tests/ui/limits/issue-17913.rs +++ b/tests/ui/limits/issue-17913.rs @@ -18,3 +18,4 @@ fn main() { } //~? ERROR are too big for the target architecture +//~? ERROR are too big for the target architecture diff --git a/tests/ui/suggestions/suggest-remove-reference-index.fixed b/tests/ui/suggestions/suggest-remove-reference-index.fixed new file mode 100644 index 0000000000000..646c650de4584 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-reference-index.fixed @@ -0,0 +1,10 @@ +//@ run-rustfix + +fn main() { + let arr = [false]; + let i = 0usize; + + println!("{}", arr[i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[(i + 0)]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` +} diff --git a/tests/ui/suggestions/suggest-remove-reference-index.rs b/tests/ui/suggestions/suggest-remove-reference-index.rs new file mode 100644 index 0000000000000..db0a33a89eff3 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-reference-index.rs @@ -0,0 +1,10 @@ +//@ run-rustfix + +fn main() { + let arr = [false]; + let i = 0usize; + + println!("{}", arr[&i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[&(i + 0)]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` + println!("{}", arr[& i]); //~ ERROR the type `[bool]` cannot be indexed by `&usize` +} diff --git a/tests/ui/suggestions/suggest-remove-reference-index.stderr b/tests/ui/suggestions/suggest-remove-reference-index.stderr new file mode 100644 index 0000000000000..4f396fe529508 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-reference-index.stderr @@ -0,0 +1,66 @@ +error[E0277]: the type `[bool]` cannot be indexed by `&usize` + --> $DIR/suggest-remove-reference-index.rs:7:24 + | +LL | println!("{}", arr[&i]); + | ^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[bool]>` is not implemented for `&usize` +help: `usize` implements trait `SliceIndex` + --> $SRC_DIR/core/src/slice/index.rs:LL:COL + | + = note: `SliceIndex<[T]>` + --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL + | + = note: `SliceIndex` + = note: required for `[bool]` to implement `Index<&usize>` +help: remove this reference + | +LL - println!("{}", arr[&i]); +LL + println!("{}", arr[i]); + | + +error[E0277]: the type `[bool]` cannot be indexed by `&usize` + --> $DIR/suggest-remove-reference-index.rs:8:24 + | +LL | println!("{}", arr[&(i + 0)]); + | ^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[bool]>` is not implemented for `&usize` +help: `usize` implements trait `SliceIndex` + --> $SRC_DIR/core/src/slice/index.rs:LL:COL + | + = note: `SliceIndex<[T]>` + --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL + | + = note: `SliceIndex` + = note: required for `[bool]` to implement `Index<&usize>` +help: remove this reference + | +LL - println!("{}", arr[&(i + 0)]); +LL + println!("{}", arr[(i + 0)]); + | + +error[E0277]: the type `[bool]` cannot be indexed by `&usize` + --> $DIR/suggest-remove-reference-index.rs:9:24 + | +LL | println!("{}", arr[& i]); + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[bool]>` is not implemented for `&usize` +help: `usize` implements trait `SliceIndex` + --> $SRC_DIR/core/src/slice/index.rs:LL:COL + | + = note: `SliceIndex<[T]>` + --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL + | + = note: `SliceIndex` + = note: required for `[bool]` to implement `Index<&usize>` +help: remove this reference + | +LL - println!("{}", arr[& i]); +LL + println!("{}", arr[i]); + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/assoc-type-static-lifetime-object-bound.rs b/tests/ui/traits/next-solver/assoc-type-static-lifetime-object-bound.rs new file mode 100644 index 0000000000000..f5ca8c10636a5 --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-type-static-lifetime-object-bound.rs @@ -0,0 +1,27 @@ +//! regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/295 + +//@ compile-flags: -Znext-solver + +#![forbid(unsafe_code)] + +trait Tr<'a> { + type A: 'a; +} + +fn f>(a: >::A) -> Box { + Box::new(a) +} + +fn launder<'b>(r: &'b u8) -> &'static u8 { + *f:: Tr<'a, A = &'b u8>>(r).downcast_ref::<&'static u8>().unwrap() + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let p; + { + let x = Box::new(42u8); + p = launder(&x); + } + println!("{}", *p); +} diff --git a/tests/ui/traits/next-solver/assoc-type-static-lifetime-object-bound.stderr b/tests/ui/traits/next-solver/assoc-type-static-lifetime-object-bound.stderr new file mode 100644 index 0000000000000..009091845f85d --- /dev/null +++ b/tests/ui/traits/next-solver/assoc-type-static-lifetime-object-bound.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/assoc-type-static-lifetime-object-bound.rs:16:6 + | +LL | fn launder<'b>(r: &'b u8) -> &'static u8 { + | -- lifetime `'b` defined here +LL | *f:: Tr<'a, A = &'b u8>>(r).downcast_ref::<&'static u8>().unwrap() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/next-solver/gat-static-in-trait-object.rs b/tests/ui/traits/next-solver/gat-static-in-trait-object.rs new file mode 100644 index 0000000000000..80f3838dc08b6 --- /dev/null +++ b/tests/ui/traits/next-solver/gat-static-in-trait-object.rs @@ -0,0 +1,24 @@ +//! regression test from https://github.com/rust-lang/rust/pull/160831/changes#r3852248101 +//! once we allow GATs in object types, we want to make sure this isn't unsound. + +//@ compile-flags: -Znext-solver + +use std::any::Any; + +trait Trait { + type Assoc<'a>: 'a; +} + +fn tr(x: T::Assoc<'static>) -> Box { Box::new(x) } + +fn foo<'s>(x: &'s str) -> Box +where + dyn for<'hr> Trait = &'s str>: Trait = &'s str>, + //~^ ERROR the trait `Trait` is not dyn compatible + //~| ERROR the trait `Trait` is not dyn compatible +{ + tr:: Trait = &'s str>>(x) + //~^ ERROR the trait `Trait` is not dyn compatible +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/gat-static-in-trait-object.stderr b/tests/ui/traits/next-solver/gat-static-in-trait-object.stderr new file mode 100644 index 0000000000000..ed27a81cc0be5 --- /dev/null +++ b/tests/ui/traits/next-solver/gat-static-in-trait-object.stderr @@ -0,0 +1,51 @@ +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/gat-static-in-trait-object.rs:16:47 + | +LL | dyn for<'hr> Trait = &'s str>: Trait = &'s str>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/gat-static-in-trait-object.rs:9:10 + | +LL | trait Trait { + | ----- this trait is not dyn compatible... +LL | type Assoc<'a>: 'a; + | ^^^^^ ...because it contains generic associated type `Assoc` + = help: consider moving `Assoc` to another trait + +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/gat-static-in-trait-object.rs:16:53 + | +LL | dyn for<'hr> Trait = &'s str>: Trait = &'s str>, + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/gat-static-in-trait-object.rs:9:10 + | +LL | trait Trait { + | ----- this trait is not dyn compatible... +LL | type Assoc<'a>: 'a; + | ^^^^^ ...because it contains generic associated type `Assoc` + = help: consider moving `Assoc` to another trait + +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/gat-static-in-trait-object.rs:20:14 + | +LL | tr:: Trait = &'s str>>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/gat-static-in-trait-object.rs:9:10 + | +LL | trait Trait { + | ----- this trait is not dyn compatible... +LL | type Assoc<'a>: 'a; + | ^^^^^ ...because it contains generic associated type `Assoc` + = help: consider moving `Assoc` to another trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/next-solver/supertrait-static-lifetime-object-bound.rs b/tests/ui/traits/next-solver/supertrait-static-lifetime-object-bound.rs new file mode 100644 index 0000000000000..b52b1c6cfcbb7 --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-static-lifetime-object-bound.rs @@ -0,0 +1,20 @@ +//! regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/295 + +//@ compile-flags: -Znext-solver + +#![forbid(unsafe_code)] + +trait Trait<'a>: 'a {} + +fn g<'s>(s: &'s String) -> &'static String +where + dyn for<'x> Trait<'x> + 's: Trait<'static>, +{ + s +} + +fn main() { + let r = g(&String::from("freed")); + //~^ ERROR temporary value dropped while borrowed + println!("{r}"); +} diff --git a/tests/ui/traits/next-solver/supertrait-static-lifetime-object-bound.stderr b/tests/ui/traits/next-solver/supertrait-static-lifetime-object-bound.stderr new file mode 100644 index 0000000000000..9463785a7da15 --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-static-lifetime-object-bound.stderr @@ -0,0 +1,18 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/supertrait-static-lifetime-object-bound.rs:17:16 + | +LL | let r = g(&String::from("freed")); + | ---^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + | +note: requirement that the value outlives `'static` introduced here + --> $DIR/supertrait-static-lifetime-object-bound.rs:11:33 + | +LL | dyn for<'x> Trait<'x> + 's: Trait<'static>, + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`.