Skip to content

Commit 1b3164f

Browse files
committed
always emit AliasRelate goals when relating aliases
Add `StructurallyRelateAliases` to allow instantiating infer vars with rigid aliases. Change `instantiate_query_response` to be infallible in the new solver. This requires canonicalization to not hide any information used by the query, so weaken universe compression. It also modifies `term_is_fully_unconstrained` to allow region inference variables in a higher universe.
1 parent eeeb9b4 commit 1b3164f

File tree

21 files changed

+420
-275
lines changed

21 files changed

+420
-275
lines changed

compiler/rustc_borrowck/src/type_check/relate_tys.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_errors::ErrorGuaranteed;
33
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
4-
use rustc_infer::infer::{NllRegionVariableOrigin, ObligationEmittingRelation};
4+
use rustc_infer::infer::NllRegionVariableOrigin;
5+
use rustc_infer::infer::{ObligationEmittingRelation, StructurallyRelateAliases};
56
use rustc_infer::traits::{Obligation, PredicateObligations};
67
use rustc_middle::mir::ConstraintCategory;
78
use rustc_middle::traits::query::NoSolution;
@@ -548,6 +549,10 @@ impl<'bccx, 'tcx> ObligationEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx
548549
self.locations.span(self.type_checker.body)
549550
}
550551

552+
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
553+
StructurallyRelateAliases::No
554+
}
555+
551556
fn param_env(&self) -> ty::ParamEnv<'tcx> {
552557
self.type_checker.param_env
553558
}

compiler/rustc_infer/src/infer/at.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,23 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
302302
let Trace { at, trace, a_is_expected } = self;
303303
let mut fields = at.infcx.combine_fields(trace, at.param_env, define_opaque_types);
304304
fields
305-
.equate(a_is_expected)
305+
.equate(StructurallyRelateAliases::No, a_is_expected)
306+
.relate(a, b)
307+
.map(move |_| InferOk { value: (), obligations: fields.obligations })
308+
}
309+
310+
/// Equates `a` and `b` while structurally relating aliases. This should only
311+
/// be used inside of the next generation trait solver when relating rigid aliases.
312+
#[instrument(skip(self), level = "debug")]
313+
pub fn eq_structurally_relating_aliases<T>(self, a: T, b: T) -> InferResult<'tcx, ()>
314+
where
315+
T: Relate<'tcx>,
316+
{
317+
let Trace { at, trace, a_is_expected } = self;
318+
debug_assert!(at.infcx.next_trait_solver());
319+
let mut fields = at.infcx.combine_fields(trace, at.param_env, DefineOpaqueTypes::No);
320+
fields
321+
.equate(StructurallyRelateAliases::Yes, a_is_expected)
306322
.relate(a, b)
307323
.map(move |_| InferOk { value: (), obligations: fields.obligations })
308324
}

compiler/rustc_infer/src/infer/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use self::region_constraints::{
5454
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
5555
};
5656
pub use self::relate::combine::CombineFields;
57+
pub use self::relate::StructurallyRelateAliases;
5758
use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
5859

5960
pub mod at;

compiler/rustc_infer/src/infer/relate/combine.rs

+41-17
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use super::equate::Equate;
2626
use super::glb::Glb;
2727
use super::lub::Lub;
2828
use super::sub::Sub;
29+
use super::StructurallyRelateAliases;
2930
use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
3031
use crate::traits::{Obligation, PredicateObligations};
3132
use rustc_middle::infer::canonical::OriginalQueryValues;
@@ -116,8 +117,15 @@ impl<'tcx> InferCtxt<'tcx> {
116117
}
117118

118119
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
119-
relation.register_type_relate_obligation(a, b);
120-
Ok(a)
120+
match relation.structurally_relate_aliases() {
121+
StructurallyRelateAliases::Yes => {
122+
ty::relate::structurally_relate_tys(relation, a, b)
123+
}
124+
StructurallyRelateAliases::No => {
125+
relation.register_type_relate_obligation(a, b);
126+
Ok(a)
127+
}
128+
}
121129
}
122130

