Actually capture all in-scope lifetimes.
This commit is contained in:
parent
8f6e0a6a4b
commit
2d74d8f333
@ -557,37 +557,29 @@ fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
|
|||||||
/// like async desugaring.
|
/// like async desugaring.
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
||||||
let mut captures = FxIndexMap::default();
|
let captures = RefCell::new(FxIndexMap::default());
|
||||||
|
|
||||||
let capture_all_in_scope_lifetimes =
|
let capture_all_in_scope_lifetimes =
|
||||||
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
|
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
|
||||||
if capture_all_in_scope_lifetimes {
|
if capture_all_in_scope_lifetimes {
|
||||||
let mut create_def_for_duplicated_param = |original_lifetime: LocalDefId, def| {
|
let lifetime_ident = |def_id: LocalDefId| {
|
||||||
captures.entry(def).or_insert_with(|| {
|
let name = self.tcx.item_name(def_id.to_def_id());
|
||||||
let name = self.tcx.item_name(original_lifetime.to_def_id());
|
let span = self.tcx.def_span(def_id);
|
||||||
let span = self.tcx.def_span(original_lifetime);
|
Ident::new(name, span)
|
||||||
let feed = self.tcx.create_def(opaque.def_id, name, DefKind::LifetimeParam);
|
|
||||||
feed.def_span(span);
|
|
||||||
feed.def_ident_span(Some(span));
|
|
||||||
feed.def_id()
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// We list scopes outwards, this causes us to see lifetime parameters in reverse
|
// We list scopes outwards, this causes us to see lifetime parameters in reverse
|
||||||
// declaration order. In order to make it consistent with what `generics_of` might
|
// declaration order. In order to make it consistent with what `generics_of` might
|
||||||
// give, we will reverse the IndexMap after early captures.
|
// give, we will reverse the IndexMap after early captures.
|
||||||
let mut scope = self.scope;
|
let mut scope = self.scope;
|
||||||
|
let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)];
|
||||||
loop {
|
loop {
|
||||||
match *scope {
|
match *scope {
|
||||||
Scope::Binder { ref bound_vars, s, .. } => {
|
Scope::Binder { ref bound_vars, s, .. } => {
|
||||||
for (&original_lifetime, &(mut def)) in bound_vars.iter().rev() {
|
for (&original_lifetime, &def) in bound_vars.iter().rev() {
|
||||||
if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
|
if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
|
||||||
if let Err(guar) =
|
let ident = lifetime_ident(original_lifetime);
|
||||||
self.check_lifetime_is_capturable(opaque.def_id, def, None)
|
self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
|
||||||
{
|
|
||||||
def = ResolvedArg::Error(guar);
|
|
||||||
}
|
|
||||||
create_def_for_duplicated_param(original_lifetime, def);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope = s;
|
scope = s;
|
||||||
@ -598,10 +590,9 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
|||||||
let parent_generics = self.tcx.generics_of(parent_item);
|
let parent_generics = self.tcx.generics_of(parent_item);
|
||||||
for param in parent_generics.own_params.iter().rev() {
|
for param in parent_generics.own_params.iter().rev() {
|
||||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||||
create_def_for_duplicated_param(
|
let def = ResolvedArg::EarlyBound(param.def_id.expect_local());
|
||||||
param.def_id.expect_local(),
|
let ident = lifetime_ident(param.def_id.expect_local());
|
||||||
ResolvedArg::EarlyBound(param.def_id.expect_local()),
|
self.remap_opaque_captures(&opaque_capture_scopes, def, ident);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
|
opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
|
||||||
@ -609,14 +600,9 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Opaque { captures: outer_captures, .. } => {
|
Scope::Opaque { captures, def_id, s } => {
|
||||||
for (_, &duplicated_param) in outer_captures.borrow().iter().rev() {
|
opaque_capture_scopes.push((def_id, captures));
|
||||||
create_def_for_duplicated_param(
|
scope = s;
|
||||||
duplicated_param,
|
|
||||||
ResolvedArg::EarlyBound(duplicated_param),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Body { .. } => {
|
Scope::Body { .. } => {
|
||||||
@ -631,11 +617,9 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
captures.reverse();
|
captures.borrow_mut().reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
let captures = RefCell::new(captures);
|
|
||||||
|
|
||||||
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 };
|
||||||
@ -643,6 +627,7 @@ fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let captures = captures.into_inner().into_iter().collect();
|
let captures = captures.into_inner().into_iter().collect();
|
||||||
|
debug!(?captures);
|
||||||
self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures);
|
self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1297,7 +1282,7 @@ fn resolve_lifetime_ref(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(mut def) = result {
|
if let Some(mut def) = result {
|
||||||
def = self.remap_opaque_captures(opaque_capture_scopes, def, lifetime_ref.ident);
|
def = self.remap_opaque_captures(&opaque_capture_scopes, def, lifetime_ref.ident);
|
||||||
|
|
||||||
if let ResolvedArg::EarlyBound(..) = def {
|
if let ResolvedArg::EarlyBound(..) = def {
|
||||||
// Do not free early-bound regions, only late-bound ones.
|
// Do not free early-bound regions, only late-bound ones.
|
||||||
@ -1396,7 +1381,7 @@ fn check_lifetime_is_capturable(
|
|||||||
&self,
|
&self,
|
||||||
opaque_def_id: LocalDefId,
|
opaque_def_id: LocalDefId,
|
||||||
lifetime: ResolvedArg,
|
lifetime: ResolvedArg,
|
||||||
span: Option<Span>,
|
capture_span: Span,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
|
let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
|
||||||
let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
|
let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
|
||||||
@ -1416,10 +1401,8 @@ fn check_lifetime_is_capturable(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let decl_span = self.tcx.def_span(lifetime_def_id);
|
let decl_span = self.tcx.def_span(lifetime_def_id);
|
||||||
let (span, label) = if let Some(span) = span
|
let (span, label) = if capture_span != decl_span {
|
||||||
&& span != decl_span
|
(capture_span, None)
|
||||||
{
|
|
||||||
(span, None)
|
|
||||||
} else {
|
} else {
|
||||||
let opaque_span = self.tcx.def_span(opaque_def_id);
|
let opaque_span = self.tcx.def_span(opaque_def_id);
|
||||||
(opaque_span, Some(opaque_span))
|
(opaque_span, Some(opaque_span))
|
||||||
@ -1435,19 +1418,22 @@ fn check_lifetime_is_capturable(
|
|||||||
Err(guar)
|
Err(guar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
|
||||||
fn remap_opaque_captures(
|
fn remap_opaque_captures(
|
||||||
&self,
|
&self,
|
||||||
opaque_capture_scopes: Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
|
opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
|
||||||
mut lifetime: ResolvedArg,
|
mut lifetime: ResolvedArg,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
) -> ResolvedArg {
|
) -> ResolvedArg {
|
||||||
for (opaque_def_id, captures) in opaque_capture_scopes.into_iter().rev() {
|
if let Some(&(opaque_def_id, _)) = opaque_capture_scopes.last() {
|
||||||
if let Err(guar) =
|
if let Err(guar) =
|
||||||
self.check_lifetime_is_capturable(opaque_def_id, lifetime, Some(ident.span))
|
self.check_lifetime_is_capturable(opaque_def_id, lifetime, ident.span)
|
||||||
{
|
{
|
||||||
return ResolvedArg::Error(guar);
|
lifetime = ResolvedArg::Error(guar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
|
||||||
let mut captures = captures.borrow_mut();
|
let mut captures = captures.borrow_mut();
|
||||||
let remapped = *captures.entry(lifetime).or_insert_with(|| {
|
let remapped = *captures.entry(lifetime).or_insert_with(|| {
|
||||||
let feed = self.tcx.create_def(opaque_def_id, ident.name, DefKind::LifetimeParam);
|
let feed = self.tcx.create_def(opaque_def_id, ident.name, DefKind::LifetimeParam);
|
||||||
@ -1976,7 +1962,7 @@ fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lifetime = self.remap_opaque_captures(opaque_capture_scopes, lifetime, lifetime_ref.ident);
|
lifetime = self.remap_opaque_captures(&opaque_capture_scopes, lifetime, lifetime_ref.ident);
|
||||||
|
|
||||||
self.insert_lifetime(lifetime_ref, lifetime);
|
self.insert_lifetime(lifetime_ref, lifetime);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
trait IntFactory {
|
trait IntFactory {
|
||||||
fn stream(self) -> impl IntFactory<stream(..): Send>;
|
fn stream(self) -> impl IntFactory<stream(..): Send>;
|
||||||
|
//~^ ERROR cycle detected when resolving lifetimes for `IntFactory::stream`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
error[E0391]: cycle detected when resolving lifetimes for `IntFactory::stream`
|
||||||
|
--> $DIR/impl-trait-in-trait.rs:4:5
|
||||||
|
|
|
||||||
|
LL | fn stream(self) -> impl IntFactory<stream(..): Send>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires computing function signature of `IntFactory::stream`...
|
||||||
|
--> $DIR/impl-trait-in-trait.rs:4:5
|
||||||
|
|
|
||||||
|
LL | fn stream(self) -> impl IntFactory<stream(..): Send>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires looking up late bound vars inside `IntFactory::stream`...
|
||||||
|
--> $DIR/impl-trait-in-trait.rs:4:5
|
||||||
|
|
|
||||||
|
LL | fn stream(self) -> impl IntFactory<stream(..): Send>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which again requires resolving lifetimes for `IntFactory::stream`, completing the cycle
|
||||||
|
note: cycle used when listing captured lifetimes for opaque `IntFactory::stream::{opaque#0}`
|
||||||
|
--> $DIR/impl-trait-in-trait.rs:4:24
|
||||||
|
|
|
||||||
|
LL | fn stream(self) -> impl IntFactory<stream(..): Send>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0391`.
|
@ -6,8 +6,9 @@
|
|||||||
#![rustc_variance_of_opaques]
|
#![rustc_variance_of_opaques]
|
||||||
|
|
||||||
fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
//~^ ERROR []
|
//~^ ERROR ['_: o]
|
||||||
//~| ERROR []
|
//~| ERROR ['_: o]
|
||||||
|
//~| ERROR `impl Trait` captures lifetime parameter
|
||||||
[*x]
|
[*x]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
error: []
|
error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
|
||||||
|
--> $DIR/capturing-implicit.rs:8:11
|
||||||
|
|
|
||||||
|
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
|
| ^ -------------------------------------------- lifetime captured due to being mentioned in the bounds of the `impl Trait`
|
||||||
|
| |
|
||||||
|
| this lifetime parameter is captured
|
||||||
|
|
||||||
|
error: ['_: o]
|
||||||
--> $DIR/capturing-implicit.rs:8:19
|
--> $DIR/capturing-implicit.rs:8:19
|
||||||
|
|
|
|
||||||
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: []
|
error: ['_: o]
|
||||||
--> $DIR/capturing-implicit.rs:8:44
|
--> $DIR/capturing-implicit.rs:8:44
|
||||||
|
|
|
|
||||||
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ impl<T> Captures<'_> for T {}
|
|||||||
|
|
||||||
fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
||||||
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
||||||
//~| ERROR return type cannot have an unboxed trait object
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,9 +12,7 @@ pub fn main() {
|
|||||||
//~^ ERROR item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
//~^ ERROR item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
||||||
type Opaque = impl Sized;
|
type Opaque = impl Sized;
|
||||||
fn define() -> Opaque {
|
fn define() -> Opaque {
|
||||||
//~^ ERROR the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
|
||||||
let x: Opaque = dyn_hoops::<()>();
|
let x: Opaque = dyn_hoops::<()>();
|
||||||
//~^ ERROR the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,57 +10,19 @@ note: lifetime declared here
|
|||||||
LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0746]: return type cannot have an unboxed trait object
|
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:6:29
|
|
||||||
|
|
|
||||||
LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
help: consider returning an `impl Trait` instead of a `dyn Trait`
|
|
||||||
|
|
|
||||||
LL | fn dyn_hoops<T: Sized>() -> impl for<'a> Iterator<Item = impl Captures<'a>> {
|
|
||||||
| ~~~~
|
|
||||||
help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
|
|
||||||
|
|
|
||||||
LL ~ fn dyn_hoops<T: Sized>() -> Box<dyn for<'a> Iterator<Item = impl Captures<'a>>> {
|
|
||||||
LL |
|
|
||||||
LL |
|
|
||||||
LL ~ Box::new(loop {})
|
|
||||||
|
|
|
||||||
|
|
||||||
error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:12:8
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:11:8
|
||||||
|
|
|
|
||||||
LL | pub fn main() {
|
LL | pub fn main() {
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: consider moving the opaque type's declaration and defining uses into a separate module
|
= note: consider moving the opaque type's declaration and defining uses into a separate module
|
||||||
note: this opaque type is in the signature
|
note: this opaque type is in the signature
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:14:19
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:13:19
|
||||||
|
|
|
|
||||||
LL | type Opaque = impl Sized;
|
LL | type Opaque = impl Sized;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)` cannot be known at compilation time
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:15:20
|
|
||||||
|
|
|
||||||
LL | fn define() -> Opaque {
|
|
||||||
| ^^^^^^ doesn't have a size known at compile-time
|
|
||||||
...
|
|
||||||
LL | x
|
|
||||||
| - return type was inferred to be `(dyn Iterator<Item = impl Captures<'_>> + 'static)` here
|
|
||||||
|
|
|
||||||
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
|
||||||
|
|
||||||
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)` cannot be known at compilation time
|
For more information about this error, try `rustc --explain E0657`.
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:17:25
|
|
||||||
|
|
|
||||||
LL | let x: Opaque = dyn_hoops::<()>();
|
|
||||||
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
|
||||||
|
|
|
||||||
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0657, E0746.
|
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user