Skip to content

Commit d78cef7

Browse files
committed
Capture binder region constraints while relating
1 parent 1a30ed9 commit d78cef7

7 files changed

Lines changed: 303 additions & 26 deletions

File tree

compiler/rustc_next_trait_solver/src/canonical/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,17 @@ fn unify_query_var_values<D, I>(
265265
assert_eq!(original_values.len(), var_values.len());
266266

267267
for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) {
268-
let goals =
269-
delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap();
268+
let goals = if delegate.cx().assumptions_on_binders() {
269+
let (goals, region_constraints) = delegate
270+
.eq_structurally_relating_aliases_with_region_constraints(
271+
param_env, orig, response, span,
272+
)
273+
.unwrap();
274+
delegate.register_solver_region_constraint(region_constraints);
275+
goals
276+
} else {
277+
delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap()
278+
};
270279
assert!(goals.is_empty());
271280
}
272281
}

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,13 +1253,7 @@ where
12531253
let identity_args = self.fresh_args_for_item(def_id);
12541254
let rigid_ctor = alias.with_args(cx, identity_args);
12551255
let ctor_term = rigid_ctor.to_term(cx);
1256-
let obligations = self.delegate.eq_structurally_relating_aliases(
1257-
param_env,
1258-
term,
1259-
ctor_term,
1260-
self.origin_span,
1261-
)?;
1262-
debug_assert!(obligations.is_empty());
1256+
self.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
12631257
self.relate(param_env, alias, variance, rigid_ctor)
12641258
} else {
12651259
Err(NoSolution)
@@ -1276,12 +1270,19 @@ where
12761270
lhs: T,
12771271
rhs: T,
12781272
) -> Result<(), NoSolution> {
1279-
let result = self.delegate.eq_structurally_relating_aliases(
1280-
param_env,
1281-
lhs,
1282-
rhs,
1283-
self.origin_span,
1284-
)?;
1273+
let result = if self.cx().assumptions_on_binders() {
1274+
let (goals, region_constraints) =
1275+
self.delegate.eq_structurally_relating_aliases_with_region_constraints(
1276+
param_env,
1277+
lhs,
1278+
rhs,
1279+
self.origin_span,
1280+
)?;
1281+
self.register_solver_region_constraint(region_constraints);
1282+
goals
1283+
} else {
1284+
self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs, self.origin_span)?
1285+
};
12851286
assert_eq!(result, vec![]);
12861287
Ok(())
12871288
}
@@ -1304,7 +1305,19 @@ where
13041305
variance: ty::Variance,
13051306
rhs: T,
13061307
) -> Result<(), NoSolution> {
1307-
let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
1308+
let goals = if self.cx().assumptions_on_binders() {
1309+
let (goals, region_constraints) = self.delegate.relate_with_region_constraints(
1310+
param_env,
1311+
lhs,
1312+
variance,
1313+
rhs,
1314+
self.origin_span,
1315+
)?;
1316+
self.register_solver_region_constraint(region_constraints);
1317+
goals
1318+
} else {
1319+
self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?
1320+
};
13081321
for &goal in goals.iter() {
13091322
let source = match goal.predicate.kind().skip_binder() {
13101323
ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {
@@ -1326,12 +1339,30 @@ where
13261339
/// goals correctly.
13271340
#[instrument(level = "trace", skip(self, param_env), ret)]
13281341
pub(super) fn eq_and_get_goals<T: Relate<I>>(
1329-
&self,
1342+
&mut self,
13301343
param_env: I::ParamEnv,
13311344
lhs: T,
13321345
rhs: T,
13331346
) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
1334-
Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
1347+
if self.cx().assumptions_on_binders() {
1348+
let (goals, region_constraints) = self.delegate.relate_with_region_constraints(
1349+
param_env,
1350+
lhs,
1351+
ty::Variance::Invariant,
1352+
rhs,
1353+
self.origin_span,
1354+
)?;
1355+
self.register_solver_region_constraint(region_constraints);
1356+
Ok(goals)
1357+
} else {
1358+
Ok(self.delegate.relate(
1359+
param_env,
1360+
lhs,
1361+
ty::Variance::Invariant,
1362+
rhs,
1363+
self.origin_span,
1364+
)?)
1365+
}
13351366
}
13361367

13371368
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(

compiler/rustc_type_ir/src/relate/solver_relating.rs

Lines changed: 177 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use tracing::{debug, instrument};
22

33
use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys};
44
use crate::data_structures::DelayedSet;
5+
use crate::region_constraint::RegionConstraint;
56
use crate::relate::combine::combine_ty_args;
67
pub use crate::relate::*;
78
use crate::solve::{Goal, VisibleForLeakCheck};
@@ -30,6 +31,70 @@ pub trait RelateExt: InferCtxtLike {
3031
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
3132
TypeError<Self::Interner>,
3233
>;
34+
35+
fn eq_structurally_relating_aliases_with_region_constraints<T: Relate<Self::Interner>>(
36+
&self,
37+
param_env: <Self::Interner as Interner>::ParamEnv,
38+
lhs: T,
39+
rhs: T,
40+
span: <Self::Interner as Interner>::Span,
41+
) -> Result<
42+
(
43+
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
44+
RegionConstraint<Self::Interner>,
45+
),
46+
TypeError<Self::Interner>,
47+
>;
48+
49+
fn relate_with_region_constraints<T: Relate<Self::Interner>>(
50+
&self,
51+
param_env: <Self::Interner as Interner>::ParamEnv,
52+
lhs: T,
53+
variance: ty::Variance,
54+
rhs: T,
55+
span: <Self::Interner as Interner>::Span,
56+
) -> Result<
57+
(
58+
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
59+
RegionConstraint<Self::Interner>,
60+
),
61+
TypeError<Self::Interner>,
62+
>;
63+
}
64+
65+
fn relate_with_options<Infcx, T>(
66+
infcx: &Infcx,
67+
structurally_relate_aliases: StructurallyRelateAliases,
68+
param_env: <Infcx::Interner as Interner>::ParamEnv,
69+
lhs: T,
70+
variance: ty::Variance,
71+
rhs: T,
72+
span: <Infcx::Interner as Interner>::Span,
73+
collect_region_constraints: bool,
74+
) -> Result<
75+
(
76+
Vec<Goal<Infcx::Interner, <Infcx::Interner as Interner>::Predicate>>,
77+
Option<RegionConstraint<Infcx::Interner>>,
78+
),
79+
TypeError<Infcx::Interner>,
80+
>
81+
where
82+
Infcx: InferCtxtLike,
83+
T: Relate<Infcx::Interner>,
84+
{
85+
let mut relate = SolverRelating::build(
86+
infcx,
87+
structurally_relate_aliases,
88+
variance,
89+
param_env,
90+
span,
91+
collect_region_constraints.then(Vec::new),
92+
);
93+
relate.relate(lhs, rhs)?;
94+
Ok((
95+
relate.goals,
96+
relate.region_constraints.map(|c| RegionConstraint::And(c.into_boxed_slice())),
97+
))
3398
}
3499

35100
impl<Infcx: InferCtxtLike> RelateExt for Infcx {
@@ -44,10 +109,17 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx {
44109
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
45110
TypeError<Self::Interner>,
46111
> {
47-
let mut relate =
48-
SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span);
49-
relate.relate(lhs, rhs)?;
50-
Ok(relate.goals)
112+
let (goals, _) = relate_with_options(
113+
self,
114+
StructurallyRelateAliases::No,
115+
param_env,
116+
lhs,
117+
variance,
118+
rhs,
119+
span,
120+
false,
121+
)?;
122+
Ok(goals)
51123
}
52124

53125
fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
@@ -60,15 +132,70 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx {
60132
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
61133
TypeError<Self::Interner>,
62134
> {
63-
let mut relate = SolverRelating::new(
135+
let (goals, _) = relate_with_options(
64136
self,
65137
StructurallyRelateAliases::Yes,
138+
param_env,
139+
lhs,
66140
ty::Invariant,
141+
rhs,
142+
span,
143+
false,
144+
)?;
145+
Ok(goals)
146+
}
147+
148+
fn eq_structurally_relating_aliases_with_region_constraints<T: Relate<Self::Interner>>(
149+
&self,
150+
param_env: <Self::Interner as Interner>::ParamEnv,
151+
lhs: T,
152+
rhs: T,
153+
span: <Self::Interner as Interner>::Span,
154+
) -> Result<
155+
(
156+
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
157+
RegionConstraint<Self::Interner>,
158+
),
159+
TypeError<Self::Interner>,
160+
> {
161+
let (goals, region_constraints) = relate_with_options(
162+
self,
163+
StructurallyRelateAliases::Yes,
67164
param_env,
165+
lhs,
166+
ty::Invariant,
167+
rhs,
68168
span,
69-
);
70-
relate.relate(lhs, rhs)?;
71-
Ok(relate.goals)
169+
true,
170+
)?;
171+
Ok((goals, region_constraints.unwrap()))
172+
}
173+
174+
fn relate_with_region_constraints<T: Relate<Self::Interner>>(
175+
&self,
176+
param_env: <Self::Interner as Interner>::ParamEnv,
177+
lhs: T,
178+
variance: ty::Variance,
179+
rhs: T,
180+
span: <Self::Interner as Interner>::Span,
181+
) -> Result<
182+
(
183+
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
184+
RegionConstraint<Self::Interner>,
185+
),
186+
TypeError<Self::Interner>,
187+
> {
188+
let (goals, region_constraints) = relate_with_options(
189+
self,
190+
StructurallyRelateAliases::No,
191+
param_env,
192+
lhs,
193+
variance,
194+
rhs,
195+
span,
196+
true,
197+
)?;
198+
Ok((goals, region_constraints.unwrap()))
72199
}
73200
}
74201

@@ -82,6 +209,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> {
82209
// Mutable fields.
83210
ambient_variance: ty::Variance,
84211
goals: Vec<Goal<I, I::Predicate>>,
212+
region_constraints: Option<Vec<RegionConstraint<I>>>,
85213
/// The cache only tracks the `ambient_variance` as it's the
86214
/// only field which is mutable and which meaningfully changes
87215
/// the result when relating types.
@@ -118,6 +246,17 @@ where
118246
ambient_variance: ty::Variance,
119247
param_env: I::ParamEnv,
120248
span: I::Span,
249+
) -> Self {
250+
Self::build(infcx, structurally_relate_aliases, ambient_variance, param_env, span, None)
251+
}
252+
253+
fn build(
254+
infcx: &'infcx Infcx,
255+
structurally_relate_aliases: StructurallyRelateAliases,
256+
ambient_variance: ty::Variance,
257+
param_env: I::ParamEnv,
258+
span: I::Span,
259+
region_constraints: Option<Vec<RegionConstraint<I>>>,
121260
) -> Self {
122261
SolverRelating {
123262
infcx,
@@ -126,6 +265,7 @@ where
126265
ambient_variance,
127266
param_env,
128267
goals: vec![],
268+
region_constraints,
129269
cache: Default::default(),
130270
}
131271
}
@@ -265,6 +405,35 @@ where
265405
}
266406
}
267407

408+
let resolve_region = |r: I::Region| match r.kind() {
409+
ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid),
410+
_ => r,
411+
};
412+
let a = resolve_region(a);
413+
let b = resolve_region(b);
414+
415+
if let Some(region_constraints) = &mut self.region_constraints {
416+
if a == b {
417+
return Ok(a);
418+
} else {
419+
match self.ambient_variance {
420+
ty::Covariant => {
421+
region_constraints.push(RegionConstraint::RegionOutlives(a, b));
422+
}
423+
ty::Contravariant => {
424+
region_constraints.push(RegionConstraint::RegionOutlives(b, a));
425+
}
426+
ty::Invariant => {
427+
region_constraints.push(RegionConstraint::RegionOutlives(a, b));
428+
region_constraints.push(RegionConstraint::RegionOutlives(b, a));
429+
}
430+
ty::Bivariant => {
431+
unreachable!("Expected bivariance to be handled in relate_with_variance")
432+
}
433+
}
434+
}
435+
}
436+
268437
Ok(a)
269438
}
270439

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@compile-flags: -Zassumptions-on-binders -Znext-solver=globally
2+
//@ dont-require-annotations: ERROR
3+
4+
trait Super<U> {
5+
fn a(&self) {
6+
let a: &dyn Sub = &();
7+
let b: &dyn Super<for<'a> fn(&'a ())> = a;
8+
}
9+
}
10+
11+
impl<T> Super<T> for () {}
12+
13+
trait Sub: Super<fn(&'static ())> {}
14+
15+
impl Sub for () {}
16+
17+
fn main() {
18+
let a: &dyn Sub = &();
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0277]: the trait bound `&dyn Sub: CoerceUnsized<&dyn Super<for<'a> fn(&'a ())>>` is not satisfied
2+
--> $DIR/principal-upcast-region-eq-issue-157859.rs:7:49
3+
|
4+
LL | let b: &dyn Super<for<'a> fn(&'a ())> = a;
5+
| ^ the nightly-only, unstable trait `Unsize<dyn Super<for<'a> fn(&'a ())>>` is not implemented for `dyn Sub`
6+
|
7+
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
8+
= note: required for `&dyn Sub` to implement `CoerceUnsized<&dyn Super<for<'a> fn(&'a ())>>`
9+
= note: required for the cast from `&dyn Sub` to `&dyn Super<for<'a> fn(&'a ())>`
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)