diff options
| author | bors <bors@rust-lang.org> | 2018-03-09 10:45:29 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-03-09 10:45:29 +0000 |
| commit | fedce67cd21dc08ece5a484fe1a060346acac98a (patch) | |
| tree | 2cc26079f1d4ee58c1bc38e326585013e52f7e6b /src/test | |
| parent | 2079a084df08c38eb4dbfc5c8de5c0245170c3d9 (diff) | |
| parent | 780b544a391fb2dc42d814ce8cb7e6ad3633fa39 (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.rs | 3 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-17994.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-23046.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/private-in-public-warn.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/rfc1623.rs | 2 | ||||
| -rw-r--r-- | src/test/parse-fail/bounds-lifetime.rs | 11 | ||||
| -rw-r--r-- | src/test/parse-fail/bounds-type.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/impl-trait/lifetimes.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/param-bounds-ignored.rs | 80 | ||||
| -rw-r--r-- | src/test/ui/param-bounds-ignored.stderr | 100 |
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 |
