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:
parent
80d9f8bb48
commit
bf51840952
2 changed files with 40 additions and 3 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue