Skip to content

Commit 5a52983

Browse files
committed
Auto merge of #54858 - nikomatsakis:universes-refactor-2, r=scalexm
second round of refactorings for universes A second round of (what I believe to be) "no functional change" refactorings, taken from my universes branch. r? @scalexm
2 parents 4f9b581 + 05f67ca commit 5a52983

30 files changed

+536
-501
lines changed

src/librustc/ich/impls_ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
12971297
});
12981298

12991299
impl_stable_hash_for!(
1300-
impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
1300+
impl<'tcx, R> for struct infer::canonical::QueryResponse<'tcx, R> {
13011301
var_values, region_constraints, certainty, value
13021302
}
13031303
);

src/librustc/infer/canonical/canonicalizer.rs

+117-84
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
1818
use infer::canonical::{
1919
Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized,
20-
SmallCanonicalVarValues,
20+
OriginalQueryValues,
2121
};
2222
use infer::InferCtxt;
2323
use std::sync::atomic::Ordering;
@@ -48,7 +48,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
4848
pub fn canonicalize_query<V>(
4949
&self,
5050
value: &V,
51-
var_values: &mut SmallCanonicalVarValues<'tcx>
51+
query_state: &mut OriginalQueryValues<'tcx>,
5252
) -> Canonicalized<'gcx, V>
5353
where
5454
V: TypeFoldable<'tcx> + Lift<'gcx>,
@@ -63,11 +63,8 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
6363
value,
6464
Some(self),
6565
self.tcx,
66-
CanonicalizeRegionMode {
67-
static_region: true,
68-
other_free_regions: true,
69-
},
70-
var_values,
66+
&CanonicalizeAllFreeRegions,
67+
query_state,
7168
)
7269
}
7370

@@ -96,23 +93,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
9693
/// out the [chapter in the rustc guide][c].
9794
///
9895
/// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
99-
pub fn canonicalize_response<V>(
100-
&self,
101-
value: &V,
102-
) -> Canonicalized<'gcx, V>
96+
pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'gcx, V>
10397
where
10498
V: TypeFoldable<'tcx> + Lift<'gcx>,
10599
{
106-
let mut var_values = SmallVec::new();
100+
let mut query_state = OriginalQueryValues::default();
107101
Canonicalizer::canonicalize(
108102
value,
109103
Some(self),
110104
self.tcx,
111-
CanonicalizeRegionMode {
112-
static_region: false,
113-
other_free_regions: false,
114-
},
115-
&mut var_values
105+
&CanonicalizeQueryResponse,
106+
&mut query_state,
116107
)
117108
}
118109

@@ -128,7 +119,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
128119
pub fn canonicalize_hr_query_hack<V>(
129120
&self,
130121
value: &V,
131-
var_values: &mut SmallCanonicalVarValues<'tcx>
122+
query_state: &mut OriginalQueryValues<'tcx>,
132123
) -> Canonicalized<'gcx, V>
133124
where
134125
V: TypeFoldable<'tcx> + Lift<'gcx>,
@@ -143,39 +134,99 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
143134
value,
144135
Some(self),
145136
self.tcx,
146-
CanonicalizeRegionMode {
147-
static_region: false,
148-
other_free_regions: true,
149-
},
150-
var_values
137+
&CanonicalizeFreeRegionsOtherThanStatic,
138+
query_state,
151139
)
152140
}
153141
}
154142

