Skip to content

Commit 30bedc7

Browse files
committed
in opaque type handling lift region vars to static if they outlive placeholders
1 parent 9725c4b commit 30bedc7

File tree

8 files changed

+90
-32
lines changed

8 files changed

+90
-32
lines changed

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
344344
}
345345
}
346346

347-
fn rewrite_placeholder_outlives<'tcx>(
347+
pub(crate) fn rewrite_placeholder_outlives<'tcx>(
348348
sccs: &Sccs<RegionVid, ConstraintSccIndex>,
349349
annotations: &SccAnnotations<'_, '_, RegionTracker>,
350350
fr_static: RegionVid,

compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(super) fn apply_member_constraints<'tcx>(
3939
debug!(?member_constraints);
4040
for scc_a in rcx.constraint_sccs.all_sccs() {
4141
debug!(?scc_a);
42-
// Start by adding the region values required by outlives constraints. This
42+
// Start by adding the region values required by outlives constraints. This
4343
// matches how we compute the final region values in `fn compute_regions`.
4444
//
4545
// We need to do this here to get a lower bound when applying member constraints.
@@ -64,6 +64,7 @@ fn apply_member_constraint<'tcx>(
6464
// If the member region lives in a higher universe, we currently choose
6565
// the most conservative option by leaving it unchanged.
6666
if !rcx.max_placeholder_universe_reached(member).is_root() {
67+
debug!("member region reached non root universe, bailing");
6768
return;
6869
}
6970

compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ fn collect_defining_uses<'tcx>(
253253
}
254254
} else {
255255
errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
256+
debug!(
257+
"collect_defining_uses: InvalidOpaqueTypeArgs for {:?} := {:?}",
258+
non_nll_opaque_type_key, hidden_type
259+
);
256260
}
257261
continue;
258262
}
@@ -276,6 +280,7 @@ fn collect_defining_uses<'tcx>(
276280
defining_uses
277281
}
278282

