Skip to content

Commit 4f49352

Browse files
authored
Rollup merge of #107981 - lcnr:canonicalization-uwu, r=compiler-errors
new solver: implement canonicalization and region constraints see the corresponding rustc-dev-guide chapter: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html r? ``@compiler-errors``
2 parents 7a809ce + a15abea commit 4f49352

File tree

13 files changed

+805
-88
lines changed

13 files changed

+805
-88
lines changed

compiler/rustc_infer/src/infer/at.rs

+28
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,34 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
369369
}
370370
}
371371

372+
impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
373+
fn to_trace(
374+
_: TyCtxt<'tcx>,
375+
cause: &ObligationCause<'tcx>,
376+
a_is_expected: bool,
377+
a: Self,
378+
b: Self,
379+
) -> TypeTrace<'tcx> {
380+
use GenericArgKind::*;
381+
TypeTrace {
382+
cause: cause.clone(),
383+
values: match (a.unpack(), b.unpack()) {
384+
(Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)),
385+
(Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
386+
(Const(a), Const(b)) => {
387+
Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
388+
}
389+
390+
(Lifetime(_), Type(_) | Const(_))
391+
| (Type(_), Lifetime(_) | Const(_))
392+
| (Const(_), Lifetime(_) | Type(_)) => {
393+
bug!("relating different kinds: {a:?} {b:?}")
394+
}
395+
},
396+
}
397+
}
398+
}
399+
372400
impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
373401
fn to_trace(
374402
_: TyCtxt<'tcx>,

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, List, TyCtxt};
3030
use rustc_span::source_map::Span;
3131

3232
pub use rustc_middle::infer::canonical::*;
33-
use substitute::CanonicalExt;
33+
pub use substitute::CanonicalExt;
3434

3535
mod canonicalizer;
3636
pub mod query_response;
@@ -100,7 +100,11 @@ impl<'tcx> InferCtxt<'tcx> {
100100
/// variable for it. If this is an existentially quantified
101101
/// variable, then you'll get a new inference variable; if it is a
102102
/// universally quantified variable, you get a placeholder.
103-
fn instantiate_canonical_var(
103+
///
104+
/// FIXME(-Ztrait-solver=next): This is public because it's used by the
105+
/// new trait solver which has a different canonicalization routine.
106+
/// We should somehow deduplicate all of this.
107+
pub fn instantiate_canonical_var(
104108
&self,
105109
span: Span,
106110
cv_info: CanonicalVarInfo<'tcx>,

compiler/rustc_infer/src/infer/canonical/query_response.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,21 @@ impl<'tcx> InferCtxt<'tcx> {
151151
})
152152
}
153153

154-
/// FIXME: This method should only be used for canonical queries and therefore be private.
155-
///
156-
/// As the new solver does canonicalization slightly differently, this is also used there
157-
/// for now. This should hopefully change fairly soon.
158-
pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
154+
/// Used by the new solver as that one takes the opaque types at the end of a probe
155+
/// to deal with multiple candidates without having to recompute them.
156+
pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
157+
self.inner
158+
.borrow()
159+
.opaque_type_storage
160+
.opaque_types
161+
.iter()
162+
.map(|&(k, ref v)| {
163+
(self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)
164+
})
165+
.collect()
166+
}
167+
168+
fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
159169
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
160170
.into_iter()
161171
.map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))

compiler/rustc_infer/src/infer/canonical/substitute.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
1111
use rustc_middle::ty::subst::GenericArgKind;
1212
use rustc_middle::ty::{self, TyCtxt};
1313

14-
pub(super) trait CanonicalExt<'tcx, V> {
14+
/// FIXME(-Ztrait-solver=next): This or public because it is shared with the
15+
/// new trait solver implementation. We should deduplicate canonicalization.
16+
pub trait CanonicalExt<'tcx, V> {
1517
/// Instantiate the wrapped value, replacing each canonical value
1618
/// with the value given in `var_values`.
1719
fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V

compiler/rustc_middle/src/infer/canonical.rs

+61-1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
123123
self.kind.universe()
124124
}
125125

126+
#[must_use]
127+
pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
128+
CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
129+
}
130+
126131
pub fn is_existential(&self) -> bool {
127132
match self.kind {
128133
CanonicalVarKind::Ty(_) => true,
@@ -133,6 +138,28 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
133138
CanonicalVarKind::PlaceholderConst(_, _) => false,
134139
}
135140
}
141+
142+
pub fn is_region(&self) -> bool {
143+
match self.kind {
144+
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
145+
CanonicalVarKind::Ty(_)
146+
| CanonicalVarKind::PlaceholderTy(_)
147+
| CanonicalVarKind::Const(_, _)
148+
| CanonicalVarKind::PlaceholderConst(_, _) => false,
149+
}
150+
}
151+
152+
pub fn expect_anon_placeholder(self) -> u32 {
153+
match self.kind {
154+
CanonicalVarKind::Ty(_)
155+
| CanonicalVarKind::Region(_)
156+
| CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
157+
158+
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
159+
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
160+
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
161+
}
162+
}
136163
}
137164

