about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-02-23 09:25:23 +0100
committerGitHub <noreply@github.com>2019-02-23 09:25:23 +0100
commit368864329356e3ef8c6aa495b35d55779ae90eaa (patch)
treea6be68cf10f1500d28cfa66b24880d695096fc0d
parentabd6f503fef1900f984d7676929581914306257f (diff)
parent283ffcfce71df51f3d1da4d63441de150938cacd (diff)
downloadrust-368864329356e3ef8c6aa495b35d55779ae90eaa.tar.gz
rust-368864329356e3ef8c6aa495b35d55779ae90eaa.zip
Rollup merge of #58353 - matthewjasper:typeck-pattern-constants, r=arielb1
Check the Self-type of inherent associated constants

r? @arielb1
-rw-r--r--src/librustc_typeck/check/mod.rs26
-rw-r--r--src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs4
-rw-r--r--src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr8
-rw-r--r--src/test/ui/nll/user-annotations/dump-fn-method.rs19
-rw-r--r--src/test/ui/nll/user-annotations/dump-fn-method.stderr20
-rw-r--r--src/test/ui/nll/user-annotations/inherent-associated-constants.rs17
-rw-r--r--src/test/ui/nll/user-annotations/inherent-associated-constants.stderr10
7 files changed, 74 insertions, 30 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 10f234fd3ca..fe13be0b126 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2234,7 +2234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hir_id, def_id, substs, user_self_ty, self.tag(),
         );
 
