mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #122206 - matthiaskrgr:rollup-4txx9wx, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #121201 (align_offset, align_to: no longer allow implementations to spuriously fail to align) - #122076 (Tweak the way we protect in-place function arguments in interpreters) - #122100 (Better comment for implicit captures in RPITIT) - #122157 (Add the new description field to Target::to_json, and add descriptions for some MSVC targets) - #122164 (Fix misaligned loads when loading UEFI arg pointers) - #122171 (Add some new solver tests) - #122172 (Don't ICE if we collect no RPITITs unless there are no unification errors) - #122197 (inspect formatter: add braces) - #122198 (Remove handling for previously dropped LLVM version) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
46b180ec24
@ -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),
|
||||
);
|
||||
|
@ -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
|
||||
|
@ -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)),
|
||||
|
@ -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.
|
||||
|
@ -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<OpTy<'tcx, M::Provenance>>> {
|
||||
) -> Vec<OpTy<'tcx, M::Provenance>> {
|
||||
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<FnArg<'tcx, M::Provenance>>> {
|
||||
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::<Vec<_>>()
|
||||
@ -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(..) => {
|
||||
|
@ -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<T> {}
|
||||
trait Lt<'a> {}
|
||||
trait BorrowInto<'a> {
|
||||
type Target;
|
||||
|
||||
impl<'a> Lt<'a> for () {}
|
||||
impl<T> Id<T> for T {}
|
||||
|
||||
fn free_fn_capture_hrtb_in_impl_trait()
|
||||
-> Box<for<'a> Id<impl Lt<'a>>> // error!
|
||||
{
|
||||
Box::new(())
|
||||
fn borrow_into(&'a self) -> Self::Target;
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn impl_fn_capture_hrtb_in_impl_trait()
|
||||
-> Box<for<'a> Id<impl Lt<'a>>> // error!
|
||||
{
|
||||
Box::new(())
|
||||
impl<'a> BorrowInto<'a> for () {
|
||||
type Target = &'a ();
|
||||
|
||||
fn borrow_into(&'a self) -> Self::Target {
|
||||
self
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
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<T> {}
|
||||
trait Lt<'a> {}
|
||||
|
||||
impl<'a> Lt<'a> for () {}
|
||||
impl<T> Id<T> for T {}
|
||||
|
||||
fn free_fn_capture_hrtb_in_impl_trait<'b>()
|
||||
-> Box<for<'a> Id<impl Lt<'b>>> // ok!
|
||||
{
|
||||
Box::new(())
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn impl_fn_capture_hrtb_in_impl_trait<'b>()
|
||||
-> Box<for<'a> Id<impl Lt<'b>>> // ok!
|
||||
{
|
||||
Box::new(())
|
||||
}
|
||||
fn opaque() -> impl for<'a> BorrowInto<'a, Target = impl Sized + 'a> {
|
||||
()
|
||||
}
|
||||
```
|
||||
|
@ -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
|
||||
|
||||
|
@ -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-
|
||||
|
@ -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),
|
||||
|
@ -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<Span>,
|
||||
#[note]
|
||||
pub decl_span: Span,
|
||||
pub bad_place: &'static str,
|
||||
}
|
||||
|
@ -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<F, R>(&mut self, func: F) -> R
|
||||
fn nested<F>(&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)?;
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -1326,9 +1326,7 @@ impl<T: ?Sized> *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<T: ?Sized> *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.
|
||||
|
@ -1589,9 +1589,7 @@ impl<T: ?Sized> *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<T: ?Sized> *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.
|
||||
|
@ -3786,11 +3786,8 @@ impl<T> [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> [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.
|
||||
|
@ -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<mir::BasicBlock>,
|
||||
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()
|
||||
|
@ -8,7 +8,7 @@ impl<T> Id<T> for T {}
|
||||
|
||||
fn free_fn_capture_hrtb_in_impl_trait()
|
||||
-> Box<for<'a> Id<impl Lt<'a>>>
|
||||
//~^ 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<for<'a> Id<impl Lt<'a>>>
|
||||
//~^ 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(())
|
||||
}
|
||||
|
@ -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<for<'a> Id<impl Lt<'a>>>
|
||||
| ^^
|
||||
|
|
||||
note: lifetime declared here
|
||||
--> $DIR/E0657.rs:10:16
|
||||
|
|
||||
LL | -> Box<for<'a> Id<impl Lt<'a>>>
|
||||
| ^^
|
||||
|
||||
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<for<'a> Id<impl Lt<'a>>>
|
||||
| ^^
|
||||
|
|
||||
note: lifetime declared here
|
||||
--> $DIR/E0657.rs:19:20
|
||||
|
|
||||
LL | -> Box<for<'a> Id<impl Lt<'a>>>
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
|
||||
| ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
|
||||
|
|
||||
note: lifetime declared here
|
||||
--> $DIR/implicit-capture-late.rs:10:36
|
||||
|
|
||||
LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
|
||||
|
18
tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
Normal file
18
tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
Normal file
@ -0,0 +1,18 @@
|
||||
struct Wrapper<'rom>(T);
|
||||
//~^ ERROR cannot find type `T` in this scope
|
||||
|
||||
trait Foo {
|
||||
fn bar() -> Wrapper<impl Sized>;
|
||||
//~^ 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() {}
|
@ -0,0 +1,67 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/opaque-and-lifetime-mismatch.rs:5:24
|
||||
|
|
||||
LL | fn bar() -> Wrapper<impl Sized>;
|
||||
| ^ 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<impl Sized>;
|
||||
| ^^^^^^^ ---------- 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<impl Sized>;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
= 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`.
|
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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.
|
||||
|
@ -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`.
|
||||
|
@ -0,0 +1,26 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
// Regression test for #119607.
|
||||
|
||||
pub trait IntoFoo {
|
||||
type Item;
|
||||
type IntoIter: Foo<Item = Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter;
|
||||
}
|
||||
|
||||
pub trait Foo {
|
||||
type Item;
|
||||
|
||||
fn next(self) -> Option<Self::Item>;
|
||||
}
|
||||
|
||||
pub fn foo<'a, Iter1, Elem1>(a: &'a Iter1)
|
||||
where
|
||||
&'a Iter1: IntoFoo<Item = Elem1>,
|
||||
{
|
||||
a.into_iter().next();
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
// Regression test for #119608.
|
||||
|
||||
pub trait Foo {}
|
||||
|
||||
pub trait Bar {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T: Foo> Bar for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
pub fn foo<I>(_input: <I as Bar>::Assoc)
|
||||
where
|
||||
I: Bar,
|
||||
<I as Bar>::Assoc: Foo,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -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 = ();
|
||||
|
@ -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`.
|
||||
|
@ -12,11 +12,11 @@ type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o]
|
||||
//~^ ERROR: unconstrained opaque type
|
||||
|
||||
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [*, 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<Item = impl Sized + Captures<'a>>; //~ [*, 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]
|
||||
|
@ -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<Item = impl Sized>;
|
||||
| ^^^^^^^^^^ `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<Item = impl Sized>;
|
||||
| ^^
|
||||
|
||||
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<Item = impl Sized + Captures<'a>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `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<Item = impl Sized + Captures<'a>>;
|
||||
|
Loading…
Reference in New Issue
Block a user