155-
/// If this flag is true, then all free regions will be replaced with
156-
/// a canonical var. This is used to make queries as generic as
157-
/// possible. For example, the query `F: Foo<'static>` would be
158-
/// canonicalized to `F: Foo<'0>`.
159-
struct CanonicalizeRegionMode {
160-
static_region: bool,
161-
other_free_regions: bool,
143+
/// Controls how we canonicalize "free regions" that are not inference
144+
/// variables. This depends on what we are canonicalizing *for* --
145+
/// e.g., if we are canonicalizing to create a query, we want to
146+
/// replace those with inference variables, since we want to make a
147+
/// maximally general query. But if we are canonicalizing a *query
148+
/// response*, then we don't typically replace free regions, as they
149+
/// must have been introduced from other parts of the system.
150+
trait CanonicalizeRegionMode {
151+
fn canonicalize_free_region(
152+
&self,
153+
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
154+
r: ty::Region<'tcx>,
155+
) -> ty::Region<'tcx>;
156+
157+
fn any(&self) -> bool;
158+
}
159+
160+
struct CanonicalizeQueryResponse;
161+
162+
impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
163+
fn canonicalize_free_region(
164+
&self,
165+
_canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
166+
r: ty::Region<'tcx>,
167+
) -> ty::Region<'tcx> {
168+
match r {
169+
ty::ReFree(_) | ty::ReEmpty | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
170+
_ => {
171+
// Other than `'static` or `'empty`, the query
172+
// response should be executing in a fully
173+
// canonicalized environment, so there shouldn't be
174+
// any other region names it can come up.
175+
bug!("unexpected region in query response: `{:?}`", r)
176+
}
177+
}
178+
}
179+
180+
fn any(&self) -> bool {
181+
false
182+
}
162183
}
163184

164-
impl CanonicalizeRegionMode {
185+
struct CanonicalizeAllFreeRegions;
186+
187+
impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
188+
fn canonicalize_free_region(
189+
&self,
190+
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
191+
r: ty::Region<'tcx>,
192+
) -> ty::Region<'tcx> {
193+
canonicalizer.canonical_var_for_region(r)
194+
}
195+
165196
fn any(&self) -> bool {
166-
self.static_region || self.other_free_regions
197+
true
198+
}
199+
}
200+
201+
struct CanonicalizeFreeRegionsOtherThanStatic;
202+
203+
impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
204+
fn canonicalize_free_region(
205+
&self,
206+
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
207+
r: ty::Region<'tcx>,
208+
) -> ty::Region<'tcx> {
209+
if let ty::ReStatic = r {
210+
r
211+
} else {
212+
canonicalizer.canonical_var_for_region(r)
213+
}
214+
}
215+
216+
fn any(&self) -> bool {
217+
true
167218
}
168219
}
169220

170221
struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
171222
infcx: Option<&'cx InferCtxt<'cx, 'gcx, 'tcx>>,
172223
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
173224
variables: SmallVec<[CanonicalVarInfo; 8]>,
174-
var_values: &'cx mut SmallCanonicalVarValues<'tcx>,
225+
query_state: &'cx mut OriginalQueryValues<'tcx>,
175226
// Note that indices is only used once `var_values` is big enough to be
176227
// heap-allocated.
177228
indices: FxHashMap<Kind<'tcx>, CanonicalVar>,
178-
canonicalize_region_mode: CanonicalizeRegionMode,
229+
canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
179230
needs_canonical_flags: TypeFlags,
180231
}
181232

@@ -192,51 +243,25 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
192243
}
193244

194245
ty::ReVar(vid) => {
195-
let r = self
196-
.infcx
246+
let r = self.infcx
197247
.unwrap()
198248
.borrow_region_constraints()
199249
.opportunistic_resolve_var(self.tcx, vid);
200-
let info = CanonicalVarInfo {
201-
kind: CanonicalVarKind::Region,
202-
};
203250
debug!(
204251
"canonical: region var found with vid {:?}, \
205252
opportunistically resolved to {:?}",
206253
vid, r
207254
);
208-
let cvar = self.canonical_var(info, r.into());
209-
self.tcx().mk_region(ty::ReCanonical(cvar))
210-
}
211-
212-
ty::ReStatic => {
213-
if self.canonicalize_region_mode.static_region {
214-
let info = CanonicalVarInfo {
215-
kind: CanonicalVarKind::Region,
216-
};
217-
let cvar = self.canonical_var(info, r.into());
218-
self.tcx().mk_region(ty::ReCanonical(cvar))
219-
} else {
220-
r
221-
}
255+
self.canonical_var_for_region(r)
222256
}
223257