138165
/// Describes the "kind" of the canonical variable. This is a "kind"
@@ -177,6 +204,38 @@ impl<'tcx> CanonicalVarKind<'tcx> {
177204
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
178205
}
179206
}
207+
208+
/// Replaces the universe of this canonical variable with `ui`.
209+
///
210+
/// In case this is a float or int variable, this causes an ICE if
211+
/// the updated universe is not the root.
212+
pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
213+
match self {
214+
CanonicalVarKind::Ty(kind) => match kind {
215+
CanonicalTyVarKind::General(_) => {
216+
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
217+
}
218+
CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
219+
assert_eq!(ui, ty::UniverseIndex::ROOT);
220+
CanonicalVarKind::Ty(kind)
221+
}
222+
},
223+
CanonicalVarKind::PlaceholderTy(placeholder) => {
224+
CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
225+
}
226+
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
227+
CanonicalVarKind::PlaceholderRegion(placeholder) => {
228+
CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
229+
}
230+
CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
231+
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
232+
CanonicalVarKind::PlaceholderConst(
233+
ty::Placeholder { universe: ui, ..placeholder },
234+
ty,
235+
)
236+
}
237+
}
238+
}
180239
}
181240

182241
/// Rust actually has more than one category of type variables;
@@ -213,7 +272,8 @@ pub struct QueryResponse<'tcx, R> {
213272
pub value: R,
214273
}
215274

216-
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
275+
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
276+
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
217277
pub struct QueryRegionConstraints<'tcx> {
218278
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
219279
pub member_constraints: Vec<MemberConstraint<'tcx>>,

compiler/rustc_middle/src/infer/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use rustc_span::Span;
1212
/// ```text
1313
/// R0 member of [O1..On]
1414
/// ```
15-
#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
15+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16+
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
1617
pub struct MemberConstraint<'tcx> {
1718
/// The `DefId` and substs of the opaque type causing this constraint.
1819
/// Used for error reporting.

compiler/rustc_middle/src/traits/solve.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::ops::ControlFlow;
22

33
use rustc_data_structures::intern::Interned;
44

5+
use crate::infer::canonical::QueryRegionConstraints;
56
use crate::ty::{
67
FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
78
};
@@ -18,20 +19,25 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
1819
}
1920

2021
/// Additional constraints returned on success.
21-
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
22+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)]
2223
pub struct ExternalConstraintsData<'tcx> {
2324
// FIXME: implement this.
24-
pub regions: (),
25+
pub region_constraints: QueryRegionConstraints<'tcx>,
2526
pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
2627
}
2728

29+
// FIXME: Having to clone `region_constraints` for folding feels bad and
30+
// probably isn't great wrt performance.
31+
//
32+
// Not sure how to fix this, maybe we should also intern `opaque_types` and
33+
// `region_constraints` here or something.
2834
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
2935
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
3036
self,
3137
folder: &mut F,
3238
) -> Result<Self, F::Error> {
3339
Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
34-
regions: (),
40+
region_constraints: self.region_constraints.clone().try_fold_with(folder)?,
3541
opaque_types: self
3642
.opaque_types
3743
.iter()
@@ -42,7 +48,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
4248

4349
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
4450
TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
45-
regions: (),
51+
region_constraints: self.region_constraints.clone().fold_with(folder),
4652
opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
4753
})
4854
}
@@ -53,7 +59,7 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
5359
&self,
5460
visitor: &mut V,
5561
) -> std::ops::ControlFlow<V::BreakTy> {
56-
self.regions.visit_with(visitor)?;
62+
self.region_constraints.visit_with(visitor)?;
5763
self.opaque_types.visit_with(visitor)?;
5864
ControlFlow::Continue(())
5965
}

compiler/rustc_middle/src/ty/sty.rs

+9
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ impl BoundRegionKind {
107107
_ => None,
108108
}
109109
}
110+
111+
pub fn expect_anon(&self) -> u32 {
112+
match *self {
113+
BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
114+
bug!("expected anon region: {self:?}")
115+
}
116+
BoundRegionKind::BrAnon(idx, _) => idx,
117+
}
118+
}
110119
}
111120

112121
pub trait Article {

0 commit comments

Comments
 (0)