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.)
This commit is contained in:
Niko Matsakis 2018-10-01 16:36:31 -04:00
parent 80d9f8bb48
commit bf51840952
2 changed files with 40 additions and 3 deletions

View file

@ -107,6 +107,20 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
)
}
pub fn canonicalize_user_type_annotation<V>(&self, value: &V) -> Canonicalized<'gcx, V>
where
V: TypeFoldable<'tcx> + Lift<'gcx>,
{
let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize(
value,
Some(self),
self.tcx,
&CanonicalizeUserTypeAnnotation,
&mut query_state,
)
}
/// A hacky variant of `canonicalize_query` that does not
/// canonicalize `'static`. Unfortunately, the existing leak
/// check treaks `'static` differently in some cases (see also
@ -197,6 +211,29 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
}
}
struct CanonicalizeUserTypeAnnotation;
impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation {
fn canonicalize_free_region(
&self,
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
match r {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReEmpty | ty::ReStatic => r,
ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
_ => {
// We only expect region names that the user can type.
bug!("unexpected region in query response: `{:?}`", r)
}
}
}
fn any(&self) -> bool {
false
}
}
struct CanonicalizeAllFreeRegions;
impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {

View file

@ -976,7 +976,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
o_ty
};
let c_ty = self.fcx.inh.infcx.canonicalize_response(&revealed_ty);
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(&revealed_ty);
debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
ty.hir_id, o_ty, revealed_ty, c_ty);
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> {
method.substs[i]
}
});
self.infcx.canonicalize_response(&UserSubsts {
self.infcx.canonicalize_user_type_annotation(&UserSubsts {
substs: just_method_substs,
user_self_ty: None, // not relevant here
})
@ -2181,7 +2181,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
);
if !substs.is_noop() {
let user_substs = self.infcx.canonicalize_response(&UserSubsts {
let user_substs = self.infcx.canonicalize_user_type_annotation(&UserSubsts {
substs,
user_self_ty,
});