mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Correctly deny late-bound lifetimes from parent in anon consts and TAITs
This commit is contained in:
parent
ab45885dec
commit
52aff53812
@ -21,12 +21,16 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
|
||||
.label = deref recursion limit reached
|
||||
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
|
||||
|
||||
hir_analysis_cannot_capture_late_bound_const_in_anon_const =
|
||||
cannot capture late-bound const parameter in a constant
|
||||
hir_analysis_cannot_capture_late_bound_const =
|
||||
cannot capture late-bound const parameter in {$what}
|
||||
.label = parameter defined here
|
||||
|
||||
hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
|
||||
cannot capture late-bound type parameter in a constant
|
||||
hir_analysis_cannot_capture_late_bound_lifetime =
|
||||
cannot capture late-bound lifetime in {$what}
|
||||
.label = lifetime defined here
|
||||
|
||||
hir_analysis_cannot_capture_late_bound_ty =
|
||||
cannot capture late-bound type parameter in {$what}
|
||||
.label = parameter defined here
|
||||
|
||||
hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
|
||||
|
@ -268,9 +268,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// (*) -- not late-bound, won't change
|
||||
}
|
||||
|
||||
Some(rbv::ResolvedArg::Error(_)) => {
|
||||
bug!("only ty/ct should resolve as ResolvedArg::Error")
|
||||
}
|
||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar),
|
||||
|
||||
None => {
|
||||
self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
|
||||
|
@ -158,13 +158,14 @@ enum Scope<'a> {
|
||||
s: ScopeRef<'a>,
|
||||
},
|
||||
|
||||
/// Disallows capturing non-lifetime binders from parent scopes.
|
||||
/// Disallows capturing late-bound vars from parent scopes.
|
||||
///
|
||||
/// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
|
||||
/// since we don't do something more correct like replacing any captured
|
||||
/// late-bound vars with early-bound params in the const's own generics.
|
||||
AnonConstBoundary {
|
||||
LateBoundary {
|
||||
s: ScopeRef<'a>,
|
||||
what: &'static str,
|
||||
},
|
||||
|
||||
Root {
|
||||
@ -216,7 +217,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
||||
Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
|
||||
Scope::LateBoundary { s: _, what } => {
|
||||
f.debug_struct("LateBoundary").field("what", what).finish()
|
||||
}
|
||||
Scope::Root { opt_parent_item } => {
|
||||
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
|
||||
}
|
||||
@ -318,7 +321,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
break (vec![], BinderScopeType::Normal);
|
||||
}
|
||||
|
||||
Scope::ObjectLifetimeDefault { s, .. } | Scope::AnonConstBoundary { s } => {
|
||||
Scope::ObjectLifetimeDefault { s, .. } | Scope::LateBoundary { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
|
||||
@ -697,9 +700,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||
}) => {
|
||||
intravisit::walk_ty(self, ty);
|
||||
|
||||
// Elided lifetimes are not allowed in non-return
|
||||
// position impl Trait
|
||||
let scope = Scope::TraitRefBoundary { s: self.scope };
|
||||
// Elided lifetimes and late-bound lifetimes (from the parent)
|
||||
// are not allowed in non-return position impl Trait
|
||||
let scope = Scope::LateBoundary {
|
||||
s: &Scope::TraitRefBoundary { s: self.scope },
|
||||
what: "type alias impl trait",
|
||||
};
|
||||
self.with(scope, |this| intravisit::walk_item(this, opaque_ty));
|
||||
|
||||
return;
|
||||
@ -979,7 +985,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
||||
self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
|
||||
self.with(Scope::LateBoundary { s: self.scope, what: "constant" }, |this| {
|
||||
intravisit::walk_anon_const(this, c);
|
||||
});
|
||||
}
|
||||
@ -1174,6 +1180,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
let mut late_depth = 0;
|
||||
let mut scope = self.scope;
|
||||
let mut outermost_body = None;
|
||||
let mut crossed_late_boundary = None;
|
||||
let result = loop {
|
||||
match *scope {
|
||||
Scope::Body { id, s } => {
|
||||
@ -1258,8 +1265,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
|
||||
Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s, .. }
|
||||
| Scope::AnonConstBoundary { s } => {
|
||||
| Scope::TraitRefBoundary { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
|
||||
Scope::LateBoundary { s, what } => {
|
||||
crossed_late_boundary = Some(what);
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
@ -1268,6 +1279,22 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
if let Some(mut def) = result {
|
||||
if let ResolvedArg::EarlyBound(..) = def {
|
||||
// Do not free early-bound regions, only late-bound ones.
|
||||
} else if let ResolvedArg::LateBound(_, _, param_def_id) = def
|
||||
&& let Some(what) = crossed_late_boundary
|
||||
{
|
||||
let use_span = lifetime_ref.ident.span;
|
||||
let def_span = self.tcx.def_span(param_def_id);
|
||||
let guar = match self.tcx.def_kind(param_def_id) {
|
||||
DefKind::LifetimeParam => {
|
||||
self.tcx.sess.emit_err(errors::CannotCaptureLateBound::Lifetime {
|
||||
use_span,
|
||||
def_span,
|
||||
what,
|
||||
})
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
def = ResolvedArg::Error(guar);
|
||||
} else if let Some(body_id) = outermost_body {
|
||||
let fn_id = self.tcx.hir().body_owner(body_id);
|
||||
match self.tcx.hir().get(fn_id) {
|
||||
@ -1322,7 +1349,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
| Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s, .. }
|
||||
| Scope::AnonConstBoundary { s } => {
|
||||
| Scope::LateBoundary { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
@ -1341,7 +1368,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
// search.
|
||||
let mut late_depth = 0;
|
||||
let mut scope = self.scope;
|
||||
let mut crossed_anon_const = false;
|
||||
let mut crossed_late_boundary = None;
|
||||
|
||||
let result = loop {
|
||||
match *scope {
|
||||
@ -1376,28 +1403,32 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
scope = s;
|
||||
}
|
||||
|
||||
Scope::AnonConstBoundary { s } => {
|
||||
crossed_anon_const = true;
|
||||
Scope::LateBoundary { s, what } => {
|
||||
crossed_late_boundary = Some(what);
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(def) = result {
|
||||
if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
|
||||
if let ResolvedArg::LateBound(..) = def
|
||||
&& let Some(what) = crossed_late_boundary
|
||||
{
|
||||
let use_span = self.tcx.hir().span(hir_id);
|
||||
let def_span = self.tcx.def_span(param_def_id);
|
||||
let guar = match self.tcx.def_kind(param_def_id) {
|
||||
DefKind::ConstParam => {
|
||||
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
|
||||
self.tcx.sess.emit_err(errors::CannotCaptureLateBound::Const {
|
||||
use_span,
|
||||
def_span,
|
||||
what,
|
||||
})
|
||||
}
|
||||
DefKind::TyParam => {
|
||||
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
|
||||
self.tcx.sess.emit_err(errors::CannotCaptureLateBound::Type {
|
||||
use_span,
|
||||
def_span,
|
||||
what,
|
||||
})
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@ -1446,7 +1477,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
| Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s, .. }
|
||||
| Scope::AnonConstBoundary { s } => {
|
||||
| Scope::LateBoundary { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
@ -1526,7 +1557,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
| Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s, .. }
|
||||
| Scope::AnonConstBoundary { s } => {
|
||||
| Scope::LateBoundary { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
@ -1831,7 +1862,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
|
||||
Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s, .. }
|
||||
| Scope::AnonConstBoundary { s } => {
|
||||
| Scope::LateBoundary { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
}
|
||||
|
@ -430,20 +430,30 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub(crate) enum CannotCaptureLateBoundInAnonConst {
|
||||
#[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)]
|
||||
pub(crate) enum CannotCaptureLateBound {
|
||||
#[diag(hir_analysis_cannot_capture_late_bound_ty)]
|
||||
Type {
|
||||
#[primary_span]
|
||||
use_span: Span,
|
||||
#[label]
|
||||
def_span: Span,
|
||||
what: &'static str,
|
||||
},
|
||||
#[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)]
|
||||
#[diag(hir_analysis_cannot_capture_late_bound_const)]
|
||||
Const {
|
||||
#[primary_span]
|
||||
use_span: Span,
|
||||
#[label]
|
||||
def_span: Span,
|
||||
what: &'static str,
|
||||
},
|
||||
#[diag(hir_analysis_cannot_capture_late_bound_lifetime)]
|
||||
Lifetime {
|
||||
#[primary_span]
|
||||
use_span: Span,
|
||||
#[label]
|
||||
def_span: Span,
|
||||
what: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,13 @@
|
||||
// failure-status: 1
|
||||
// known-bug: unknown
|
||||
// error-pattern:internal compiler error
|
||||
// normalize-stderr-test "internal compiler error.*" -> ""
|
||||
// normalize-stderr-test "DefId\([^)]*\)" -> "..."
|
||||
// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
|
||||
// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
|
||||
// normalize-stderr-test "thread.*panicked.*:\n.*\n" -> ""
|
||||
// normalize-stderr-test "stack backtrace:\n" -> ""
|
||||
// normalize-stderr-test "\s\d{1,}: .*\n" -> ""
|
||||
// normalize-stderr-test "\s at .*\n" -> ""
|
||||
// normalize-stderr-test ".*note: Some details.*\n" -> ""
|
||||
// normalize-stderr-test "\n[ ]*\n" -> ""
|
||||
// normalize-stderr-test "compiler/.*: projection" -> "projection"
|
||||
// normalize-stderr-test ".*omitted \d{1,} frame.*\n" -> ""
|
||||
// normalize-stderr-test "error: [\s\n]*query stack during panic:\n" -> ""
|
||||
// this should run-pass
|
||||
|
||||
// If we want this to compile, then we'd need to do something like RPITs do,
|
||||
// where nested associated constants have early-bound versions of their captured
|
||||
// late-bound vars inserted into their generics. This gives us substitutable
|
||||
// lifetimes to actually use when borrow-checking the associated const, which is
|
||||
// lowered as a totally separate body from its parent. Since this doesn't exist,
|
||||
// so we should just error rather than resolving this late-bound var with no
|
||||
// binder to actually attach it to, or worse, as a free region that can't even be
|
||||
// substituted correctly, and ICEing. - @compiler-errors
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
@ -1,10 +1,20 @@
|
||||
#0 [mir_borrowck] borrow-checking `test::{closure#0}::{constant#1}`
|
||||
#1 [mir_drops_elaborated_and_const_checked] elaborating drops for `test::{closure#0}::{constant#1}`
|
||||
#2 [mir_for_ctfe] caching mir of `test::{closure#0}::{constant#1}` for CTFE
|
||||
#3 [eval_to_allocation_raw] const-evaluating + checking `test::{closure#0}::{constant#1}`
|
||||
#4 [eval_to_allocation_raw] const-evaluating + checking `test::{closure#0}::{constant#1}`
|
||||
#5 [eval_to_valtree] evaluating type-level constant
|
||||
#6 [typeck] type-checking `test`
|
||||
#7 [analysis] running analysis passes on this crate
|
||||
end of query stack
|
||||
error: aborting due to previous error
|
||||
error: cannot capture late-bound lifetime in constant
|
||||
--> $DIR/in_closure.rs:24:29
|
||||
|
|
||||
LL | fn test<'a>() {
|
||||
| -- lifetime defined here
|
||||
LL | let _ = || {
|
||||
LL | let _: [u8; inner::<'a>()];
|
||||
| ^^
|
||||
|
||||
error: cannot capture late-bound lifetime in constant
|
||||
--> $DIR/in_closure.rs:25:29
|
||||
|
|
||||
LL | fn test<'a>() {
|
||||
| -- lifetime defined here
|
||||
...
|
||||
LL | let _ = [0; inner::<'a>()];
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,22 +1,13 @@
|
||||
// failure-status: 101
|
||||
// known-bug: unknown
|
||||
// error-pattern:internal compiler error
|
||||
// normalize-stderr-test "internal compiler error.*" -> ""
|
||||
// normalize-stderr-test "DefId\([^)]*\)" -> "..."
|
||||
// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
|
||||
// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
|
||||
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
|
||||
// normalize-stderr-test "thread.*panicked.*:\n.*\n" -> ""
|
||||
// normalize-stderr-test "stack backtrace:\n" -> ""
|
||||
// normalize-stderr-test "\s\d{1,}: .*\n" -> ""
|
||||
// normalize-stderr-test "\s at .*\n" -> ""
|
||||
// normalize-stderr-test ".*note: Some details.*\n" -> ""
|
||||
// normalize-stderr-test "\n\n[ ]*\n" -> ""
|
||||
// normalize-stderr-test "compiler/.*: projection" -> "projection"
|
||||
// normalize-stderr-test ".*omitted \d{1,} frame.*\n" -> ""
|
||||
// normalize-stderr-test "error: [\s\n]*query stack" -> "error: query stack"
|
||||
|
||||
// If we want this to compile, then we'd need to do something like RPITs do,
|
||||
// where nested associated constants have early-bound versions of their captured
|
||||
// late-bound vars inserted into their generics. This gives us substitutable
|
||||
// lifetimes to actually use when borrow-checking the associated const, which is
|
||||
// lowered as a totally separate body from its parent. Since this doesn't exist,
|
||||
// so we should just error rather than resolving this late-bound var with no
|
||||
// binder to actually attach it to, or worse, as a free region that can't even be
|
||||
// substituted correctly, and ICEing. - @compiler-errors
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
@ -1,12 +1,19 @@
|
||||
error: query stack during panic:
|
||||
#0 [mir_borrowck] borrow-checking `test::{constant#1}`
|
||||
#1 [mir_drops_elaborated_and_const_checked] elaborating drops for `test::{constant#1}`
|
||||
#2 [mir_for_ctfe] caching mir of `test::{constant#1}` for CTFE
|
||||
#3 [eval_to_allocation_raw] const-evaluating + checking `test::{constant#1}`
|
||||
#4 [eval_to_allocation_raw] const-evaluating + checking `test::{constant#1}`
|
||||
#5 [eval_to_valtree] evaluating type-level constant
|
||||
#6 [typeck] type-checking `test`
|
||||
#7 [analysis] running analysis passes on this crate
|
||||
end of query stack
|
||||
error: aborting due to previous error
|
||||
error: cannot capture late-bound lifetime in constant
|
||||
--> $DIR/simple.rs:20:25
|
||||
|
|
||||
LL | fn test<'a>() {
|
||||
| -- lifetime defined here
|
||||
LL | let _: [u8; inner::<'a>()];
|
||||
| ^^
|
||||
|
||||
error: cannot capture late-bound lifetime in constant
|
||||
--> $DIR/simple.rs:21:25
|
||||
|
|
||||
LL | fn test<'a>() {
|
||||
| -- lifetime defined here
|
||||
LL | let _: [u8; inner::<'a>()];
|
||||
LL | let _ = [0; inner::<'a>()];
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
13
tests/ui/consts/escaping-bound-var.rs
Normal file
13
tests/ui/consts/escaping-bound-var.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#![feature(generic_const_exprs)]
|
||||
//~^ WARN the feature `generic_const_exprs` is incomplete
|
||||
|
||||
fn test<'a>(
|
||||
_: &'a (),
|
||||
) -> [(); {
|
||||
let x: &'a ();
|
||||
//~^ ERROR cannot capture late-bound lifetime in constant
|
||||
1
|
||||
}] {
|
||||
}
|
||||
|
||||
fn main() {}
|
20
tests/ui/consts/escaping-bound-var.stderr
Normal file
20
tests/ui/consts/escaping-bound-var.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/escaping-bound-var.rs:1:12
|
||||
|
|
||||
LL | #![feature(generic_const_exprs)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: cannot capture late-bound lifetime in constant
|
||||
--> $DIR/escaping-bound-var.rs:7:13
|
||||
|
|
||||
LL | fn test<'a>(
|
||||
| -- lifetime defined here
|
||||
...
|
||||
LL | let x: &'a ();
|
||||
| ^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
@ -4,7 +4,7 @@
|
||||
fn b()
|
||||
where
|
||||
for<const C: usize> [(); C]: Copy,
|
||||
//~^ ERROR cannot capture late-bound const parameter in a constant
|
||||
//~^ ERROR cannot capture late-bound const parameter in constant
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ LL | #![feature(non_lifetime_binders)]
|
||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: cannot capture late-bound const parameter in a constant
|
||||
error: cannot capture late-bound const parameter in constant
|
||||
--> $DIR/capture-late-ct-in-anon.rs:6:30
|
||||
|
|
||||
LL | for<const C: usize> [(); C]: Copy,
|
||||
|
@ -5,7 +5,7 @@
|
||||
fn foo() -> usize
|
||||
where
|
||||
for<T> [i32; { let _: T = todo!(); 0 }]:,
|
||||
//~^ ERROR cannot capture late-bound type parameter in a constant
|
||||
//~^ ERROR cannot capture late-bound type parameter in constant
|
||||
{}
|
||||
|
||||
fn main() {}
|
||||
|
@ -15,7 +15,7 @@ LL | #![feature(non_lifetime_binders, generic_const_exprs)]
|
||||
|
|
||||
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
|
||||
|
||||
error: cannot capture late-bound type parameter in a constant
|
||||
error: cannot capture late-bound type parameter in constant
|
||||
--> $DIR/late-bound-in-anon-ct.rs:7:27
|
||||
|
|
||||
LL | for<T> [i32; { let _: T = todo!(); 0 }]:,
|
||||
|
22
tests/ui/type-alias-impl-trait/escaping-bound-var.rs
Normal file
22
tests/ui/type-alias-impl-trait/escaping-bound-var.rs
Normal file
@ -0,0 +1,22 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
pub trait Trait<'a> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
trait Test<'a> {}
|
||||
|
||||
pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
||||
//~^ ERROR cannot capture late-bound lifetime in type alias impl trait
|
||||
|
||||
impl Trait<'_> for () {
|
||||
type Assoc = ();
|
||||
}
|
||||
|
||||
impl Test<'_> for () {}
|
||||
|
||||
fn constrain() -> Foo {
|
||||
()
|
||||
}
|
||||
|
||||
fn main() {}
|
8
tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
Normal file
8
tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: cannot capture late-bound lifetime in type alias impl trait
|
||||
--> $DIR/escaping-bound-var.rs:9:57
|
||||
|
|
||||
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
||||
| -- lifetime defined here ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -9,42 +9,36 @@ type NotCapturedEarly<'a> = impl Sized; //~ [o]
|
||||
|
||||
type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o]
|
||||
|
||||
// TAIT does *not* capture `'b`
|
||||
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [o]
|
||||
|
||||
type CapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'b>>; //~ [o]
|
||||
|
||||
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a> + Captures<'b>>; //~ [o]
|
||||
// TAIT does *not* capture `'b`
|
||||
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [o]
|
||||
|
||||
type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [o, o, o]
|
||||
|
||||
trait Foo<'i> {
|
||||
type ImplicitCapturedEarly<'a>;
|
||||
type ImplicitCapture<'a>;
|
||||
|
||||
type ExplicitCaptureEarly<'a>;
|
||||
type ExplicitCaptureFromHeader<'a>;
|
||||
|
||||
type ImplicitCaptureLate<'a>;
|
||||
|
||||
type ExplicitCaptureLate<'a>;
|
||||
type ExplicitCaptureFromGat<'a>;
|
||||
}
|
||||
|
||||
impl<'i> Foo<'i> for &'i () {
|
||||
type ImplicitCapturedEarly<'a> = impl Sized; //~ [o, o]
|
||||
type ImplicitCapture<'a> = impl Sized; //~ [o, o]
|
||||
|
||||
type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>; //~ [o, o]
|
||||
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o]
|
||||
|
||||
type ImplicitCaptureLate<'a> = impl Sized; //~ [o, o]
|
||||
|
||||
type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>; //~ [o, o]
|
||||
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o]
|
||||
}
|
||||
|
||||
impl<'i> Foo<'i> for () {
|
||||
type ImplicitCapturedEarly<'a> = impl Sized; //~ [o, o]
|
||||
type ImplicitCapture<'a> = impl Sized; //~ [o, o]
|
||||
|
||||
type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>; //~ [o, o]
|
||||
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o]
|
||||
|
||||
type ImplicitCaptureLate<'a> = impl Sized; //~ [o, o]
|
||||
|
||||
type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>; //~ [o, o]
|
||||
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -11,22 +11,16 @@ LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o]
|
||||
--> $DIR/variance.rs:12:56
|
||||
--> $DIR/variance.rs:13:56
|
||||
|
|
||||
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: [o]
|
||||
--> $DIR/variance.rs:14:53
|
||||
|
|
||||
LL | type CapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'b>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o]
|
||||
--> $DIR/variance.rs:16:49
|
||||
|
|
||||
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a> + Captures<'b>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o, o, o]
|
||||
--> $DIR/variance.rs:18:27
|
||||
@ -35,52 +29,40 @@ LL | type Bar<'a, 'b: 'b, T> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:31:38
|
||||
--> $DIR/variance.rs:29:32
|
||||
|
|
||||
LL | type ImplicitCapturedEarly<'a> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
LL | type ImplicitCapture<'a> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:33:37
|
||||
--> $DIR/variance.rs:31:42
|
||||
|
|
||||
LL | type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:35:36
|
||||
--> $DIR/variance.rs:33:39
|
||||
|
|
||||
LL | type ImplicitCaptureLate<'a> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:37:36
|
||||
--> $DIR/variance.rs:37:32
|
||||
|
|
||||
LL | type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | type ImplicitCapture<'a> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:41:38
|
||||
--> $DIR/variance.rs:39:42
|
||||
|
|
||||
LL | type ImplicitCapturedEarly<'a> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:43:37
|
||||
--> $DIR/variance.rs:41:39
|
||||
|
|
||||
LL | type ExplicitCaptureEarly<'a> = impl Sized + Captures<'i>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:45:36
|
||||
|
|
||||
LL | type ImplicitCaptureLate<'a> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: [o, o]
|
||||
--> $DIR/variance.rs:47:36
|
||||
|
|
||||
LL | type ExplicitCaptureLate<'a> = impl Sized + Captures<'a>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user