mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
in opaque type handling lift region vars to static if they outlive placeholders
This commit is contained in:
@@ -344,7 +344,7 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn rewrite_placeholder_outlives<'tcx>(
|
||||
pub(crate) fn rewrite_placeholder_outlives<'tcx>(
|
||||
sccs: &Sccs<RegionVid, ConstraintSccIndex>,
|
||||
annotations: &SccAnnotations<'_, '_, RegionTracker>,
|
||||
fr_static: RegionVid,
|
||||
|
||||
@@ -39,7 +39,7 @@ pub(super) fn apply_member_constraints<'tcx>(
|
||||
debug!(?member_constraints);
|
||||
for scc_a in rcx.constraint_sccs.all_sccs() {
|
||||
debug!(?scc_a);
|
||||
// Start by adding the region values required by outlives constraints. This
|
||||
// Start by adding the region values required by outlives constraints. This
|
||||
// matches how we compute the final region values in `fn compute_regions`.
|
||||
//
|
||||
// We need to do this here to get a lower bound when applying member constraints.
|
||||
@@ -64,6 +64,7 @@ fn apply_member_constraint<'tcx>(
|
||||
// If the member region lives in a higher universe, we currently choose
|
||||
// the most conservative option by leaving it unchanged.
|
||||
if !rcx.max_placeholder_universe_reached(member).is_root() {
|
||||
debug!("member region reached non root universe, bailing");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -253,6 +253,10 @@ fn collect_defining_uses<'tcx>(
|
||||
}
|
||||
} else {
|
||||
errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
|
||||
debug!(
|
||||
"collect_defining_uses: InvalidOpaqueTypeArgs for {:?} := {:?}",
|
||||
non_nll_opaque_type_key, hidden_type
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -276,6 +280,7 @@ fn collect_defining_uses<'tcx>(
|
||||
defining_uses
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))]
|
||||
fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
||||
rcx: &RegionCtxt<'_, 'tcx>,
|
||||
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
|
||||
@@ -287,6 +292,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
||||
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
|
||||
FxIndexMap::default();
|
||||
for &DefiningUse { opaque_type_key, ref arg_regions, hidden_type } in defining_uses {
|
||||
debug!(?opaque_type_key, ?arg_regions, ?hidden_type);
|
||||
// After applying member constraints, we now map all regions in the hidden type
|
||||
// to the `arg_regions` of this defining use. In case a region in the hidden type
|
||||
// ended up not being equal to any such region, we error.
|
||||
@@ -294,6 +300,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
||||
match hidden_type.try_fold_with(&mut ToArgRegionsFolder::new(rcx, arg_regions)) {
|
||||
Ok(hidden_type) => hidden_type,
|
||||
Err(r) => {
|
||||
debug!("UnexpectedHiddenRegion: {:?}", r);
|
||||
errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
|
||||
hidden_type,
|
||||
opaque_type_key,
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
use crate::handle_placeholders::{SccAnnotations, region_definitions};
|
||||
use crate::region_infer::reverse_sccs::ReverseSccGraph;
|
||||
use crate::region_infer::values::RegionValues;
|
||||
use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker, Representative};
|
||||
use crate::region_infer::{
|
||||
ConstraintSccs, OutlivesConstraintSet, RegionDefinition, RegionTracker, Representative,
|
||||
};
|
||||
use crate::type_check::MirTypeckRegionConstraints;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
@@ -39,16 +41,36 @@ pub(super) fn new(
|
||||
location_map: Rc<DenseLocationMap>,
|
||||
constraints: &MirTypeckRegionConstraints<'tcx>,
|
||||
) -> RegionCtxt<'a, 'tcx> {
|
||||
let mut outlives_constraints = constraints.outlives_constraints.clone();
|
||||
let universal_regions = &universal_region_relations.universal_regions;
|
||||
let (definitions, _has_placeholders) = region_definitions(infcx, universal_regions);
|
||||
|
||||
let compute_sccs =
|
||||
|outlives_constraints: &OutlivesConstraintSet<'tcx>,
|
||||
annotations: &mut SccAnnotations<'_, 'tcx, RegionTracker>| {
|
||||
ConstraintSccs::new_with_annotation(
|
||||
&outlives_constraints
|
||||
.graph(definitions.len())
|
||||
.region_graph(outlives_constraints, universal_regions.fr_static),
|
||||
annotations,
|
||||
)
|
||||
};
|
||||
|
||||
let mut scc_annotations = SccAnnotations::init(&definitions);
|
||||
let constraint_sccs = ConstraintSccs::new_with_annotation(
|
||||
&constraints
|
||||
.outlives_constraints
|
||||
.graph(definitions.len())
|
||||
.region_graph(&constraints.outlives_constraints, universal_regions.fr_static),
|
||||
&mut scc_annotations,
|
||||
let mut constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
|
||||
|
||||
let added_constraints = crate::handle_placeholders::rewrite_placeholder_outlives(
|
||||
&constraint_sccs,
|
||||
&scc_annotations,
|
||||
universal_regions.fr_static,
|
||||
&mut outlives_constraints,
|
||||
);
|
||||
|
||||
if added_constraints {
|
||||
scc_annotations = SccAnnotations::init(&definitions);
|
||||
constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
|
||||
}
|
||||
|
||||
let scc_annotations = scc_annotations.scc_to_annotation;
|
||||
|
||||
// Unlike the `RegionInferenceContext`, we only care about free regions
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//@ check-pass
|
||||
|
||||
// We have some `RPIT` with an item bound of `for<'a> Outlives<'a>`. We
|
||||
// infer a hidden type of `&'?x i32` where `'?x` is required to outlive
|
||||
// some placeholder `'!a` due to the `for<'a> Outlives<'a>` item bound.
|
||||
//
|
||||
// We previously did not write constraints of the form `'?x: '!a` into
|
||||
// `'?x: 'static`. This caused member constraints to bail and not consider
|
||||
// `'?x` to be constrained to an arg region.
|
||||
|
||||
pub trait Outlives<'a> {}
|
||||
impl<'a, T: 'a> Outlives<'a> for T {}
|
||||
|
||||
pub fn foo() -> impl for<'a> Outlives<'a> {
|
||||
let x: &'static i32 = &1;
|
||||
x
|
||||
}
|
||||
|
||||
// This *didn't* regress but feels like it's "the same thing" so
|
||||
// test it anyway
|
||||
pub fn bar() -> impl Sized {
|
||||
let x: &'static i32 = &1;
|
||||
hr_outlives(x)
|
||||
}
|
||||
|
||||
fn hr_outlives<T>(v: T) -> T
|
||||
where
|
||||
for<'a> T: 'a
|
||||
{
|
||||
v
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -48,7 +48,6 @@ fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = im
|
||||
// This should resolve.
|
||||
fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
|
||||
//~^ ERROR implementation of `Bar` is not general enough
|
||||
//~| ERROR lifetime may not live long enough
|
||||
|
||||
// This should resolve.
|
||||
fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/nested-rpit-hrtb.rs:57:77
|
||||
--> $DIR/nested-rpit-hrtb.rs:56:77
|
||||
|
|
||||
LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
|
||||
| ^^ undeclared lifetime
|
||||
@@ -15,7 +15,7 @@ LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Siz
|
||||
| ++++
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/nested-rpit-hrtb.rs:65:82
|
||||
--> $DIR/nested-rpit-hrtb.rs:64:82
|
||||
|
|
||||
LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
|
||||
| ^^ undeclared lifetime
|
||||
@@ -87,12 +87,6 @@ LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc
|
||||
but trait `Qux<'_>` is implemented for `()`
|
||||
= help: for that trait implementation, expected `()`, found `&'a ()`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/nested-rpit-hrtb.rs:49:93
|
||||
|
|
||||
LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
|
||||
| -- lifetime `'b` defined here ^^ opaque type requires that `'b` must outlive `'static`
|
||||
|
||||
error: implementation of `Bar` is not general enough
|
||||
--> $DIR/nested-rpit-hrtb.rs:49:93
|
||||
|
|
||||
@@ -103,7 +97,7 @@ LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc =
|
||||
= note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
|
||||
|
||||
error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied
|
||||
--> $DIR/nested-rpit-hrtb.rs:61:64
|
||||
--> $DIR/nested-rpit-hrtb.rs:60:64
|
||||
|
|
||||
LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Qux<'b>` is not implemented for `&'a ()`
|
||||
@@ -112,7 +106,7 @@ LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b>
|
||||
but trait `Qux<'_>` is implemented for `()`
|
||||
= help: for that trait implementation, expected `()`, found `&'a ()`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0261, E0277, E0657.
|
||||
For more information about an error, try `rustc --explain E0261`.
|
||||
|
||||
@@ -17,75 +17,77 @@ LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
= note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/ice-106874.rs:8:5
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/ice-106874.rs:8:5
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/ice-106874.rs:8:41
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `FnOnce` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Fn` is not general enough
|
||||
--> $DIR/ice-106874.rs:8:7
|
||||
|
|
||||
LL | A(B(C::new(D::new(move |st| f(st)))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
|
||||
|
|
||||
= note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
|
||||
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
||||
Reference in New Issue
Block a user