diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 16122e5557e9c..d1f32087908ee 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -260,35 +260,29 @@ pub unsafe fn create_module<'ll>( } if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection { - let behavior = if llvm_version >= (15, 0, 0) { - llvm::LLVMModFlagBehavior::Min - } else { - llvm::LLVMModFlagBehavior::Error - }; - if sess.target.arch == "aarch64" { llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"branch-target-enforcement".as_ptr().cast(), bti.into(), ); llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"sign-return-address".as_ptr().cast(), pac_ret.is_some().into(), ); let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"sign-return-address-all".as_ptr().cast(), pac_opts.leaf.into(), ); llvm::LLVMRustAddModuleFlag( llmod, - behavior, + llvm::LLVMModFlagBehavior::Min, c"sign-return-address-with-bkey".as_ptr().cast(), u32::from(pac_opts.key == PAuthKey::B), ); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 2161bf61daa41..1a3c70cedd0a1 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -510,11 +510,13 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Params for UEFI let param_handle = bx.get_param(0); let param_system_table = bx.get_param(1); + let ptr_size = bx.tcx().data_layout.pointer_size; + let ptr_align = bx.tcx().data_layout.pointer_align.abi; let arg_argc = bx.const_int(cx.type_isize(), 2); - let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE); - bx.store(param_handle, arg_argv, Align::ONE); - let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]); - bx.store(param_system_table, arg_argv_el1, Align::ONE); + let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align); + bx.store(param_handle, arg_argv, ptr_align); + let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes())); + bx.store(param_system_table, arg_argv_el1, ptr_align); (arg_argc, arg_argv) } else if cx.sess().target.main_needs_argc_argv { // Params from native `main()` used as args for rust start function diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 864241fbd4ac7..6736fc749c02d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -227,7 +227,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { if self.tcx.has_attr(def_id, sym::rustc_const_panic_str) || Some(def_id) == self.tcx.lang_items().begin_panic_fn() { - let args = self.copy_fn_args(args)?; + let args = self.copy_fn_args(args); // &str or &&str assert!(args.len() == 1); @@ -254,7 +254,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { return Ok(Some(new_instance)); } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() { - let args = self.copy_fn_args(args)?; + let args = self.copy_fn_args(args); // For align_offset, we replace the function call if the pointer has no address. match self.align_offset(instance, &args, dest, ret)? { ControlFlow::Continue(()) => return Ok(Some(instance)), diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index c798f1ce018cf..90a654a12294b 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -472,11 +472,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// argument/return value was actually copied or passed in-place.. fn protect_in_place_function_argument( ecx: &mut InterpCx<'mir, 'tcx, Self>, - place: &PlaceTy<'tcx, Self::Provenance>, + mplace: &MPlaceTy<'tcx, Self::Provenance>, ) -> InterpResult<'tcx> { // Without an aliasing model, all we can do is put `Uninit` into the place. // Conveniently this also ensures that the place actually points to suitable memory. - ecx.write_uninit(place) + ecx.write_uninit(mplace) } /// Called immediately before a new stack frame gets pushed. diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index f2b1ec425678d..bafb8cb0018c2 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,5 +1,7 @@ use std::borrow::Cow; +use either::Either; + use rustc_middle::{ mir, ty::{ @@ -29,14 +31,14 @@ pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> { Copy(OpTy<'tcx, Prov>), /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and /// make the place inaccessible for the duration of the function call. - InPlace(PlaceTy<'tcx, Prov>), + InPlace(MPlaceTy<'tcx, Prov>), } impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> { pub fn layout(&self) -> &TyAndLayout<'tcx> { match self { FnArg::Copy(op) => &op.layout, - FnArg::InPlace(place) => &place.layout, + FnArg::InPlace(mplace) => &mplace.layout, } } } @@ -44,13 +46,10 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> { impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the /// original memory occurs. - pub fn copy_fn_arg( - &self, - arg: &FnArg<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> { match arg { - FnArg::Copy(op) => Ok(op.clone()), - FnArg::InPlace(place) => self.place_to_op(place), + FnArg::Copy(op) => op.clone(), + FnArg::InPlace(mplace) => mplace.clone().into(), } } @@ -59,7 +58,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn copy_fn_args( &self, args: &[FnArg<'tcx, M::Provenance>], - ) -> InterpResult<'tcx, Vec>> { + ) -> Vec> { args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect() } @@ -70,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> { Ok(match arg { FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?), - FnArg::InPlace(place) => FnArg::InPlace(self.project_field(place, field)?), + FnArg::InPlace(mplace) => FnArg::InPlace(self.project_field(mplace, field)?), }) } @@ -238,10 +237,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, Vec>> { ops.iter() .map(|op| { - Ok(match &op.node { - mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?), - _ => FnArg::Copy(self.eval_operand(&op.node, None)?), - }) + let arg = match &op.node { + mir::Operand::Copy(_) | mir::Operand::Constant(_) => { + // Make a regular copy. + let op = self.eval_operand(&op.node, None)?; + FnArg::Copy(op) + } + mir::Operand::Move(place) => { + // If this place lives in memory, preserve its location. + // We call `place_to_op` which will be an `MPlaceTy` whenever there exists + // an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local` + // which can return a local even if that has an mplace.) + let place = self.eval_place(*place)?; + let op = self.place_to_op(&place)?; + + match op.as_mplace_or_imm() { + Either::Left(mplace) => FnArg::InPlace(mplace), + Either::Right(_imm) => { + // This argument doesn't live in memory, so there's no place + // to make inaccessible during the call. + // We rely on there not being any stray `PlaceTy` that would let the + // caller directly access this local! + // This is also crucial for tail calls, where we want the `FnArg` to + // stay valid when the old stack frame gets popped. + FnArg::Copy(op) + } + } + } + }; + + Ok(arg) }) .collect() } @@ -451,7 +476,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We work with a copy of the argument for now; if this is in-place argument passing, we // will later protect the source it comes from. This means the callee cannot observe if we // did in-place of by-copy argument passing, except for pointer equality tests. - let caller_arg_copy = self.copy_fn_arg(caller_arg)?; + let caller_arg_copy = self.copy_fn_arg(caller_arg); if !already_live { let local = callee_arg.as_local().unwrap(); let meta = caller_arg_copy.meta(); @@ -469,8 +494,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // specifically.) self.copy_op_allow_transmute(&caller_arg_copy, &callee_arg)?; // If this was an in-place pass, protect the place it comes from for the duration of the call. - if let FnArg::InPlace(place) = caller_arg { - M::protect_in_place_function_argument(self, place)?; + if let FnArg::InPlace(mplace) = caller_arg { + M::protect_in_place_function_argument(self, mplace)?; } Ok(()) } @@ -517,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::call_intrinsic( self, instance, - &self.copy_fn_args(args)?, + &self.copy_fn_args(args), destination, target, unwind, @@ -594,8 +619,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .map(|arg| ( arg.layout().ty, match arg { - FnArg::Copy(op) => format!("copy({:?})", *op), - FnArg::InPlace(place) => format!("in-place({:?})", *place), + FnArg::Copy(op) => format!("copy({op:?})"), + FnArg::InPlace(mplace) => format!("in-place({mplace:?})"), } )) .collect::>() @@ -717,8 +742,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { callee_ty: callee_fn_abi.ret.layout.ty }); } + // Protect return place for in-place return value passing. - M::protect_in_place_function_argument(self, &destination.clone().into())?; + M::protect_in_place_function_argument(self, &destination)?; // Don't forget to mark "initially live" locals as live. self.storage_live_for_always_live_locals()?; @@ -741,7 +767,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // An `InPlace` does nothing here, we keep the original receiver intact. We can't // really pass the argument in-place anyway, and we are constructing a new // `Immediate` receiver. - let mut receiver = self.copy_fn_arg(&args[0])?; + let mut receiver = self.copy_fn_arg(&args[0]); let receiver_place = loop { match receiver.layout.ty.kind() { ty::Ref(..) | ty::RawPtr(..) => { diff --git a/compiler/rustc_error_codes/src/error_codes/E0657.md b/compiler/rustc_error_codes/src/error_codes/E0657.md index 7fe48c5114790..477d8e8bb6dad 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0657.md +++ b/compiler/rustc_error_codes/src/error_codes/E0657.md @@ -1,57 +1,26 @@ -A lifetime bound on a trait implementation was captured at an incorrect place. +An `impl Trait` captured a higher-ranked lifetime, which is not supported. + +Currently, `impl Trait` types are only allowed to capture lifetimes from +their parent items, and not from any `for<'a>` binders in scope. Erroneous code example: ```compile_fail,E0657 -trait Id {} -trait Lt<'a> {} - -impl<'a> Lt<'a> for () {} -impl Id for T {} - -fn free_fn_capture_hrtb_in_impl_trait() - -> Box Id>> // error! -{ - Box::new(()) -} +trait BorrowInto<'a> { + type Target; -struct Foo; -impl Foo { - fn impl_fn_capture_hrtb_in_impl_trait() - -> Box Id>> // error! - { - Box::new(()) - } + fn borrow_into(&'a self) -> Self::Target; } -``` -Here, you have used the inappropriate lifetime in the `impl Trait`, -The `impl Trait` can only capture lifetimes bound at the fn or impl -level. +impl<'a> BorrowInto<'a> for () { + type Target = &'a (); -To fix this we have to define the lifetime at the function or impl -level and use that lifetime in the `impl Trait`. For example you can -define the lifetime at the function: - -``` -trait Id {} -trait Lt<'a> {} - -impl<'a> Lt<'a> for () {} -impl Id for T {} - -fn free_fn_capture_hrtb_in_impl_trait<'b>() - -> Box Id>> // ok! -{ - Box::new(()) + fn borrow_into(&'a self) -> Self::Target { + self + } } -struct Foo; -impl Foo { - fn impl_fn_capture_hrtb_in_impl_trait<'b>() - -> Box Id>> // ok! - { - Box::new(()) - } +fn opaque() -> impl for<'a> BorrowInto<'a, Target = impl Sized + 'a> { + () } ``` diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index e376411cd95c1..bad472dcb5c06 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -312,6 +312,10 @@ hir_analysis_only_current_traits_primitive = only traits defined in the current hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate +hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot capture {$bad_place} + .label = `impl Trait` implicitly captures all lifetimes in scope + .note = lifetime declared here + hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index f708c66cfa444..ec9e928ce593d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -521,14 +521,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ) .fold_with(&mut collector); - if !unnormalized_trait_sig.output().references_error() { - debug_assert_ne!( - collector.types.len(), - 0, - "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" - ); - } - let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig); trait_sig.error_reported()?; let trait_return_ty = trait_sig.output(); @@ -647,6 +639,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( } } + if !unnormalized_trait_sig.output().references_error() { + debug_assert!( + !collector.types.is_empty(), + "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`" + ); + } + // FIXME: This has the same issue as #108544, but since this isn't breaking // existing code, I'm not particularly inclined to do the same hack as above // where we process wf obligations manually. This can be fixed in a forward- diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 9464e3746e9be..7936621c86829 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -9,7 +9,6 @@ use core::ops::ControlFlow; use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -669,34 +668,47 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // and ban them. Type variables instantiated inside binders aren't // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. - let def = self.map.defs.get(&lifetime.hir_id).cloned(); - let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; - let Some(def_id) = def_id.as_local() else { continue }; - let hir_id = self.tcx.local_def_id_to_hir_id(def_id); - // Ensure that the parent of the def is an item, not HRTB - let parent_id = self.tcx.parent_hir_id(hir_id); - if !parent_id.is_owner() { - struct_span_code_err!( - self.tcx.dcx(), - lifetime.ident.span, - E0657, - "`impl Trait` can only capture lifetimes bound at the fn or impl level" - ) - .emit(); - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); - } - if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::OpaqueTy { .. }, .. - }) = self.tcx.hir_node(parent_id) + let def = self.map.defs.get(&lifetime.hir_id).copied(); + let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; + let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue }; + let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); + + let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) { - self.tcx.dcx().struct_span_err( - lifetime.ident.span, - "higher kinded lifetime bounds on nested opaque types are not supported yet", - ) - .with_span_note(self.tcx.def_span(def_id), "lifetime declared here") - .emit(); - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); - } + // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque + // it must be a reified late-bound lifetime from a trait goal. + hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy { .. }, .. + }) => "higher-ranked lifetime from outer `impl Trait`", + // Other items are fine. + hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => { + continue; + } + hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => { + "higher-ranked lifetime from function pointer" + } + hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => { + "higher-ranked lifetime from `dyn` type" + } + _ => "higher-ranked lifetime", + }; + + let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id) + { + let opaque_span = self.tcx.def_span(item_id.owner_id); + (opaque_span, Some(opaque_span)) + } else { + (lifetime.ident.span, None) + }; + + // Ensure that the parent of the def is an item, not HRTB + self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime { + span, + label, + decl_span: self.tcx.def_span(lifetime_def_id), + bad_place, + }); + self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } _ => intravisit::walk_ty(self, ty), diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 5330260fbf513..26349cd1c6551 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1607,3 +1607,15 @@ pub struct UnnamedFieldsReprFieldDefined { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] +pub struct OpaqueCapturesHigherRankedLifetime { + #[primary_span] + pub span: Span, + #[label] + pub label: Option, + #[note] + pub decl_span: Span, + pub bad_place: &'static str, +} diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 89c5eb517e565..8d3109a7b284c 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -4,22 +4,31 @@ pub(super) struct ProofTreeFormatter<'a, 'b> { f: &'a mut (dyn Write + 'b), } +enum IndentorState { + StartWithNewline, + OnNewline, + Inline, +} + /// A formatter which adds 4 spaces of indentation to its input before /// passing it on to its nested formatter. /// /// We can use this for arbitrary levels of indentation by nesting it. struct Indentor<'a, 'b> { f: &'a mut (dyn Write + 'b), - on_newline: bool, + state: IndentorState, } impl Write for Indentor<'_, '_> { fn write_str(&mut self, s: &str) -> std::fmt::Result { for line in s.split_inclusive('\n') { - if self.on_newline { - self.f.write_str(" ")?; + match self.state { + IndentorState::StartWithNewline => self.f.write_str("\n ")?, + IndentorState::OnNewline => self.f.write_str(" ")?, + IndentorState::Inline => {} } - self.on_newline = line.ends_with('\n'); + self.state = + if line.ends_with('\n') { IndentorState::OnNewline } else { IndentorState::Inline }; self.f.write_str(line)?; } @@ -32,11 +41,15 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProofTreeFormatter { f } } - fn nested(&mut self, func: F) -> R + fn nested(&mut self, func: F) -> std::fmt::Result where - F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R, + F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> std::fmt::Result, { - func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } }) + write!(self.f, " {{")?; + func(&mut ProofTreeFormatter { + f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline }, + })?; + writeln!(self.f, "}}") } pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result { @@ -47,7 +60,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", }, }; - writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; + write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation)) } @@ -69,7 +82,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { } CanonicalGoalEvaluationKind::Evaluation { revisions } => { for (n, step) in revisions.iter().enumerate() { - writeln!(self.f, "REVISION {n}")?; + write!(self.f, "REVISION {n}")?; self.nested(|this| this.format_evaluation_step(step))?; } writeln!(self.f, "RESULT: {:?}", eval.result) @@ -88,25 +101,25 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result { match &probe.kind { ProbeKind::Root { result } => { - writeln!(self.f, "ROOT RESULT: {result:?}") + write!(self.f, "ROOT RESULT: {result:?}") } ProbeKind::NormalizedSelfTyAssembly => { - writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") + write!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") } ProbeKind::UnsizeAssembly => { - writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") + write!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") } ProbeKind::UpcastProjectionCompatibility => { - writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") + write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") } ProbeKind::CommitIfOk => { - writeln!(self.f, "COMMIT_IF_OK:") + write!(self.f, "COMMIT_IF_OK:") } ProbeKind::MiscCandidate { name, result } => { - writeln!(self.f, "CANDIDATE {name}: {result:?}") + write!(self.f, "CANDIDATE {name}: {result:?}") } ProbeKind::TraitCandidate { source, result } => { - writeln!(self.f, "CANDIDATE {source:?}: {result:?}") + write!(self.f, "CANDIDATE {source:?}: {result:?}") } }?; @@ -137,7 +150,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?; for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() { - writeln!(self.f, "ITERATION {n}")?; + write!(self.f, "ITERATION {n}")?; self.nested(|this| { for goal_evaluation in iterations { this.format_goal_evaluation(goal_evaluation)?; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2e66d4d0ab097..3b6e15fad4661 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3253,6 +3253,7 @@ impl ToJson for Target { } target_val!(llvm_target); + target_val!(description); d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json()); target_val!(arch); target_val!(data_layout); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 12eba14925807..29c191fc9ab49 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -7,7 +7,7 @@ pub fn target() -> Target { Target { llvm_target: "aarch64-pc-windows-msvc".into(), - description: None, + description: Some("ARM64 Windows MSVC".into()), pointer_width: 64, data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(), arch: "aarch64".into(), diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index 28b2345874a0e..0ba486417ff56 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -23,7 +23,7 @@ pub fn target() -> Target { Target { llvm_target: "i686-pc-windows-msvc".into(), - description: None, + description: Some("32-bit MSVC (Windows 7+)".into()), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index 1990c91bdcc33..081b4c5364cf1 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -23,7 +23,7 @@ pub fn target() -> Target { Target { llvm_target: "i686-pc-windows-msvc".into(), - description: None, + description: Some("32-bit Windows 7 support".into()), pointer_width: 32, data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32" diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs index 31a01f5cbffc0..bb2555bb1a5b1 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs @@ -13,7 +13,7 @@ pub fn target() -> Target { Target { llvm_target: "thumbv7a-pc-windows-msvc".into(), - description: None, + description: Some("ARM32 Windows MSVC".into()), pointer_width: 32, data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: "arm".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index c8d01a912cb8e..c066c453feb41 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -10,7 +10,7 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), - description: None, + description: Some("64-bit MSVC (Windows 7+)".into()), pointer_width: 64, data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs index f0c1afcdce86f..813802e232043 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs @@ -9,7 +9,7 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-win7-windows-msvc".into(), - description: None, + description: Some("64-bit Windows 7 support".into()), pointer_width: 64, data_layout: "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f2566fe9bccae..0c69bf2aef9c1 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1326,9 +1326,7 @@ impl *const T { /// `align`. /// /// If it is not possible to align the pointer, the implementation returns - /// `usize::MAX`. It is permissible for the implementation to *always* - /// return `usize::MAX`. Only your algorithm's performance can depend - /// on getting a usable offset here, not its correctness. + /// `usize::MAX`. /// /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be /// used with the `wrapping_add` method. @@ -1337,6 +1335,15 @@ impl *const T { /// beyond the allocation that the pointer points into. It is up to the caller to ensure that /// the returned offset is correct in all terms other than alignment. /// + /// When this is called during compile-time evaluation (which is unstable), the implementation + /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the + /// actual alignment of pointers is not known yet during compile-time, so an offset with + /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; + /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet + /// known, so the execution has to be correct for either choice. It is therefore impossible to + /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual + /// for unstable APIs.) + /// /// # Panics /// /// The function panics if `align` is not a power-of-two. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 8b0b22a02f2ba..5ce3b1f298cba 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1589,9 +1589,7 @@ impl *mut T { /// `align`. /// /// If it is not possible to align the pointer, the implementation returns - /// `usize::MAX`. It is permissible for the implementation to *always* - /// return `usize::MAX`. Only your algorithm's performance can depend - /// on getting a usable offset here, not its correctness. + /// `usize::MAX`. /// /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be /// used with the `wrapping_add` method. @@ -1600,6 +1598,15 @@ impl *mut T { /// beyond the allocation that the pointer points into. It is up to the caller to ensure that /// the returned offset is correct in all terms other than alignment. /// + /// When this is called during compile-time evaluation (which is unstable), the implementation + /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the + /// actual alignment of pointers is not known yet during compile-time, so an offset with + /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; + /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet + /// known, so the execution has to be correct for either choice. It is therefore impossible to + /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual + /// for unstable APIs.) + /// /// # Panics /// /// The function panics if `align` is not a power-of-two. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 643b7971a662d..2d5e091feaae8 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3786,11 +3786,8 @@ impl [T] { /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. How exactly the slice is split up is not - /// specified; the middle part may be smaller than necessary. However, if this fails to return a - /// maximal middle part, that is because code is running in a context where performance does not - /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running - /// in a default (debug or release) execution *will* return a maximal middle part. + /// slice of a new type, and the suffix slice. The middle part will be as big as possible under + /// the given alignment constraint and element size. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -3854,11 +3851,8 @@ impl [T] { /// types is maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. How exactly the slice is split up is not - /// specified; the middle part may be smaller than necessary. However, if this fails to return a - /// maximal middle part, that is because code is running in a context where performance does not - /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running - /// in a default (debug or release) execution *will* return a maximal middle part. + /// slice of a new type, and the suffix slice. The middle part will be as big as possible under + /// the given alignment constraint and element size. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index c3c3a81585614..19d02c6f74620 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -8,7 +8,6 @@ use std::fmt; use std::path::Path; use std::process; -use either::Either; use rand::rngs::StdRng; use rand::Rng; use rand::SeedableRng; @@ -962,7 +961,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the // foreign function // Any needed call to `goto_block` will be performed by `emulate_foreign_item`. - let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit? let link_name = ecx.item_link_name(instance.def_id()); return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind); } @@ -981,7 +980,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ret: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit? + let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit? ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind) } @@ -1334,18 +1333,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn protect_in_place_function_argument( ecx: &mut InterpCx<'mir, 'tcx, Self>, - place: &PlaceTy<'tcx, Provenance>, + place: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { // If we have a borrow tracker, we also have it set up protection so that all reads *and // writes* during this call are insta-UB. let protected_place = if ecx.machine.borrow_tracker.is_some() { - // Have to do `to_op` first because a `Place::Local` doesn't imply the local doesn't have an address. - if let Either::Left(place) = ecx.place_to_op(place)?.as_mplace_or_imm() { - ecx.protect_place(&place)?.into() - } else { - // Locals that don't have their address taken are as protected as they can ever be. - place.clone() - } + ecx.protect_place(&place)?.into() } else { // No borrow tracker. place.clone() diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs index cb11de13f73c6..212c1d9e581a2 100644 --- a/tests/ui/error-codes/E0657.rs +++ b/tests/ui/error-codes/E0657.rs @@ -8,7 +8,7 @@ impl Id for T {} fn free_fn_capture_hrtb_in_impl_trait() -> Box Id>> - //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type { Box::new(()) } @@ -17,7 +17,7 @@ struct Foo; impl Foo { fn impl_fn_capture_hrtb_in_impl_trait() -> Box Id>> - //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type { Box::new(()) } diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr index df76b45a5891f..c539007cdcf19 100644 --- a/tests/ui/error-codes/E0657.stderr +++ b/tests/ui/error-codes/E0657.stderr @@ -1,14 +1,26 @@ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type --> $DIR/E0657.rs:10:31 | LL | -> Box Id>> | ^^ + | +note: lifetime declared here + --> $DIR/E0657.rs:10:16 + | +LL | -> Box Id>> + | ^^ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type --> $DIR/E0657.rs:19:35 | LL | -> Box Id>> | ^^ + | +note: lifetime declared here + --> $DIR/E0657.rs:19:20 + | +LL | -> Box Id>> + | ^^ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs index 06c3d9ad434e4..a9ea657f10e2c 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -2,19 +2,19 @@ use std::fmt::Debug; fn a() -> impl Fn(&u8) -> (impl Debug + '_) { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 959d6577d9a60..bdb099619b76f 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -10,7 +10,7 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ~~~~~~~ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { @@ -31,7 +31,7 @@ LL | |x| x | |return type of closure is impl Debug + '2 | has type `&'1 u8` -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:10:52 | LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { @@ -52,7 +52,7 @@ LL | |x| x | |return type of closure is impl Debug + '2 | has type `&'1 u8` -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:16:52 | LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { @@ -75,4 +75,5 @@ LL | |x| x error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0657. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs index a4a1f1dcee120..ef9d87335097f 100644 --- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs +++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; fn a() -> impl Fn(&u8) -> impl Debug + '_ { //~^ ERROR ambiguous `+` in a type - //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~| ERROR cannot capture higher-ranked lifetime from outer `impl Trait` |x| x //~^ ERROR lifetime may not live long enough } diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr index e18e89700b4e9..3881b37a0cbf4 100644 --- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr +++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -10,7 +10,7 @@ error: ambiguous `+` in a type LL | fn b() -> impl Fn() -> impl Debug + Send { | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-parsing-ambiguities.rs:4:40 | LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { @@ -33,3 +33,4 @@ LL | |x| x error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr index 2fb5ebb65418c..080750f849767 100644 --- a/tests/ui/impl-trait/implicit-capture-late.stderr +++ b/tests/ui/impl-trait/implicit-capture-late.stderr @@ -1,4 +1,10 @@ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/implicit-capture-late.rs:10:55 + | +LL | fn foo(x: Vec) -> Box Deref> { + | ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here --> $DIR/implicit-capture-late.rs:10:36 | LL | fn foo(x: Vec) -> Box Deref> { diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs new file mode 100644 index 0000000000000..6f0dbd752b0c2 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs @@ -0,0 +1,18 @@ +struct Wrapper<'rom>(T); +//~^ ERROR cannot find type `T` in this scope + +trait Foo { + fn bar() -> Wrapper; + //~^ ERROR missing lifetime specifier + //~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied +} + +impl Foo for () { + fn bar() -> i32 { + //~^ ERROR method `bar` has an incompatible type for trait + //~| ERROR method `bar` has an incompatible return type for trait + 0 + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr new file mode 100644 index 0000000000000..d30557c8a7bc2 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr @@ -0,0 +1,67 @@ +error[E0106]: missing lifetime specifier + --> $DIR/opaque-and-lifetime-mismatch.rs:5:24 + | +LL | fn bar() -> Wrapper; + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values + | +LL | fn bar() -> Wrapper<'static, impl Sized>; + | ++++++++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/opaque-and-lifetime-mismatch.rs:1:22 + | +LL | struct Wrapper<'rom>(T); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Wrapper<'rom, T>(T); + | +++ + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/opaque-and-lifetime-mismatch.rs:5:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^ ---------- help: remove this generic argument + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/opaque-and-lifetime-mismatch.rs:1:8 + | +LL | struct Wrapper<'rom>(T); + | ^^^^^^^ + +error[E0053]: method `bar` has an incompatible return type for trait + --> $DIR/opaque-and-lifetime-mismatch.rs:11:17 + | +LL | fn bar() -> i32 { + | ^^^ + | | + | expected `Wrapper<'static>`, found `i32` + | return type in trait + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/opaque-and-lifetime-mismatch.rs:11:17 + | +LL | fn bar() -> i32 { + | ^^^ + | | + | expected `Wrapper<'static>`, found `i32` + | help: change the output type to match the trait: `Wrapper<'static>` + | +note: type in trait + --> $DIR/opaque-and-lifetime-mismatch.rs:5:17 + | +LL | fn bar() -> Wrapper; + | ^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn() -> Wrapper<'static>` + found signature `fn() -> i32` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0053, E0106, E0107, E0412. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs index 8d7a1d56f8320..13c0038ce4340 100644 --- a/tests/ui/impl-trait/issues/issue-54895.rs +++ b/tests/ui/impl-trait/issues/issue-54895.rs @@ -13,7 +13,7 @@ impl<'a> Trait<'a> for X { } fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` X(()) } diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.stderr index 999ffd5214154..64b425328e3ab 100644 --- a/tests/ui/impl-trait/issues/issue-54895.stderr +++ b/tests/ui/impl-trait/issues/issue-54895.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-54895.rs:15:53 | LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { @@ -12,3 +12,4 @@ LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs index 6dc8935c77708..939eca82a8f6d 100644 --- a/tests/ui/impl-trait/issues/issue-67830.rs +++ b/tests/ui/impl-trait/issues/issue-67830.rs @@ -19,7 +19,7 @@ where struct A; fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` Wrap(|a| Some(a).into_iter()) //~^ ERROR implementation of `FnOnce` is not general enough //~| ERROR implementation of `FnOnce` is not general enough diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr index 546198b8a1037..ef513a40cf39f 100644 --- a/tests/ui/impl-trait/issues/issue-67830.stderr +++ b/tests/ui/impl-trait/issues/issue-67830.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-67830.rs:21:62 | LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { @@ -31,3 +31,4 @@ LL | Wrap(|a| Some(a).into_iter()) error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs index f4354d1b2aef0..7ff08d8174f8e 100644 --- a/tests/ui/impl-trait/issues/issue-88236-2.rs +++ b/tests/ui/impl-trait/issues/issue-88236-2.rs @@ -13,17 +13,17 @@ impl<'a> Hrtb<'a> for &'a () { } fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` &() //~^ ERROR implementation of `Hrtb` is not general enough //~| ERROR implementation of `Hrtb` is not general enough } fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` x //~^ ERROR implementation of `Hrtb` is not general enough //~| ERROR implementation of `Hrtb` is not general enough diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr index 1f5029f9d9fa7..09fd58056a561 100644 --- a/tests/ui/impl-trait/issues/issue-88236-2.stderr +++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236-2.rs:15:61 | LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} @@ -10,7 +10,7 @@ note: lifetime declared here LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236-2.rs:18:80 | LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { @@ -40,7 +40,7 @@ LL | &() = note: `Hrtb<'a>` would have to be implemented for the type `&()` = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0` -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236-2.rs:25:78 | LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { @@ -90,3 +90,4 @@ LL | x error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-88236.rs b/tests/ui/impl-trait/issues/issue-88236.rs index 36d12417354a2..e782a87657346 100644 --- a/tests/ui/impl-trait/issues/issue-88236.rs +++ b/tests/ui/impl-trait/issues/issue-88236.rs @@ -13,6 +13,6 @@ impl<'a> Hrtb<'a> for &'a () { } fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-88236.stderr b/tests/ui/impl-trait/issues/issue-88236.stderr index 6cf1a42d6a997..5dee5f88c89f2 100644 --- a/tests/ui/impl-trait/issues/issue-88236.stderr +++ b/tests/ui/impl-trait/issues/issue-88236.stderr @@ -1,4 +1,4 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/issue-88236.rs:15:61 | LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} @@ -12,3 +12,4 @@ LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs index a3eca741daad9..c10bfbfe4dc1a 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.rs +++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs @@ -23,18 +23,18 @@ impl Qux<'_> for () {} // This is not supported. fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` // This is not supported. fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` //~| ERROR implementation of `Bar` is not general enough fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` //~| ERROR: the trait bound `for<'a> &'a (): Qux<'_>` is not satisfied // This should resolve. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index 4fc22712de616..2779694a51711 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -29,7 +29,7 @@ help: consider introducing lifetime `'b` here LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} | ++++ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:25:69 | LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} @@ -41,7 +41,7 @@ note: lifetime declared here LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:29:68 | LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} @@ -53,7 +53,7 @@ note: lifetime declared here LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} | ^^ -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:32:74 | LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} @@ -74,7 +74,7 @@ LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a = note: `()` must implement `Bar<'a>` = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` -error: higher kinded lifetime bounds on nested opaque types are not supported yet +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/nested-rpit-hrtb.rs:36:73 | LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} @@ -133,5 +133,5 @@ LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Si error: aborting due to 12 previous errors -Some errors have detailed explanations: E0261, E0277. +Some errors have detailed explanations: E0261, E0277, E0657. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs new file mode 100644 index 0000000000000..ddda1a71d7ee4 --- /dev/null +++ b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs @@ -0,0 +1,26 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for #119607. + +pub trait IntoFoo { + type Item; + type IntoIter: Foo; + + fn into_iter(self) -> Self::IntoIter; +} + +pub trait Foo { + type Item; + + fn next(self) -> Option; +} + +pub fn foo<'a, Iter1, Elem1>(a: &'a Iter1) +where + &'a Iter1: IntoFoo, +{ + a.into_iter().next(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs new file mode 100644 index 0000000000000..1b9e9866cd60e --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for #119608. + +pub trait Foo {} + +pub trait Bar { + type Assoc; +} + +impl Bar for T { + type Assoc = T; +} + +pub fn foo(_input: ::Assoc) +where + I: Bar, + ::Assoc: Foo, +{ +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs index b030ce39d1dfc..1ff200680be5e 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs @@ -7,7 +7,7 @@ pub trait Trait<'a> { trait Test<'a> {} pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; -//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` impl Trait<'_> for () { type Assoc = (); diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr index 706de37e9f3c7..09f6fba79cfdf 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr @@ -1,8 +1,8 @@ -error: higher kinded lifetime bounds on nested opaque types are not supported yet - --> $DIR/escaping-bound-var.rs:9:25 +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/escaping-bound-var.rs:9:47 | LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; - | ^^ + | ^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope | note: lifetime declared here --> $DIR/escaping-bound-var.rs:9:25 @@ -12,3 +12,4 @@ LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index 457c4affb9d22..4b9fa67fd64c7 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -12,11 +12,11 @@ type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o] //~^ ERROR: unconstrained opaque type type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ [*, o, o] -//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type type Captured<'a> = dyn for<'b> Iterator>; //~ [*, o, o] -//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level +//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o] diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index eafe583e89c26..1aaf36223b7f5 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -1,10 +1,22 @@ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/variance.rs:14:56 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; + | ^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here --> $DIR/variance.rs:14:36 | LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; | ^^ -error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/variance.rs:18:49 + | +LL | type Captured<'a> = dyn for<'b> Iterator>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here --> $DIR/variance.rs:18:29 | LL | type Captured<'a> = dyn for<'b> Iterator>;