Skip to content

Commit bf51840

Browse files
committed
distinguish user-type annotations from other annotations
In particular, we don't want to preserve the universes for the `'_` variables that appear in there. And we don't expect to find any placeholders, which justifies this as harmless. (In particular, if you have a query like `Foo(!1, !2, ?3)`, then you care about the universe of `?3`, since it may control whether `?3 = !1` and `?3 = !2` is a valid answer. But without any placeholders, we don't really care: any placeholders that would appear in the output must therefore come from some fresh universe anyway.)
1 parent 80d9f8b commit bf51840

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

src/librustc/infer/canonical/canonicalizer.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,20 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
107107
)
108108
}
109109

110+
pub fn canonicalize_user_type_annotation<V>(&self, value: &V) -> Canonicalized<'gcx, V>
111+
where
112+
V: TypeFoldable<'tcx> + Lift<'gcx>,
113+
{
114+
let mut query_state = OriginalQueryValues::default();
115+
Canonicalizer::canonicalize(
116+
value,
117+
Some(self),
118+
self.tcx,
119+
&CanonicalizeUserTypeAnnotation,
120+
&mut query_state,
121+
)
122+
}
123+
110124
/// A hacky variant of `canonicalize_query` that does not
111125
/// canonicalize `'static`. Unfortunately, the existing leak
112126
/// check treaks `'static` differently in some cases (see also
@@ -197,6 +211,29 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
197211
}
198212
}
199213

214+
struct CanonicalizeUserTypeAnnotation;
215+
216+
impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation {
217+
fn canonicalize_free_region(
218+
&self,
219+
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
220+
r: ty::Region<'tcx>,
221+
) -> ty::Region<'tcx> {
222+
match r {
223+
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReEmpty | ty::ReStatic => r,
224+
ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
225+
_ => {
226+
// We only expect region names that the user can type.
227+
bug!("unexpected region in query response: `{:?}`", r)
228+
}
229+
}
230+
}
231+
232+
fn any(&self) -> bool {
233+
false
234+
}
235+
}
236+
200237
struct CanonicalizeAllFreeRegions;
201238

202239
impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {

src/librustc_typeck/check/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
976976
o_ty
977977
};
978978

979-
let c_ty = self.fcx.inh.infcx.canonicalize_response(&revealed_ty);
979+
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(&revealed_ty);
980980
debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
981981
ty.hir_id, o_ty, revealed_ty, c_ty);
982982
self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty);
@@ -2137,7 +2137,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
21372137
method.substs[i]
21382138
}
21392139
});
2140-
self.infcx.canonicalize_response(&UserSubsts {
2140+
self.infcx.canonicalize_user_type_annotation(&UserSubsts {
21412141
substs: just_method_substs,
21422142
user_self_ty: None, // not relevant here
21432143
})
@@ -2181,7 +2181,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
21812181
);
21822182

21832183
if !substs.is_noop() {
2184-
let user_substs = self.infcx.canonicalize_response(&UserSubsts {
2184+
let user_substs = self.infcx.canonicalize_user_type_annotation(&UserSubsts {
21852185
substs,
21862186
user_self_ty,
21872187
});

0 commit comments

Comments
 (0)