-        if !substs.is_noop() {
+        if Self::can_contain_user_lifetime_bounds((substs, user_self_ty)) {
             let canonicalized = self.infcx.canonicalize_user_type_annotation(
                 &UserType::TypeOf(def_id, UserSubsts {
                     substs,
@@ -2429,15 +2429,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let ty = self.to_ty(ast_ty);
         debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
 
-        // If the type given by the user has free regions, save it for
-        // later, since NLL would like to enforce those. Also pass in
-        // types that involve projections, since those can resolve to
-        // `'static` bounds (modulo #54940, which hopefully will be
-        // fixed by the time you see this comment, dear reader,
-        // although I have my doubts). Also pass in types with inference
-        // types, because they may be repeated. Other sorts of things
-        // are already sufficiently enforced with erased regions. =)
-        if ty.has_free_regions() || ty.has_projections() || ty.has_infer_types() {
+        if Self::can_contain_user_lifetime_bounds(ty) {
             let c_ty = self.infcx.canonicalize_response(&UserType::Ty(ty));
             debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
             self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
@@ -2446,6 +2438,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         ty
     }
 
+    // If the type given by the user has free regions, save it for later, since
+    // NLL would like to enforce those. Also pass in types that involve
+    // projections, since those can resolve to `'static` bounds (modulo #54940,
+    // which hopefully will be fixed by the time you see this comment, dear
+    // reader, although I have my doubts). Also pass in types with inference
+    // types, because they may be repeated. Other sorts of things are already
+    // sufficiently enforced with erased regions. =)
+    fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
+    where
+        T: TypeFoldable<'tcx>
+    {
+        t.has_free_regions() || t.has_projections() || t.has_infer_types()
+    }
+
     pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
         match self.tables.borrow().node_types().get(id) {
             Some(&t) => t,
diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs
index 5dcd41078c7..45f56836d18 100644
--- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs
+++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.rs
@@ -15,5 +15,7 @@ fn main() {
 
     SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation.
 
-    SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
+    SomeStruct::<u32> { t: 22 }; // No lifetime bounds given.
+
+    SomeStruct::<&'static u32> { t: &22 }; //~ ERROR [&ReStatic u32]
 }
diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr
index 123c26195d0..6e24da094e0 100644
--- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr
+++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr
@@ -1,8 +1,8 @@
-error: user substs: UserSubsts { substs: [u32], user_self_ty: None }
-  --> $DIR/dump-adt-brace-struct.rs:18:5
+error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None }
+  --> $DIR/dump-adt-brace-struct.rs:20:5
    |
-LL |     SomeStruct::<u32> { t: 22 }; //~ ERROR [u32]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     SomeStruct::<&'static u32> { t: &22 }; //~ ERROR [&ReStatic u32]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.rs b/src/test/ui/nll/user-annotations/dump-fn-method.rs
index 7551a9474dc..b689f18c225 100644
--- a/src/test/ui/nll/user-annotations/dump-fn-method.rs
+++ b/src/test/ui/nll/user-annotations/dump-fn-method.rs
@@ -11,7 +11,7 @@ trait Bazoom<T> {
     fn method<U>(&self, arg: T, arg2: U) { }
 }
 
-impl<T, U> Bazoom<U> for T {
+impl<S, T> Bazoom<T> for S {
 }
 
 fn foo<'a, T>(_: T) { }
@@ -22,20 +22,29 @@ fn main() {
     let x = foo;
     x(22);
 
-    // Here: `u32` is given.
-    let x = foo::<u32>; //~ ERROR [u32]
+    // Here: `u32` is given, which doesn't contain any lifetimes, so we don't
+    // have any annotation.
+    let x = foo::<u32>;
     x(22);
 
+    let x = foo::<&'static u32>; //~ ERROR [&ReStatic u32]
+    x(&22);
+
     // Here: we only want the `T` to be given, the rest should be variables.
     //
     // (`T` refers to the declaration of `Bazoom`)
     let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
     x(&22, 44, 66);
 
-    // Here: all are given
-    let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
+    // Here: all are given and definitely contain no lifetimes, so we
+    // don't have any annotation.
+    let x = <u8 as Bazoom<u16>>::method::<u32>;
     x(&22, 44, 66);
 
+    // Here: all are given and we have a lifetime.
+    let x = <u8 as Bazoom<&'static u16>>::method::<u32>; //~ ERROR [u8, &ReStatic u16, u32]
+    x(&22, &44, 66);
+
     // Here: we want in particular that *only* the method `U`
     // annotation is given, the rest are variables.
     //
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
index a1a4e43e8a3..04ceb8e5f84 100644
--- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr
+++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
@@ -1,23 +1,23 @@
-error: user substs: UserSubsts { substs: [u32], user_self_ty: None }
-  --> $DIR/dump-fn-method.rs:26:13
+error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:30:13
    |
-LL |     let x = foo::<u32>; //~ ERROR [u32]
-   |             ^^^^^^^^^^
+LL |     let x = foo::<&'static u32>; //~ ERROR [&ReStatic u32]
+   |             ^^^^^^^^^^^^^^^^^^^
 
 error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None }
-  --> $DIR/dump-fn-method.rs:32:13
+  --> $DIR/dump-fn-method.rs:36:13
    |
 LL |     let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: user substs: UserSubsts { substs: [u8, u16, u32], user_self_ty: None }
-  --> $DIR/dump-fn-method.rs:36:13
+error: user substs: UserSubsts { substs: [u8, &ReStatic u16, u32], user_self_ty: None }
+  --> $DIR/dump-fn-method.rs:45:13
    |
-LL |     let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let x = <u8 as Bazoom<&'static u16>>::method::<u32>; //~ ERROR [u8, &ReStatic u16, u32]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None }
-  --> $DIR/dump-fn-method.rs:44:5
+  --> $DIR/dump-fn-method.rs:53:5
    |
 LL |     y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/user-annotations/inherent-associated-constants.rs b/src/test/ui/nll/user-annotations/inherent-associated-constants.rs
new file mode 100644
index 00000000000..2490187605a
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/inherent-associated-constants.rs
@@ -0,0 +1,17 @@
+#![feature(nll)]
+
+struct A<'a>(&'a ());
+
+impl A<'static> {
+    const IC: i32 = 10;
+}
+
+fn non_wf_associated_const<'a>(x: i32) {
+    A::<'a>::IC; //~ ERROR lifetime may not live long enough
+}
+
+fn wf_associated_const<'a>(x: i32) {
+    A::<'static>::IC;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
new file mode 100644
index 00000000000..785b39ec887
--- /dev/null
+++ b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/inherent-associated-constants.rs:10:5
+   |
+LL | fn non_wf_associated_const<'a>(x: i32) {
+   |                            -- lifetime `'a` defined here
+LL |     A::<'a>::IC; //~ ERROR lifetime may not live long enough
+   |     ^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+