283+
#[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))]
279284
fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
280285
rcx: &RegionCtxt<'_, 'tcx>,
281286
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
@@ -287,13 +292,15 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
287292
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
288293
FxIndexMap::default();
289294
for &DefiningUse { opaque_type_key, ref arg_regions, hidden_type } in defining_uses {
295+
debug!(?opaque_type_key, ?arg_regions, ?hidden_type);
290296
// After applying member constraints, we now map all regions in the hidden type
291297
// to the `arg_regions` of this defining use. In case a region in the hidden type
292298
// ended up not being equal to any such region, we error.
293299
let hidden_type =
294300
match hidden_type.try_fold_with(&mut ToArgRegionsFolder::new(rcx, arg_regions)) {
295301
Ok(hidden_type) => hidden_type,
296302
Err(r) => {
303+
debug!("UnexpectedHiddenRegion: {:?}", r);
297304
errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
298305
hidden_type,
299306
opaque_type_key,

compiler/rustc_borrowck/src/region_infer/opaque_types/region_ctxt.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use crate::constraints::ConstraintSccIndex;
1111
use crate::handle_placeholders::{SccAnnotations, region_definitions};
1212
use crate::region_infer::reverse_sccs::ReverseSccGraph;
1313
use crate::region_infer::values::RegionValues;
14-
use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker, Representative};
14+
use crate::region_infer::{
15+
ConstraintSccs, OutlivesConstraintSet, RegionDefinition, RegionTracker, Representative,
16+
};
1517
use crate::type_check::MirTypeckRegionConstraints;
1618
use crate::type_check::free_region_relations::UniversalRegionRelations;
1719
use crate::universal_regions::UniversalRegions;
@@ -39,16 +41,36 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
3941
location_map: Rc<DenseLocationMap>,
4042
constraints: &MirTypeckRegionConstraints<'tcx>,
4143
) -> RegionCtxt<'a, 'tcx> {
44+
let mut outlives_constraints = constraints.outlives_constraints.clone();
4245
let universal_regions = &universal_region_relations.universal_regions;
4346
let (definitions, _has_placeholders) = region_definitions(infcx, universal_regions);
47+
48+
let compute_sccs =
49+
|outlives_constraints: &OutlivesConstraintSet<'tcx>,
50+
annotations: &mut SccAnnotations<'_, 'tcx, RegionTracker>| {
51+
ConstraintSccs::new_with_annotation(
52+
&outlives_constraints
53+
.graph(definitions.len())
54+
.region_graph(outlives_constraints, universal_regions.fr_static),
55+
annotations,
56+
)
57+
};
58+
4459
let mut scc_annotations = SccAnnotations::init(&definitions);
45-
let constraint_sccs = ConstraintSccs::new_with_annotation(
46-
&constraints
47-
.outlives_constraints
48-
.graph(definitions.len())
49-
.region_graph(&constraints.outlives_constraints, universal_regions.fr_static),
50-
&mut scc_annotations,
60+
let mut constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
61+
62+
let added_constraints = crate::handle_placeholders::rewrite_placeholder_outlives(
63+
&constraint_sccs,
64+
&scc_annotations,
65+
universal_regions.fr_static,
66+
&mut outlives_constraints,
5167
);
68+
69+
if added_constraints {
70+
scc_annotations = SccAnnotations::init(&definitions);
71+
constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
72+
}
73+
5274
let scc_annotations = scc_annotations.scc_to_annotation;
5375

5476
// Unlike the `RegionInferenceContext`, we only care about free regions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ check-pass
2+
3+
// We have some `RPIT` with an item bound of `for<'a> Outlives<'a>`. We
4+
// infer a hidden type of `&'?x i32` where `'?x` is required to outlive
5+
// some placeholder `'!a` due to the `for<'a> Outlives<'a>` item bound.
6+
//
7+
// We previously did not write constraints of the form `'?x: '!a` into
8+
// `'?x: 'static`. This caused member constraints to bail and not consider
9+
// `'?x` to be constrained to an arg region.
10+
11+
pub trait Outlives<'a> {}
12+
impl<'a, T: 'a> Outlives<'a> for T {}
13+
14+
pub fn foo() -> impl for<'a> Outlives<'a> {
15+
let x: &'static i32 = &1;
16+
x
17+
}
18+
19+
// This *didn't* regress but feels like it's "the same thing" so
20+
// test it anyway
21+
pub fn bar() -> impl Sized {
22+
let x: &'static i32 = &1;
23+
hr_outlives(x)
24+
}
25+
26+
fn hr_outlives<T>(v: T) -> T
27+
where
28+
for<'a> T: 'a
29+
{
30+
v
31+
}
32+
33+
fn main() {}

tests/ui/impl-trait/nested-rpit-hrtb.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = im
4848
// This should resolve.
4949
fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
5050
//~^ ERROR implementation of `Bar` is not general enough
51-
//~| ERROR lifetime may not live long enough
5251

5352
// This should resolve.
5453
fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {}

tests/ui/impl-trait/nested-rpit-hrtb.stderr

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0261]: use of undeclared lifetime name `'b`
2-
--> $DIR/nested-rpit-hrtb.rs:57:77
2+
--> $DIR/nested-rpit-hrtb.rs:56:77
33
|
44
LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
55
| ^^ undeclared lifetime
@@ -15,7 +15,7 @@ LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Siz
1515
| ++++
1616

1717
error[E0261]: use of undeclared lifetime name `'b`
18-
--> $DIR/nested-rpit-hrtb.rs:65:82
18+
--> $DIR/nested-rpit-hrtb.rs:64:82
1919
|
2020
LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
2121
| ^^ undeclared lifetime
@@ -87,12 +87,6 @@ LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc
8787
but trait `Qux<'_>` is implemented for `()`
8888
= help: for that trait implementation, expected `()`, found `&'a ()`
8989

90-
error: lifetime may not live long enough
91-
--> $DIR/nested-rpit-hrtb.rs:49:93
92-
|
93-
LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
94-
| -- lifetime `'b` defined here ^^ opaque type requires that `'b` must outlive `'static`
95-
9690
error: implementation of `Bar` is not general enough
9791
--> $DIR/nested-rpit-hrtb.rs:49:93
9892
|
@@ -103,7 +97,7 @@ LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc =
10397
= note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
10498

10599
error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied
106-
--> $DIR/nested-rpit-hrtb.rs:61:64
100+
--> $DIR/nested-rpit-hrtb.rs:60:64
107101
|
108102
LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
109103
| ^^^^^^^^^^^^^^^^^^^^ 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>
112106
but trait `Qux<'_>` is implemented for `()`
113107
= help: for that trait implementation, expected `()`, found `&'a ()`
114108

115-
error: aborting due to 10 previous errors
109+
error: aborting due to 9 previous errors
116110

117111
Some errors have detailed explanations: E0261, E0277, E0657.
118112
For more information about an error, try `rustc --explain E0261`.

tests/ui/nll/ice-106874.stderr

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,20 @@ LL | A(B(C::new(D::new(move |st| f(st)))))
1717
= note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
1818
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1919

20+
error: higher-ranked subtype error
21+
--> $DIR/ice-106874.rs:8:5
22+
|
23+
LL | A(B(C::new(D::new(move |st| f(st)))))
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
26+
error: higher-ranked subtype error
27+
--> $DIR/ice-106874.rs:8:5
28+
|
29+
LL | A(B(C::new(D::new(move |st| f(st)))))
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
33+
2034
error: implementation of `FnOnce` is not general enough
2135
--> $DIR/ice-106874.rs:8:7
2236
|
@@ -75,17 +89,5 @@ LL | A(B(C::new(D::new(move |st| f(st)))))
7589
= note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
7690
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
7791

78-
error: higher-ranked subtype error
79-
--> $DIR/ice-106874.rs:8:7
80-
|
81-
LL | A(B(C::new(D::new(move |st| f(st)))))
82-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
83-
84-
error: higher-ranked subtype error
85-
--> $DIR/ice-106874.rs:8:41
86-
|
87-
LL | A(B(C::new(D::new(move |st| f(st)))))
88-
| ^
89-
9092
error: aborting due to 10 previous errors
9193

0 commit comments

Comments
 (0)