about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-03-09 10:45:29 +0000
committerbors <bors@rust-lang.org>2018-03-09 10:45:29 +0000
commitfedce67cd21dc08ece5a484fe1a060346acac98a (patch)
tree2cc26079f1d4ee58c1bc38e326585013e52f7e6b /src/test
parent2079a084df08c38eb4dbfc5c8de5c0245170c3d9 (diff)
parent780b544a391fb2dc42d814ce8cb7e6ad3633fa39 (diff)
Auto merge of #48326 - RalfJung:generic-bounds, r=petrochenkov
Warn about ignored generic bounds in `for`

This adds a new lint to fix #42181. For consistency and to avoid code duplication, I also moved the existing "bounds in type aliases are ignored" here.

Questions to the reviewer:
* Is it okay to just remove a diagnostic error code like this? Should I instead keep the warning about type aliases where it is? The old code provided a detailed explanation of what's going on when asked, that information is now lost. On the other hand, `span_warn!` seems deprecated (after this patch, it has exactly one user left!).
* Did I miss any syntactic construct that can appear as `for` in the surface syntax? I covered function types (`for<'a> fn(...)`), generic traits (`for <'a> Fn(...)`, can appear both as bounds as as trait objects) and bounds (`for<'a> F: ...`).
* For the sake of backwards compatibility, this adds a warning, not an error. @nikomatsakis suggested an error in https://github.com/rust-lang/rust/issues/42181#issuecomment-306924389, but I feel that can only happen in a new epoch -- right?

Cc @eddyb
Diffstat (limited to 'src/test')
-rw-r--r--src/test/compile-fail/bounds-lifetime.rs (renamed from src/test/compile-fail/issue-39122.rs)8
-rw-r--r--src/test/compile-fail/dst-bad-assign-3.rs3
-rw-r--r--src/test/compile-fail/issue-17994.rs2
-rw-r--r--src/test/compile-fail/issue-23046.rs4
-rw-r--r--src/test/compile-fail/private-in-public-warn.rs4
-rw-r--r--src/test/compile-fail/rfc1623.rs2
-rw-r--r--src/test/parse-fail/bounds-lifetime.rs11
-rw-r--r--src/test/parse-fail/bounds-type.rs2
-rw-r--r--src/test/run-pass/impl-trait/lifetimes.rs4
-rw-r--r--src/test/ui/param-bounds-ignored.rs80
-rw-r--r--src/test/ui/param-bounds-ignored.stderr100
11 files changed, 184 insertions, 36 deletions
diff --git a/src/test/compile-fail/issue-39122.rs b/src/test/compile-fail/bounds-lifetime.rs
index 2e8a740f893..5bfaa6c54fa 100644
--- a/src/test/compile-fail/issue-39122.rs
+++ b/src/test/compile-fail/bounds-lifetime.rs
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-type Foo<T: std::ops::Add> = T; //~ WARNING E0122
+type A = for<'b, 'a: 'b> fn(); //~ ERROR lifetime bounds cannot be used in this context
+type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context
+type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context
+type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
+type E = for<T> Fn(); //~ ERROR only lifetime parameters can be used in this context
 
-type Bar<T> where T: std::ops::Add = T; //~ WARNING E0122
+fn main() {}
diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs
index 759da7b2bde..ceaa3716232 100644
--- a/src/test/compile-fail/dst-bad-assign-3.rs
+++ b/src/test/compile-fail/dst-bad-assign-3.rs
@@ -12,8 +12,7 @@
 
 #![feature(unsized_tuple_coercion)]
 
-type Fat<T: ?Sized> = (isize, &'static str, T);
-//~^ WARNING bounds are ignored
+type Fat<T> = (isize, &'static str, T);
 
 #[derive(PartialEq,Eq)]
 struct Bar;
diff --git a/src/test/compile-fail/issue-17994.rs b/src/test/compile-fail/issue-17994.rs
index ac15bd9d15b..0f30e2461cf 100644
--- a/src/test/compile-fail/issue-17994.rs
+++ b/src/test/compile-fail/issue-17994.rs
@@ -10,5 +10,5 @@
 
 trait Tr {}
 type Huh<T> where T: Tr = isize; //~  ERROR type parameter `T` is unused
-                                 //~| WARNING E0122
+                                 //~| WARNING where clauses are ignored in type aliases
 fn main() {}
diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs
index 129f7c8b1ea..670706b7a9a 100644
--- a/src/test/compile-fail/issue-23046.rs
+++ b/src/test/compile-fail/issue-23046.rs
@@ -10,7 +10,7 @@
 
 pub enum Expr<'var, VAR> {
     Let(Box<Expr<'var, VAR>>,
-        Box<for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>)
+        Box<for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>)
 }
 
 pub fn add<'var, VAR>
@@ -18,7 +18,7 @@ pub fn add<'var, VAR>
     loop {}
 }
 
-pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
+pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
                        (a: Expr<'var, VAR>, b: F) -> Expr<'var, VAR> {
     loop {}
 }
diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs
index aa91ce27c37..cc9eed7e654 100644
--- a/src/test/compile-fail/private-in-public-warn.rs
+++ b/src/test/compile-fail/private-in-public-warn.rs
@@ -58,7 +58,7 @@ mod traits {
     pub trait PubTr {}
 
     pub type Alias<T: PrivTr> = T; //~ ERROR private trait `traits::PrivTr` in public interface
-    //~^ WARN bounds are ignored in type aliases
+    //~^ WARNING bounds on generic parameters are ignored
     //~| WARNING hard error
     pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface
     //~^ WARNING hard error
@@ -85,7 +85,7 @@ mod traits_where {
     pub type Alias<T> where T: PrivTr = T;
         //~^ ERROR private trait `traits_where::PrivTr` in public interface
         //~| WARNING hard error
-        //~| WARNING E0122
+        //~| WARNING where clauses are ignored in type aliases
     pub trait Tr2<T> where T: PrivTr {}
         //~^ ERROR private trait `traits_where::PrivTr` in public interface
         //~| WARNING hard error
diff --git a/src/test/compile-fail/rfc1623.rs b/src/test/compile-fail/rfc1623.rs
index e8295e5e2da..579fa378a1c 100644
--- a/src/test/compile-fail/rfc1623.rs
+++ b/src/test/compile-fail/rfc1623.rs
@@ -22,7 +22,7 @@ static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
 struct SomeStruct<'x, 'y, 'z: 'x> {
     foo: &'x Foo<'z>,
     bar: &'x Bar<'z>,
-    f: &'y for<'a, 'b: 'a> Fn(&'a Foo<'b>) -> &'a Bar<'b>,
+    f: &'y for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>,
 }
 
 fn id<T>(t: T) -> T {
diff --git a/src/test/parse-fail/bounds-lifetime.rs b/src/test/parse-fail/bounds-lifetime.rs
index 5113a6b4803..88db205310c 100644
--- a/src/test/parse-fail/bounds-lifetime.rs
+++ b/src/test/parse-fail/bounds-lifetime.rs
@@ -8,17 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only -Z continue-parse-after-error
+// compile-flags: -Z parse-only
 
-type A = for<'a: 'b + 'c> fn(); // OK
-type A = for<'a: 'b,> fn(); // OK
 type A = for<'a:> fn(); // OK
 type A = for<'a:,> fn(); // OK
 type A = for<'a> fn(); // OK
 type A = for<> fn(); // OK
-type A = for<'a: 'b +> fn(); // OK
-
-type A = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
+type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation)
+type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation)
+type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation)
+type A = for<'a, T> fn(); // OK (rejected later by ast_validation)
 type A = for<,> fn(); //~ ERROR expected one of `>`, identifier, or lifetime, found `,`
 
 fn main() {}
diff --git a/src/test/parse-fail/bounds-type.rs b/src/test/parse-fail/bounds-type.rs
index c224b44a14b..0ebe7fde0a6 100644
--- a/src/test/parse-fail/bounds-type.rs
+++ b/src/test/parse-fail/bounds-type.rs
@@ -15,7 +15,7 @@ struct S<
     T: Tr + 'a, // OK
     T: 'a, // OK
     T:, // OK
-    T: ?for<'a: 'b + 'c> Trait, // OK
+    T: ?for<'a> Trait, // OK
     T: Tr +, // OK
     T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
 >;
diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs
index 2d5dfb045db..fcad23926fc 100644
--- a/src/test/run-pass/impl-trait/lifetimes.rs
+++ b/src/test/run-pass/impl-trait/lifetimes.rs
@@ -69,8 +69,8 @@ fn foo(x: &impl Debug) -> &impl Debug { x }
 fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> &'a impl Debug { x }
 fn foo_explicit_arg<T: Debug>(x: &T) -> &impl Debug { x }
 
-fn mixed_lifetimes<'a>() -> impl for<'b: 'a> Fn(&'b u32) { |_| () }
-fn mixed_as_static() -> impl Fn(&'static u32) { mixed_lifetimes() }
+fn mixed_lifetimes<'a>() -> impl for<'b> Fn(&'b &'a u32) { |_| () }
+fn mixed_as_static() -> impl Fn(&'static &'static u32) { mixed_lifetimes() }
 
 trait MultiRegionTrait<'a, 'b>: Debug {}
 
diff --git a/src/test/ui/param-bounds-ignored.rs b/src/test/ui/param-bounds-ignored.rs
index 9e09102f2d4..94bcdec9450 100644
--- a/src/test/ui/param-bounds-ignored.rs
+++ b/src/test/ui/param-bounds-ignored.rs
@@ -8,13 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// must-compile-successfully
+#![allow(dead_code, non_camel_case_types)]
 
 use std::rc::Rc;
 
-type SVec<T: Send> = Vec<T>;
-type VVec<'b, 'a: 'b> = Vec<&'a i32>;
-type WVec<'b, T: 'b> = Vec<T>;
+type SVec<T: Send+Send> = Vec<T>;
+//~^ WARN bounds on generic parameters are ignored in type aliases
+type VVec<'b, 'a: 'b+'b> = Vec<&'a i32>;
+//~^ WARN bounds on generic parameters are ignored in type aliases
+type WVec<'b, T: 'b+'b> = Vec<T>;
+//~^ WARN bounds on generic parameters are ignored in type aliases
+type W2Vec<'b, T> where T: 'b, T: 'b = Vec<T>;
+//~^ WARN where clauses are ignored in type aliases
 
 fn foo<'a>(y: &'a i32) {
     // If the bounds above would matter, the code below would be rejected.
@@ -26,8 +31,73 @@ fn foo<'a>(y: &'a i32) {
 
     let mut x : WVec<'static, & 'a i32> = Vec::new();
     x.push(y);
+
+    let mut x : W2Vec<'static, & 'a i32> = Vec::new();
+    x.push(y);
+}
+
+fn bar1<'a, 'b>(
+    x: &'a i32,
+    y: &'b i32,
+    f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32)
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
 }
 
+fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(
+    //~^ ERROR lifetime bounds cannot be used in this context
+    x: &'a i32,
+    y: &'b i32,
+    f: F)
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+fn bar3<'a, 'b, F>(
+    x: &'a i32,
+    y: &'b i32,
+    f: F)
+    where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+fn bar4<'a, 'b, F>(
+    x: &'a i32,
+    y: &'b i32,
+    f: F)
+    where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+    // If the bound in f's type would matter, the call below would (have to)
+    // be rejected.
+    f(x, y);
+}
+
+struct S1<F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(F);
+//~^ ERROR lifetime bounds cannot be used in this context
+struct S2<F>(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32;
+//~^ ERROR lifetime bounds cannot be used in this context
+struct S3<F>(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32;
+//~^ ERROR lifetime bounds cannot be used in this context
+
+struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32);
+//~^ ERROR lifetime bounds cannot be used in this context
+
+type T1 = Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
+//~^ ERROR lifetime bounds cannot be used in this context
+
 fn main() {
-    foo(&42);
+    let _ : Option<for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32> = None;
+    //~^ ERROR lifetime bounds cannot be used in this context
+    let _ : Option<Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
+    //~^ ERROR lifetime bounds cannot be used in this context
 }
diff --git a/src/test/ui/param-bounds-ignored.stderr b/src/test/ui/param-bounds-ignored.stderr
index fe5986448fa..657fec54f96 100644
--- a/src/test/ui/param-bounds-ignored.stderr
+++ b/src/test/ui/param-bounds-ignored.stderr
@@ -1,18 +1,94 @@
-warning[E0122]: generic bounds are ignored in type aliases
-  --> $DIR/param-bounds-ignored.rs:15:1
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:42:22
    |
-LL | type SVec<T: Send> = Vec<T>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32)
+   |                      ^^^ ^^^
 
-warning[E0122]: generic bounds are ignored in type aliases
-  --> $DIR/param-bounds-ignored.rs:16:1
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:50:34
    |
-LL | type VVec<'b, 'a: 'b> = Vec<&'a i32>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(
+   |                                  ^^^
 
-warning[E0122]: generic bounds are ignored in type aliases
-  --> $DIR/param-bounds-ignored.rs:17:1
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:65:28
    |
-LL | type WVec<'b, T: 'b> = Vec<T>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32
+   |                            ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:77:25
+   |
+LL |     where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32
+   |                         ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:85:28
+   |
+LL | struct S1<F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>(F);
+   |                            ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:87:40
+   |
+LL | struct S2<F>(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32;
+   |                                        ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:89:37
+   |
+LL | struct S3<F>(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32;
+   |                                     ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:92:29
+   |
+LL | struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32);
+   |                             ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:95:29
+   |
+LL | type T1 = Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
+   |                             ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:99:34
+   |
+LL |     let _ : Option<for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32> = None;
+   |                                  ^^^
+
+error: lifetime bounds cannot be used in this context
+  --> $DIR/param-bounds-ignored.rs:101:38
+   |
+LL |     let _ : Option<Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
+   |                                      ^^^
+
+warning: bounds on generic parameters are ignored in type aliases
+  --> $DIR/param-bounds-ignored.rs:15:14
+   |
+LL | type SVec<T: Send+Send> = Vec<T>;
+   |              ^^^^ ^^^^
+   |
+   = note: #[warn(ignored_generic_bounds)] on by default
+
+warning: bounds on generic parameters are ignored in type aliases
+  --> $DIR/param-bounds-ignored.rs:17:19
+   |
+LL | type VVec<'b, 'a: 'b+'b> = Vec<&'a i32>;
+   |                   ^^ ^^
+
+warning: bounds on generic parameters are ignored in type aliases
+  --> $DIR/param-bounds-ignored.rs:19:18
+   |
+LL | type WVec<'b, T: 'b+'b> = Vec<T>;
+   |                  ^^ ^^
+
+warning: where clauses are ignored in type aliases
+  --> $DIR/param-bounds-ignored.rs:21:25
+   |
+LL | type W2Vec<'b, T> where T: 'b, T: 'b = Vec<T>;
+   |                         ^^^^^  ^^^^^
+
+error: aborting due to 11 previous errors