224-
ty::ReEarlyBound(..)
258+
ty::ReStatic
259+
| ty::ReEarlyBound(..)
225260
| ty::ReFree(_)
226261
| ty::ReScope(_)
227262
| ty::RePlaceholder(..)
228263
| ty::ReEmpty
229-
| ty::ReErased => {
230-
if self.canonicalize_region_mode.other_free_regions {
231-
let info = CanonicalVarInfo {
232-
kind: CanonicalVarKind::Region,
233-
};
234-
let cvar = self.canonical_var(info, r.into());
235-
self.tcx().mk_region(ty::ReCanonical(cvar))
236-
} else {
237-
r
238-
}
239-
}
264+
| ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
240265

241266
ty::ReClosureBound(..) | ty::ReCanonical(_) => {
242267
bug!("canonical region encountered during canonicalization")
@@ -302,10 +327,10 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
302327
/// `canonicalize_query` and `canonicalize_response`.
303328
fn canonicalize<V>(
304329
value: &V,
305-
infcx: Option<&'cx InferCtxt<'cx, 'gcx, 'tcx>>,
306-
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
307-
canonicalize_region_mode: CanonicalizeRegionMode,
308-
var_values: &'cx mut SmallCanonicalVarValues<'tcx>
330+
infcx: Option<&InferCtxt<'_, 'gcx, 'tcx>>,
331+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
332+
canonicalize_region_mode: &dyn CanonicalizeRegionMode,
333+
query_state: &mut OriginalQueryValues<'tcx>,
309334
) -> Canonicalized<'gcx, V>
310335
where
311336
V: TypeFoldable<'tcx> + Lift<'gcx>,
@@ -340,7 +365,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
340365
canonicalize_region_mode,
341366
needs_canonical_flags,
342367
variables: SmallVec::new(),
343-
var_values,
368+
query_state,
344369
indices: FxHashMap::default(),
345370
};
346371
let out_value = value.fold_with(&mut canonicalizer);
@@ -371,11 +396,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
371396
fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> CanonicalVar {
372397
let Canonicalizer {
373398
variables,
374-
var_values,
399+
query_state,
375400
indices,
376401
..
377402
} = self;
378403

404+
let var_values = &mut query_state.var_values;
405+
379406
// This code is hot. `variables` and `var_values` are usually small
380407
// (fewer than 8 elements ~95% of the time). They are SmallVec's to
381408
// avoid allocations in those cases. We also don't use `indices` to
@@ -398,28 +425,34 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
398425
// fill up `indices` to facilitate subsequent lookups.
399426
if var_values.spilled() {
400427
assert!(indices.is_empty());
401-
*indices =
402-
var_values.iter()
403-
.enumerate()
404-
.map(|(i, &kind)| (kind, CanonicalVar::new(i)))
405-
.collect();
428+
*indices = var_values
429+
.iter()
430+
.enumerate()
431+
.map(|(i, &kind)| (kind, CanonicalVar::new(i)))
432+
.collect();
406433
}
407434
// The cv is the index of the appended element.
408435
CanonicalVar::new(var_values.len() - 1)
409436
}
410437
} else {
411438
// `var_values` is large. Do a hashmap search via `indices`.
412-
*indices
413-
.entry(kind)
414-
.or_insert_with(|| {
415-
variables.push(info);
416-
var_values.push(kind);
417-
assert_eq!(variables.len(), var_values.len());
418-
CanonicalVar::new(variables.len() - 1)
419-
})
439+
*indices.entry(kind).or_insert_with(|| {
440+
variables.push(info);
441+
var_values.push(kind);
442+
assert_eq!(variables.len(), var_values.len());
443+
CanonicalVar::new(variables.len() - 1)
444+
})
420445
}
421446
}
422447

448+
fn canonical_var_for_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
449+
let info = CanonicalVarInfo {
450+
kind: CanonicalVarKind::Region,
451+
};
452+
let cvar = self.canonical_var(info, r.into());
453+
self.tcx().mk_region(ty::ReCanonical(cvar))
454+
}
455+
423456
/// Given a type variable `ty_var` of the given kind, first check
424457
/// if `ty_var` is bound to anything; if so, canonicalize
425458
/// *that*. Otherwise, create a new canonical variable for

0 commit comments

Comments
 (0)