Skip to content

Commit

Permalink
distinguish user-type annotations from other annotations
Browse files Browse the repository at this point in the history
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.)
  • Loading branch information
nikomatsakis committed Oct 27, 2018
1 parent 80d9f8b commit bf51840
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
37 changes: 37 additions & 0 deletions src/librustc/infer/canonical/canonicalizer.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -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);
Expand Down Expand Up @@ -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
})
Expand Down Expand Up @@ -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,
});
Expand Down

0 comments on commit bf51840

Please sign in to comment.