about summary refs log tree commit diff
path: root/src/librustc/infer
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-10-01 16:36:31 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-10-27 09:06:03 -0400
commitbf51840952b701606fa6aa5e076b4e27fb8d9ee8 (patch)
tree12bd8210898607306ff7c00f64eb7c170eb69f81 /src/librustc/infer
parent80d9f8bb48d2799307f84dd8fa69884c5a407ac6 (diff)
downloadrust-bf51840952b701606fa6aa5e076b4e27fb8d9ee8.tar.gz
rust-bf51840952b701606fa6aa5e076b4e27fb8d9ee8.zip
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.)
Diffstat (limited to 'src/librustc/infer')
-rw-r--r--src/librustc/infer/canonical/canonicalizer.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index 94bb17988c7..cc6e4df0710 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -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 {