123131
// All other cases of inference are errors
@@ -240,19 +248,26 @@ impl<'tcx> InferCtxt<'tcx> {
240248
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
241249
if self.tcx.features().generic_const_exprs || self.next_trait_solver() =>
242250
{
243-
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };
244-
245-
relation.register_predicates([if self.next_trait_solver() {
246-
ty::PredicateKind::AliasRelate(
247-
a.into(),
248-
b.into(),
249-
ty::AliasRelationDirection::Equate,
250-
)
251-
} else {
252-
ty::PredicateKind::ConstEquate(a, b)
253-
}]);
254-
255-
Ok(b)
251+
match relation.structurally_relate_aliases() {
252+
StructurallyRelateAliases::No => {
253+
let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) };
254+
255+
relation.register_predicates([if self.next_trait_solver() {
256+
ty::PredicateKind::AliasRelate(
257+
a.into(),
258+
b.into(),
259+
ty::AliasRelationDirection::Equate,
260+
)
261+
} else {
262+
ty::PredicateKind::ConstEquate(a, b)
263+
}]);
264+
265+
Ok(b)
266+
}
267+
StructurallyRelateAliases::Yes => {
268+
ty::relate::structurally_relate_consts(relation, a, b)
269+
}
270+
}
256271
}
257272
_ => ty::relate::structurally_relate_consts(relation, a, b),
258273
}
@@ -303,8 +318,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
303318
self.infcx.tcx
304319
}
305320

306-
pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'tcx> {
307-
Equate::new(self, a_is_expected)
321+
pub fn equate<'a>(
322+
&'a mut self,
323+
structurally_relate_aliases: StructurallyRelateAliases,
324+
a_is_expected: bool,
325+
) -> Equate<'a, 'infcx, 'tcx> {
326+
Equate::new(self, structurally_relate_aliases, a_is_expected)
308327
}
309328

310329
pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'tcx> {
@@ -335,6 +354,11 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
335354

336355
fn param_env(&self) -> ty::ParamEnv<'tcx>;
337356

357+
/// Whether aliases should be related structurally. This is pretty much
358+
/// always `No` unless you're equating in some specific locations of the
359+
/// new solver. See the comments in these use-cases for more details.
360+
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
361+
338362
/// Register obligations that must hold in order for this relation to hold
339363
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
340364

compiler/rustc_infer/src/infer/relate/equate.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::combine::{CombineFields, ObligationEmittingRelation};
2+
use super::StructurallyRelateAliases;
23
use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
34
use crate::traits::PredicateObligations;
45

@@ -13,15 +14,17 @@ use rustc_span::Span;
1314
/// Ensures `a` is made equal to `b`. Returns `a` on success.
1415
pub struct Equate<'combine, 'infcx, 'tcx> {
1516
fields: &'combine mut CombineFields<'infcx, 'tcx>,
17+
structurally_relate_aliases: StructurallyRelateAliases,
1618
a_is_expected: bool,
1719
}
1820

1921
impl<'combine, 'infcx, 'tcx> Equate<'combine, 'infcx, 'tcx> {
2022
pub fn new(
2123
fields: &'combine mut CombineFields<'infcx, 'tcx>,
24+
structurally_relate_aliases: StructurallyRelateAliases,
2225
a_is_expected: bool,
2326
) -> Equate<'combine, 'infcx, 'tcx> {
24-
Equate { fields, a_is_expected }
27+
Equate { fields, structurally_relate_aliases, a_is_expected }
2528
}
2629
}
2730

@@ -99,7 +102,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
99102
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
100103
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
101104
) if a_def_id == b_def_id => {
102-
self.fields.infcx.super_combine_tys(self, a, b)?;
105+
infcx.super_combine_tys(self, a, b)?;
103106
}
104107
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
105108
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
@@ -120,7 +123,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
120123
);
121124
}
122125
_ => {
123-
self.fields.infcx.super_combine_tys(self, a, b)?;
126+
infcx.super_combine_tys(self, a, b)?;
124127
}
125128
}
126129

