in opaque type handling lift region vars to static if they outlive placeholders

This commit is contained in:
Boxy Uwu
2025-10-10 19:56:57 +01:00
parent 9725c4baac
commit 30bedc74d4
8 changed files with 137 additions and 79 deletions
@@ -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() {}
-1
View File
@@ -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>> {}
+4 -10
View File
@@ -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`.
+61 -59
View File
@@ -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