mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Rollup merge of #132832 - compiler-errors:late-ty, r=cjgillot
Deny capturing late-bound ty/const params in nested opaques
First, this reverts a7f609504c
. I can't exactly remember why I approved this specific bit of https://github.com/rust-lang/rust/pull/132466; specifically, I don't know that the purpose of that commit is, and afaict we will never have an opaque that captures late-bound params through a const because opaques can't be used inside of anon consts. Am I missing something `@cjgillot?` Since I can't see a case where this matters, and no tests seem to fail.
The second commit adds a `deny_late_regions: bool` to distinguish `Scope::LateBoundary` which should deny *any* late-bound params or just ty/consts. Then, when resolving opaques we wrap ourselves in a `Scope::LateBoundary { deny_late_regions: false }` so that we deny late-bound ty/const, which fixes a bunch of ICEs that all vaguely look like `impl for<T> Trait<Assoc = impl OtherTrait<T>>`.
I guess this could be achieved other ways; for example, with a different scope kind, or maybe we could just reuse `Scope::Opaque`. But this seems a bit more verbose. I'm open to feedback anyways.
Fixes #131535
Fixes #131637
Fixes #132530
I opted to remove those crashes tests ^ without adding them as regular tests, since they're basically triggering uninteresting late-bound ICEs far off in the trait solver, and the reason that existing tests such as `tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs` don't ICE are kinda just coincidental (i.e. due to a missing impl block). I don't really feel motivated to add random permutations to tests just to exercise non-lifetime binders.
r? cjgillot
This commit is contained in:
commit
a1c98ca160
@ -177,6 +177,7 @@ enum Scope<'a> {
|
|||||||
LateBoundary {
|
LateBoundary {
|
||||||
s: ScopeRef<'a>,
|
s: ScopeRef<'a>,
|
||||||
what: &'static str,
|
what: &'static str,
|
||||||
|
deny_late_regions: bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
Root {
|
Root {
|
||||||
@ -234,9 +235,11 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
|||||||
.field("s", &"..")
|
.field("s", &"..")
|
||||||
.finish(),
|
.finish(),
|
||||||
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
||||||
Scope::LateBoundary { s: _, what } => {
|
Scope::LateBoundary { s: _, what, deny_late_regions } => f
|
||||||
f.debug_struct("LateBoundary").field("what", what).finish()
|
.debug_struct("LateBoundary")
|
||||||
}
|
.field("what", what)
|
||||||
|
.field("deny_late_regions", deny_late_regions)
|
||||||
|
.finish(),
|
||||||
Scope::Root { opt_parent_item } => {
|
Scope::Root { opt_parent_item } => {
|
||||||
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
|
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
|
||||||
}
|
}
|
||||||
@ -573,17 +576,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||||||
// give, we will reverse the IndexMap after early captures.
|
// give, we will reverse the IndexMap after early captures.
|
||||||
let mut late_depth = 0;
|
let mut late_depth = 0;
|
||||||
let mut scope = self.scope;
|
let mut scope = self.scope;
|
||||||
let mut crossed_late_boundary = None;
|
|
||||||
let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
|
let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
|
||||||
loop {
|
loop {
|
||||||
match *scope {
|
match *scope {
|
||||||
Scope::Binder { ref bound_vars, scope_type, s, .. } => {
|
Scope::Binder { ref bound_vars, scope_type, s, .. } => {
|
||||||
for (&original_lifetime, &def) in bound_vars.iter().rev() {
|
for (&original_lifetime, &def) in bound_vars.iter().rev() {
|
||||||
if let ResolvedArg::LateBound(..) = def
|
|
||||||
&& crossed_late_boundary.is_some()
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
|
if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
|
||||||
let def = def.shifted(late_depth);
|
let def = def.shifted(late_depth);
|
||||||
let ident = lifetime_ident(original_lifetime);
|
let ident = lifetime_ident(original_lifetime);
|
||||||
@ -624,12 +621,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||||||
|
|
||||||
Scope::ObjectLifetimeDefault { s, .. }
|
Scope::ObjectLifetimeDefault { s, .. }
|
||||||
| Scope::Supertrait { s, .. }
|
| Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. } => {
|
| Scope::TraitRefBoundary { s, .. }
|
||||||
scope = s;
|
| Scope::LateBoundary { s, .. } => {
|
||||||
}
|
|
||||||
|
|
||||||
Scope::LateBoundary { s, what, .. } => {
|
|
||||||
crossed_late_boundary = Some(what);
|
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -640,7 +633,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||||||
let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
|
let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
|
||||||
self.with(scope, |this| {
|
self.with(scope, |this| {
|
||||||
let scope = Scope::TraitRefBoundary { s: this.scope };
|
let scope = Scope::TraitRefBoundary { s: this.scope };
|
||||||
this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
|
this.with(scope, |this| {
|
||||||
|
let scope = Scope::LateBoundary {
|
||||||
|
s: this.scope,
|
||||||
|
what: "nested `impl Trait`",
|
||||||
|
// We can capture late-bound regions; we just don't duplicate
|
||||||
|
// lifetime or const params, so we can't allow those.
|
||||||
|
deny_late_regions: false,
|
||||||
|
};
|
||||||
|
this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let captures = captures.into_inner().into_iter().collect();
|
let captures = captures.into_inner().into_iter().collect();
|
||||||
@ -997,9 +999,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
||||||
self.with(Scope::LateBoundary { s: self.scope, what: "constant" }, |this| {
|
self.with(
|
||||||
intravisit::walk_anon_const(this, c);
|
Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true },
|
||||||
});
|
|this| {
|
||||||
|
intravisit::walk_anon_const(this, c);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
|
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
|
||||||
@ -1291,8 +1296,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::LateBoundary { s, what } => {
|
Scope::LateBoundary { s, what, deny_late_regions } => {
|
||||||
crossed_late_boundary = Some(what);
|
if deny_late_regions {
|
||||||
|
crossed_late_boundary = Some(what);
|
||||||
|
}
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1508,7 +1515,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::LateBoundary { s, what } => {
|
Scope::LateBoundary { s, what, deny_late_regions: _ } => {
|
||||||
crossed_late_boundary = Some(what);
|
crossed_late_boundary = Some(what);
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
//@ known-bug: #131535
|
|
||||||
#![feature(non_lifetime_binders)]
|
|
||||||
trait v0<> {}
|
|
||||||
fn kind :(v0<'_, > impl for<v4> v0<'_, v2 = impl v0<v4> + '_>) {}
|
|
@ -1,7 +0,0 @@
|
|||||||
//@ known-bug: #121637
|
|
||||||
#![feature(non_lifetime_binders)]
|
|
||||||
trait Trait<Type> {
|
|
||||||
type Type;
|
|
||||||
|
|
||||||
fn method(&self) -> impl for<T> Trait<impl Trait<T>>;
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
//@ known-bug: #132530
|
|
||||||
|
|
||||||
#![feature(non_lifetime_binders)]
|
|
||||||
|
|
||||||
trait Trait<'a, A> {
|
|
||||||
type Assoc<'a> = i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn a() -> impl for<T> Trait<Assoc = impl Trait<T>> {}
|
|
@ -7,6 +7,7 @@ fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
|
|||||||
//~^ ERROR associated type `Assoc` not found for `Trait`
|
//~^ ERROR associated type `Assoc` not found for `Trait`
|
||||||
//~| ERROR associated type `Assoc` not found for `Trait`
|
//~| ERROR associated type `Assoc` not found for `Trait`
|
||||||
//~| the trait bound `{integer}: Trait<()>` is not satisfied
|
//~| the trait bound `{integer}: Trait<()>` is not satisfied
|
||||||
|
//~| ERROR cannot capture late-bound type parameter in nested `impl Trait`
|
||||||
16
|
16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
error: cannot capture late-bound type parameter in nested `impl Trait`
|
||||||
|
--> $DIR/non-lifetime-binder-in-constraint.rs:6:58
|
||||||
|
|
|
||||||
|
LL | fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
|
||||||
|
| - parameter defined here ^
|
||||||
|
|
||||||
error[E0220]: associated type `Assoc` not found for `Trait`
|
error[E0220]: associated type `Assoc` not found for `Trait`
|
||||||
--> $DIR/non-lifetime-binder-in-constraint.rs:6:39
|
--> $DIR/non-lifetime-binder-in-constraint.rs:6:39
|
||||||
|
|
|
|
||||||
@ -27,7 +33,7 @@ help: this trait has no implementations, consider adding one
|
|||||||
LL | trait Trait<T: ?Sized> {}
|
LL | trait Trait<T: ?Sized> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0220, E0277.
|
Some errors have detailed explanations: E0220, E0277.
|
||||||
For more information about an error, try `rustc --explain E0220`.
|
For more information about an error, try `rustc --explain E0220`.
|
||||||
|
@ -5,6 +5,7 @@ trait Trait<T> {}
|
|||||||
|
|
||||||
fn f() -> impl for<T> Trait<impl Trait<T>> {}
|
fn f() -> impl for<T> Trait<impl Trait<T>> {}
|
||||||
//~^ ERROR nested `impl Trait` is not allowed
|
//~^ ERROR nested `impl Trait` is not allowed
|
||||||
//~| ERROR the trait bound `(): Trait<impl Trait<T>>` is not satisfied
|
//~| ERROR the trait bound `(): Trait<impl Trait<{type error}>>` is not satisfied
|
||||||
|
//~| ERROR cannot capture late-bound type parameter in nested `impl Trait`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -7,11 +7,19 @@ LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
|
|||||||
| | nested `impl Trait` here
|
| | nested `impl Trait` here
|
||||||
| outer `impl Trait`
|
| outer `impl Trait`
|
||||||
|
|
||||||
error[E0277]: the trait bound `(): Trait<impl Trait<T>>` is not satisfied
|
error: cannot capture late-bound type parameter in nested `impl Trait`
|
||||||
|
--> $DIR/non-lifetime-binder.rs:6:40
|
||||||
|
|
|
||||||
|
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
|
||||||
|
| - ^
|
||||||
|
| |
|
||||||
|
| parameter defined here
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `(): Trait<impl Trait<{type error}>>` is not satisfied
|
||||||
--> $DIR/non-lifetime-binder.rs:6:11
|
--> $DIR/non-lifetime-binder.rs:6:11
|
||||||
|
|
|
|
||||||
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
|
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<impl Trait<T>>` is not implemented for `()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<impl Trait<{type error}>>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
help: this trait has no implementations, consider adding one
|
help: this trait has no implementations, consider adding one
|
||||||
--> $DIR/non-lifetime-binder.rs:4:1
|
--> $DIR/non-lifetime-binder.rs:4:1
|
||||||
@ -19,7 +27,7 @@ help: this trait has no implementations, consider adding one
|
|||||||
LL | trait Trait<T> {}
|
LL | trait Trait<T> {}
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0666.
|
Some errors have detailed explanations: E0277, E0666.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
Loading…
Reference in New Issue
Block a user