@@ -180,6 +183,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
180183
self.fields.trace.span()
181184
}
182185

186+
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
187+
self.structurally_relate_aliases
188+
}
189+
183190
fn param_env(&self) -> ty::ParamEnv<'tcx> {
184191
self.fields.param_env
185192
}

compiler/rustc_infer/src/infer/relate/generalize.rs

+46-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::mem;
22

3+
use super::StructurallyRelateAliases;
34
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue};
45
use crate::infer::{InferCtxt, ObligationEmittingRelation, RegionVariableOrigin};
56
use rustc_data_structures::sso::SsoHashMap;
@@ -45,8 +46,14 @@ impl<'tcx> InferCtxt<'tcx> {
4546
// region/type inference variables.
4647
//
4748
// We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`.
48-
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } =
49-
self.generalize(relation.span(), target_vid, instantiation_variance, source_ty)?;
49+
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self
50+
.generalize(
51+
relation.span(),
52+
relation.structurally_relate_aliases(),
53+
target_vid,
54+
instantiation_variance,
55+
source_ty,
56+
)?;
5057

5158
// Constrain `b_vid` to the generalized type `generalized_ty`.
5259
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
@@ -178,8 +185,14 @@ impl<'tcx> InferCtxt<'tcx> {
178185
) -> RelateResult<'tcx, ()> {
179186
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
180187
// constants and generic expressions are not yet handled correctly.
181-
let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } =
182-
self.generalize(relation.span(), target_vid, ty::Variance::Invariant, source_ct)?;
188+
let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = self
189+
.generalize(
190+
relation.span(),
191+
relation.structurally_relate_aliases(),
192+
target_vid,
193+
ty::Variance::Invariant,
194+
source_ct,
195+
)?;
183196

184197
debug_assert!(!generalized_ct.is_ct_infer());
185198
if has_unconstrained_ty_var {
@@ -217,6 +230,7 @@ impl<'tcx> InferCtxt<'tcx> {
217230
fn generalize<T: Into<Term<'tcx>> + Relate<'tcx>>(
218231
&self,
219232
span: Span,
233+
structurally_relate_aliases: StructurallyRelateAliases,
220234
target_vid: impl Into<ty::TermVid>,
221235
ambient_variance: ty::Variance,
222236
source_term: T,
@@ -237,6 +251,7 @@ impl<'tcx> InferCtxt<'tcx> {
237251
let mut generalizer = Generalizer {
238252
infcx: self,
239253
span,
254+
structurally_relate_aliases,
240255
root_vid,
241256
for_universe,
242257
ambient_variance,
@@ -270,6 +285,10 @@ struct Generalizer<'me, 'tcx> {
270285

271286
span: Span,
272287

288+
/// Whether aliases should be related structurally. If not, we have to
289+
/// be careful when generalizing aliases.
290+
structurally_relate_aliases: StructurallyRelateAliases,
291+
273292
/// The vid of the type variable that is in the process of being
274293
/// instantiated. If we find this within the value we are folding,
275294
/// that means we would have created a cyclic value.
@@ -314,13 +333,30 @@ impl<'tcx> Generalizer<'_, 'tcx> {
314333
/// to normalize the alias after all.
315334
///
316335
/// We handle this by lazily equating the alias and generalizing
317-
/// it to an inference variable.
336+
/// it to an inference variable. In the new solver, we always
337+
/// generalize to an infer var unless the alias contains escaping
338+
/// bound variables.
318339
///
319-
/// This is incomplete and will hopefully soon get fixed by #119106.
340+
/// Correctly handling aliases with escaping bound variables is
341+
/// difficult and currently incomplete in two opposite ways:
342+
/// - if we get an occurs check failure in the alias, replace it with a new infer var.
343+
/// This causes us to later emit an alias-relate goal and is incomplete in case the
344+
/// alias normalizes to type containing one of the bound variables.
345+
/// - if the alias contains an inference variable not nameable by `for_universe`, we
346+
/// continue generalizing the alias. This ends up pulling down the universe of the
347+
/// inference variable and is incomplete in case the alias would normalize to a type
348+
/// which does not mention that inference variable.
320349
fn generalize_alias_ty(
321350
&mut self,
322351
alias: ty::AliasTy<'tcx>,
323352
) -> Result<Ty<'tcx>, TypeError<'tcx>> {
353+
if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() {
354+
return Ok(self.infcx.next_ty_var_in_universe(
355+
TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: self.span },
356+
self.for_universe,
357+
));
358+
}
359+
324360
let is_nested_alias = mem::replace(&mut self.in_alias, true);
325361
let result = match self.relate(alias, alias) {
326362
Ok(alias) => Ok(alias.to_ty(self.tcx())),
@@ -490,7 +526,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
490526
}
491527
}
492528

493-
ty::Alias(_, data) => self.generalize_alias_ty(data),
529+
ty::Alias(_, data) => match self.structurally_relate_aliases {
530+
StructurallyRelateAliases::No => self.generalize_alias_ty(data),
531+
StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
532+
},
494533

495534
_ => relate::structurally_relate_tys(self, t, t),
496535
}?;

compiler/rustc_infer/src/infer/relate/glb.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_span::Span;
66

77
use super::combine::{CombineFields, ObligationEmittingRelation};
88
use super::lattice::{self, LatticeDir};
9+
use super::StructurallyRelateAliases;
910
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
1011
use crate::traits::{ObligationCause, PredicateObligations};
1112

@@ -45,7 +46,9 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
4546
b: T,
4647
) -> RelateResult<'tcx, T> {
4748
match variance {
48-
ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
49+
ty::Invariant => {
50+
self.fields.equate(StructurallyRelateAliases::No, self.a_is_expected).relate(a, b)
51+
}
4952
ty::Covariant => self.relate(a, b),
5053
// FIXME(#41044) -- not correct, need test
5154
ty::Bivariant => Ok(a),
@@ -139,6 +142,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
139142
self.fields.trace.span()
140143
}
141144

145+
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
146+
StructurallyRelateAliases::No
147+
}
148+
142149
fn param_env(&self) -> ty::ParamEnv<'tcx> {
143150
self.fields.param_env
144151
}

compiler/rustc_infer/src/infer/relate/lub.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::combine::{CombineFields, ObligationEmittingRelation};
44
use super::lattice::{self, LatticeDir};
5+
use super::StructurallyRelateAliases;
56
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
67
use crate::traits::{ObligationCause, PredicateObligations};
78

@@ -45,7 +46,9 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
4546
b: T,
4647
) -> RelateResult<'tcx, T> {
4748
match variance {
48-
ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
49+
ty::Invariant => {
50+
self.fields.equate(StructurallyRelateAliases::No, self.a_is_expected).relate(a, b)
51+
}
4952
ty::Covariant => self.relate(a, b),
5053
// FIXME(#41044) -- not correct, need test
5154
ty::Bivariant => Ok(a),
@@ -139,6 +142,10 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
139142
self.fields.trace.span()
140143
}
141144

145+
fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
146+
StructurallyRelateAliases::No
147+
}
148+
142149
fn param_env(&self) -> ty::ParamEnv<'tcx> {
143150
self.fields.param_env
144151
}

compiler/rustc_infer/src/infer/relate/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,15 @@ mod higher_ranked;
99
mod lattice;
1010
mod lub;
1111
mod sub;
12+
13+
/// Whether aliases should be related structurally or not. Used
14+
/// to adjust the behavior of generalization and combine.
15+
///
16+
/// This should always be `No` unless in a few special-cases when
17+
/// instantiating canonical responses and in the new solver. Each
18+
/// such case should have a comment explaining why it is used.
19+
#[derive(Debug, Copy, Clone)]
20+
pub enum StructurallyRelateAliases {
21+
Yes,
22+
No,
23+
}

0 commit comments

Comments
 (0)