diff options
| author | bors <bors@rust-lang.org> | 2016-11-04 07:20:44 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-04 07:20:44 -0700 |
| commit | ccfc38f034e3f53cb460936bd9744085d4a63b40 (patch) | |
| tree | 2f7c7808ef2f74a2c40d4c296808be5e2b8edf03 /src/test | |
| parent | d2bc30b03fa4bf5425d080710f681f36f58f1706 (diff) | |
| parent | 4501e5a52f6268a156e95a8fe72ae17c47bf6ee3 (diff) | |
| download | rust-ccfc38f034e3f53cb460936bd9744085d4a63b40.tar.gz rust-ccfc38f034e3f53cb460936bd9744085d4a63b40.zip | |
Auto merge of #37167 - nikomatsakis:jroesch-issue-18937, r=pnkfelix
detect extra region requirements in impls
The current "compare method" check fails to check for the "region obligations" that accrue in the fulfillment context. This branch switches that code to create a `FnCtxt` so that it can invoke the regionck code. Previous crater runs (I haven't done one with the latest tip) have found some small number of affected crates, so I went ahead and introduced a warning cycle. I will kick off a crater run with this branch shortly.
This is a [breaking-change] because previously unsound code was accepted. The crater runs also revealed some cases where legitimate code was no longer type-checking, so the branch contains one additional (but orthogonal) change. It improves the elaborator so that we elaborate region requirements more thoroughly. In particular, if we know that `&'a T: 'b`, we now deduce that `T: 'b` and `'a: 'b`.
I invested a certain amount of effort in getting a good error message. The error message looks like this:
```
error[E0276]: impl has stricter requirements than trait
--> traits-elaborate-projection-region.rs:33:5
|
21 | fn foo() where T: 'a;
| --------------------- definition of `foo` from trait
...
33 | fn foo() where U: 'a { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #18937 <https://github.com/rust-lang/rust/issues/18937>
note: lint level defined here
--> traits-elaborate-projection-region.rs:12:9
|
12 | #![deny(extra_requirement_in_impl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
```
Obviously the warning only prints if this is a _new_ error (that resulted from the bugfix). But all existing errors that fit this description are updated to follow the general template. In order to get the lint to preserve the span-labels and the error code, I separate out the core `Diagnostic` type (which encapsulates the error code, message, span, and children) from the `DiagnosticBuilder` (which layers on a `Handler` that can be used to report errors). I also extended `add_lint` with an alternative `add_lint_diagnostic` that takes in a full diagnostic (cc @jonathandturner for those changes). This doesn't feel ideal but feels like it's moving in the right direction =).
r? @pnkfelix
cc @arielb1
Fixes #18937
Diffstat (limited to 'src/test')
37 files changed, 419 insertions, 30 deletions
diff --git a/src/test/compile-fail/issue-14853.rs b/src/test/compile-fail/issue-14853.rs index c4d88267032..e4da3e4fa43 100644 --- a/src/test/compile-fail/issue-14853.rs +++ b/src/test/compile-fail/issue-14853.rs @@ -20,7 +20,7 @@ struct X { data: u32 } impl Something for X { fn yay<T: Str>(_:Option<X>, thing: &[T]) { - //~^ ERROR the requirement `T: Str` appears on the impl method + //~^ ERROR E0276 } } diff --git a/src/test/compile-fail/issue-18937.rs b/src/test/compile-fail/issue-18937.rs new file mode 100644 index 00000000000..8ac66bb44d2 --- /dev/null +++ b/src/test/compile-fail/issue-18937.rs @@ -0,0 +1,53 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #18937. + +#![deny(extra_requirement_in_impl)] + +use std::fmt; + +#[derive(Debug)] +struct MyString<'a>(&'a String); + +struct B { + list: Vec<Box<fmt::Debug>>, +} + +trait A<'a> { + fn foo<F>(&mut self, f: F) + where F: fmt::Debug + 'a, + Self: Sized; +} + +impl<'a> A<'a> for B { + fn foo<F>(&mut self, f: F) //~ ERROR E0276 + //~^ WARNING future release + where F: fmt::Debug + 'static, + { + self.list.push(Box::new(f)); + } +} + +fn main() { + let mut b = B { list: Vec::new() }; + + // Create a borrowed pointer, put it in `b`, then drop what's borrowing it + let a = "hello".to_string(); + b.foo(MyString(&a)); + + // Drop the data which `b` has a reference to + drop(a); + + // Use the data, probably segfaulting + for b in b.list.iter() { + println!("{:?}", b); + } +} diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs index 6e60a373d9b..1d4ffe0690d 100644 --- a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs +++ b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs @@ -52,7 +52,7 @@ impl<'a, 't> Foo<'a, 't> for &'a isize { } fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { - //~^ ERROR lifetime bound not satisfied + //~^ ERROR E0276 } } diff --git a/src/test/parse-fail/associated-types-project-from-hrtb-explicit.rs b/src/test/parse-fail/associated-types-project-from-hrtb-explicit.rs index 9c7721589d9..70055a10181 100644 --- a/src/test/parse-fail/associated-types-project-from-hrtb-explicit.rs +++ b/src/test/parse-fail/associated-types-project-from-hrtb-explicit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error // Test you can't use a higher-ranked trait bound inside of a qualified // path (just won't parse). diff --git a/src/test/parse-fail/generic-non-trailing-defaults.rs b/src/test/parse-fail/generic-non-trailing-defaults.rs index 26ee6ce80d6..2bb593258ae 100644 --- a/src/test/parse-fail/generic-non-trailing-defaults.rs +++ b/src/test/parse-fail/generic-non-trailing-defaults.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error struct Heap; diff --git a/src/test/parse-fail/issue-17904.rs b/src/test/parse-fail/issue-17904.rs index 580b8c66c74..de5aeb02ab7 100644 --- a/src/test/parse-fail/issue-17904.rs +++ b/src/test/parse-fail/issue-17904.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well. diff --git a/src/test/parse-fail/lex-bad-octal-literal.rs b/src/test/parse-fail/lex-bad-octal-literal.rs index bf9880cb6cf..c8406af52ae 100644 --- a/src/test/parse-fail/lex-bad-octal-literal.rs +++ b/src/test/parse-fail/lex-bad-octal-literal.rs @@ -8,6 +8,8 @@ // 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 + fn main() { 0o18; //~ ERROR invalid digit for a base 8 literal 0o1234_9_5670; //~ ERROR invalid digit for a base 8 literal diff --git a/src/test/parse-fail/lifetime-no-keyword.rs b/src/test/parse-fail/lifetime-no-keyword.rs index 9ca81d9918e..a8771ae93af 100644 --- a/src/test/parse-fail/lifetime-no-keyword.rs +++ b/src/test/parse-fail/lifetime-no-keyword.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error fn foo<'a>(a: &'a isize) { } fn bar(a: &'static isize) { } diff --git a/src/test/parse-fail/raw-byte-string-literals.rs b/src/test/parse-fail/raw-byte-string-literals.rs index d6be8fce53e..2e33f98add6 100644 --- a/src/test/parse-fail/raw-byte-string-literals.rs +++ b/src/test/parse-fail/raw-byte-string-literals.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error pub fn main() { - br"é"; //~ raw byte string must be ASCII - br##~"a"~##; //~ only `#` is allowed in raw string delimitation + br"é"; //~ ERROR raw byte string must be ASCII + br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation } diff --git a/src/test/parse-fail/removed-syntax-field-let.rs b/src/test/parse-fail/removed-syntax-field-let.rs index 4e542fd7477..6deb3bb2e95 100644 --- a/src/test/parse-fail/removed-syntax-field-let.rs +++ b/src/test/parse-fail/removed-syntax-field-let.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error struct s { let foo: (), diff --git a/src/test/parse-fail/syntax-trait-polarity.rs b/src/test/parse-fail/syntax-trait-polarity.rs index c0d85034383..1971ffeaf26 100644 --- a/src/test/parse-fail/syntax-trait-polarity.rs +++ b/src/test/parse-fail/syntax-trait-polarity.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error #![feature(optin_builtin_traits)] diff --git a/src/test/parse-fail/trailing-plus-in-bounds.rs b/src/test/parse-fail/trailing-plus-in-bounds.rs index 4abdbad9a03..44bb1f930c7 100644 --- a/src/test/parse-fail/trailing-plus-in-bounds.rs +++ b/src/test/parse-fail/trailing-plus-in-bounds.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error use std::fmt::Debug; diff --git a/src/test/parse-fail/trait-bounds-not-on-impl.rs b/src/test/parse-fail/trait-bounds-not-on-impl.rs index 3bd8908d18b..b7dcc8a8b3b 100644 --- a/src/test/parse-fail/trait-bounds-not-on-impl.rs +++ b/src/test/parse-fail/trait-bounds-not-on-impl.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error trait Foo { } diff --git a/src/test/parse-fail/use-as-where-use-ends-with-mod-sep.rs b/src/test/parse-fail/use-as-where-use-ends-with-mod-sep.rs index c1e1cc1c7f7..9e16e29ba50 100644 --- a/src/test/parse-fail/use-as-where-use-ends-with-mod-sep.rs +++ b/src/test/parse-fail/use-as-where-use-ends-with-mod-sep.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error use std::any:: as foo; //~ ERROR expected identifier, found keyword `as` //~^ ERROR: expected one of `::`, `;`, or `as`, found `foo` diff --git a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs index 3ac71176342..45165b76c4a 100644 --- a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs +++ b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only +// compile-flags: -Z parse-only -Z continue-parse-after-error fn equal1<T>(_: &T, _: &T) -> bool where { //~^ ERROR a `where` clause must have at least one predicate in it diff --git a/src/test/run-pass/issue-18937-1.rs b/src/test/run-pass/issue-18937-1.rs new file mode 100644 index 00000000000..7a24d087b44 --- /dev/null +++ b/src/test/run-pass/issue-18937-1.rs @@ -0,0 +1,30 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to type-check this example. In particular, +// knowing that `T: 'a` allows us to deduce that `[U]: 'a` (because +// when `T=[U]` it implies that `U: 'a`). +// +// Regr. test for live code we found in the wild when fixing #18937. + +pub trait Leak<T : ?Sized> { + fn leak<'a>(self) -> &'a T where T: 'a; +} + +impl<U> Leak<[U]> for Vec<U> { + fn leak<'a>(mut self) -> &'a [U] where [U]: 'a { + let r: *mut [U] = &mut self[..]; + std::mem::forget(self); + unsafe { &mut *r } + } +} +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/run-pass/traits-elaborate-type-region.rs b/src/test/run-pass/traits-elaborate-type-region.rs new file mode 100644 index 00000000000..4621c2ca4be --- /dev/null +++ b/src/test/run-pass/traits-elaborate-type-region.rs @@ -0,0 +1,58 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized> { + fn foo() where T: 'a; +} + +// [U]: 'a => U: 'a +impl<'a, U> Master<'a, [U]> for () { + fn foo() where U: 'a { } +} + +// &'b U: 'a => 'b: 'a, U: 'a +impl<'a, 'b, U> Master<'a, &'b U> for () { + fn foo() where 'b: 'a, U: 'a { } +} + +// &'b [U]: 'a => 'b: 'a, U: 'a +impl<'a, 'b, U> Master<'a, &'b [U]> for () { + fn foo() where 'b: 'a, U: 'a { } +} + +// Foo<'b>: 'a => 'b: 'a +struct Foo<'a> { x: &'a () } +impl<'a, 'b> Master<'a, Foo<'b>> for () { + fn foo() where 'b: 'a { } +} + +// Bar<'b, T>: 'a => 'b: 'a, T: 'a +struct Bar<'a, T: 'a> { x: &'a T } +impl<'a, 'b, T> Master<'a, Bar<'b, T>> for () { + fn foo() where 'b: 'a, T: 'a { } +} + +// fn(T): 'a => T: 'a +impl<'a, T> Master<'a, fn(T)> for () { + fn foo() where T: 'a { } +} + +// fn() -> T: 'a => T: 'a +impl<'a, T> Master<'a, fn() -> T> for () { + fn foo() where T: 'a { } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/compare-method/proj-outlives-region.rs b/src/test/ui/compare-method/proj-outlives-region.rs new file mode 100644 index 00000000000..54cfe4be9c1 --- /dev/null +++ b/src/test/ui/compare-method/proj-outlives-region.rs @@ -0,0 +1,27 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] +#![deny(extra_requirement_in_impl)] + +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized, U> { + fn foo() where T: 'a; +} + +// `U::Item: 'a` does not imply that `U: 'a` +impl<'a, U: Iterator> Master<'a, U::Item, U> for () { + fn foo() where U: 'a { } //~ ERROR E0276 +} + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr new file mode 100644 index 00000000000..79293e0deed --- /dev/null +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -0,0 +1,19 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/proj-outlives-region.rs:22:5 + | +17 | fn foo() where T: 'a; + | --------------------- definition of `foo` from trait +... +22 | fn foo() where U: 'a { } //~ ERROR E0276 + | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166> +note: lint level defined here + --> $DIR/proj-outlives-region.rs:12:9 + | +12 | #![deny(extra_requirement_in_impl)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/compare-method/proj-outlives-region.stdout b/src/test/ui/compare-method/proj-outlives-region.stdout new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/test/ui/compare-method/proj-outlives-region.stdout diff --git a/src/test/compile-fail/region-bound-extra-bound-in-impl.rs b/src/test/ui/compare-method/region-extra-2.rs index 5bcc6be4c3d..b0cd3b8fdd2 100644 --- a/src/test/compile-fail/region-bound-extra-bound-in-impl.rs +++ b/src/test/ui/compare-method/region-extra-2.rs @@ -17,7 +17,7 @@ trait Tr<'a, T> { impl<'a, T> Tr<'a, T> for &'a mut [T] { fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { - //~^ ERROR lifetime bound not satisfied + //~^ ERROR E0276 &mut self[..] } } diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr new file mode 100644 index 00000000000..54a551bcfed --- /dev/null +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -0,0 +1,11 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/region-extra-2.rs:19:5 + | +15 | fn renew<'b: 'a>(self) -> &'b mut [T]; + | -------------------------------------- definition of `renew` from trait +... +19 | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { + | ^ impl has extra requirement `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/compare-method/region-extra.rs b/src/test/ui/compare-method/region-extra.rs new file mode 100644 index 00000000000..d61d0250211 --- /dev/null +++ b/src/test/ui/compare-method/region-extra.rs @@ -0,0 +1,27 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] +#![deny(extra_requirement_in_impl)] + +// Test that you cannot add an extra where clause in the impl relating +// two regions. + +trait Master<'a, 'b> { + fn foo(); +} + +impl<'a, 'b> Master<'a, 'b> for () { + fn foo() where 'a: 'b { } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr new file mode 100644 index 00000000000..e657813221a --- /dev/null +++ b/src/test/ui/compare-method/region-extra.stderr @@ -0,0 +1,11 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/region-extra.rs:22:5 + | +18 | fn foo(); + | --------- definition of `foo` from trait +... +22 | fn foo() where 'a: 'b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/compare-method/region-extra.stdout b/src/test/ui/compare-method/region-extra.stdout new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/test/ui/compare-method/region-extra.stdout diff --git a/src/test/ui/compare-method/region-unrelated.rs b/src/test/ui/compare-method/region-unrelated.rs new file mode 100644 index 00000000000..8f79b30bd5f --- /dev/null +++ b/src/test/ui/compare-method/region-unrelated.rs @@ -0,0 +1,28 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] +#![deny(extra_requirement_in_impl)] + +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized, U> { + fn foo() where T: 'a; +} + +// `U: 'a` does not imply `V: 'a` +impl<'a, U, V> Master<'a, U, V> for () { + fn foo() where V: 'a { } + //~^ ERROR parameter type `V` may not live long enough +} + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr new file mode 100644 index 00000000000..b7cfdf799bc --- /dev/null +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -0,0 +1,19 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/region-unrelated.rs:22:5 + | +17 | fn foo() where T: 'a; + | --------------------- definition of `foo` from trait +... +22 | fn foo() where V: 'a { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166> +note: lint level defined here + --> $DIR/region-unrelated.rs:12:9 + | +12 | #![deny(extra_requirement_in_impl)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/compare-method/region-unrelated.stdout b/src/test/ui/compare-method/region-unrelated.stdout new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/test/ui/compare-method/region-unrelated.stdout diff --git a/src/test/compile-fail/issue-2611-5.rs b/src/test/ui/compare-method/reordered-type-param.rs index 440294f38ae..0b844d4521d 100644 --- a/src/test/compile-fail/issue-2611-5.rs +++ b/src/test/ui/compare-method/reordered-type-param.rs @@ -10,6 +10,8 @@ // Tests that ty params get matched correctly when comparing // an impl against a trait +// +// cc #26111 trait A { fn b<C:Clone,D>(&self, x: C) -> C; diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr new file mode 100644 index 00000000000..985b85cc4ec --- /dev/null +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -0,0 +1,14 @@ +error[E0053]: method `b` has an incompatible type for trait + --> $DIR/reordered-type-param.rs:26:30 + | +17 | fn b<C:Clone,D>(&self, x: C) -> C; + | - type in trait +... +26 | fn b<F:Clone,G>(&self, _x: G) -> G { panic!() } //~ ERROR method `b` has an incompatible type + | ^ expected type parameter, found a different type parameter + | + = note: expected type `fn(&E, F) -> F` + = note: found type `fn(&E, G) -> G` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/ui/compare-method/trait-bound-on-type-parameter.rs index 16d7ea46846..09e9fb4ca2b 100644 --- a/src/test/compile-fail/issue-2611-4.rs +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Tests that an impl method's bounds aren't *more* restrictive -// than the trait method it's implementing +// Tests that impl can't add extra `F: Sync` bound aren't *more* restrictive +// than the trait method it's implementing. +// +// Regr test for #26111. trait A { fn b<C,D>(&self, x: C) -> C; @@ -20,8 +22,7 @@ struct E { } impl A for E { - fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } - //~^ ERROR `F: std::marker::Sync` appears on the impl method + fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } //~ ERROR E0276 } fn main() {} diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr new file mode 100644 index 00000000000..7112a00c7b7 --- /dev/null +++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -0,0 +1,11 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/trait-bound-on-type-parameter.rs:25:5 + | +17 | fn b<C,D>(&self, x: C) -> C; + | ---------------------------- definition of `b` from trait +... +25 | fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } //~ ERROR E0276 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs b/src/test/ui/compare-method/traits-misc-mismatch-1.rs index 9cf65a9d00d..cca282a1d19 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.rs @@ -34,15 +34,15 @@ trait Foo { impl Foo for isize { // invalid bound for T, was defined as Eq in trait fn test_error1_fn<T: Ord>(&self) {} - //~^ ERROR the requirement `T: std::cmp::Ord` appears on the impl + //~^ ERROR E0276 // invalid bound for T, was defined as Eq + Ord in trait fn test_error2_fn<T: Eq + B>(&self) {} - //~^ ERROR the requirement `T: B` appears on the impl + //~^ ERROR E0276 // invalid bound for T, was defined as Eq + Ord in trait fn test_error3_fn<T: B + Eq>(&self) {} - //~^ ERROR the requirement `T: B` appears on the impl + //~^ ERROR E0276 // multiple bounds, same order as in trait fn test3_fn<T: Ord + Eq>(&self) {} @@ -52,16 +52,16 @@ impl Foo for isize { // parameters in impls must be equal or more general than in the defining trait fn test_error5_fn<T: B>(&self) {} - //~^ ERROR the requirement `T: B` appears on the impl + //~^ ERROR E0276 // bound `std::cmp::Eq` not enforced by this implementation, but this is OK fn test6_fn<T: A>(&self) {} fn test_error7_fn<T: A + Eq>(&self) {} - //~^ ERROR the requirement `T: std::cmp::Eq` appears on the impl + //~^ ERROR E0276 fn test_error8_fn<T: C>(&self) {} - //~^ ERROR the requirement `T: C` appears on the impl + //~^ ERROR E0276 } trait Getter<T> { @@ -74,7 +74,7 @@ trait Trait { impl Trait for usize { fn method<G: Getter<usize>>(&self) {} - //~^ ERROR `G: Getter<usize>` appears on the impl method + //~^ ERROR E0276 } fn main() {} diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr new file mode 100644 index 00000000000..f221ebe3302 --- /dev/null +++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr @@ -0,0 +1,65 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:36:5 + | +23 | fn test_error1_fn<T: Eq>(&self); + | -------------------------------- definition of `test_error1_fn` from trait +... +36 | fn test_error1_fn<T: Ord>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::cmp::Ord` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:40:5 + | +24 | fn test_error2_fn<T: Eq + Ord>(&self); + | -------------------------------------- definition of `test_error2_fn` from trait +... +40 | fn test_error2_fn<T: Eq + B>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:44:5 + | +25 | fn test_error3_fn<T: Eq + Ord>(&self); + | -------------------------------------- definition of `test_error3_fn` from trait +... +44 | fn test_error3_fn<T: B + Eq>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:54:5 + | +28 | fn test_error5_fn<T: A>(&self); + | ------------------------------- definition of `test_error5_fn` from trait +... +54 | fn test_error5_fn<T: B>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: B` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:60:5 + | +30 | fn test_error7_fn<T: A>(&self); + | ------------------------------- definition of `test_error7_fn` from trait +... +60 | fn test_error7_fn<T: A + Eq>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::cmp::Eq` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:63:5 + | +31 | fn test_error8_fn<T: B>(&self); + | ------------------------------- definition of `test_error8_fn` from trait +... +63 | fn test_error8_fn<T: C>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: C` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:76:5 + | +72 | fn method<G:Getter<isize>>(&self); + | ---------------------------------- definition of `method` from trait +... +76 | fn method<G: Getter<usize>>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>` + +error: aborting due to 7 previous errors + diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/ui/compare-method/traits-misc-mismatch-2.rs index 8d587b29ba9..e82cf256df1 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.rs @@ -21,7 +21,7 @@ trait IteratorUtil<A>: Sized impl<A, T: Iterator<A>> IteratorUtil<A> for T { fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> { - //~^ ERROR the requirement `U: Iterator<B>` appears on the impl method + //~^ ERROR E0276 ZipIterator{a: self, b: other} } } diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr new file mode 100644 index 00000000000..5003550fd1e --- /dev/null +++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr @@ -0,0 +1,11 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-2.rs:23:5 + | +19 | fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>; + | ------------------------------------------------------------------ definition of `zip` from trait +... +23 | fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> { + | ^ impl has extra requirement `U: Iterator<B>` + +error: aborting due to previous error + diff --git a/src/test/ui/update-references.sh b/src/test/ui/update-references.sh index f0a6f8a3d44..aa99d35f7aa 100755 --- a/src/test/ui/update-references.sh +++ b/src/test/ui/update-references.sh @@ -36,12 +36,12 @@ while [[ "$1" != "" ]]; do STDOUT_NAME="${1/%.rs/.stdout}" shift if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ - ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME > /dev/null); then + ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then echo updating $MYDIR/$STDOUT_NAME cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME fi if [ -f $BUILD_DIR/$STDERR_NAME ] && \ - ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME > /dev/null); then + ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then echo updating $MYDIR/$STDERR_NAME cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME fi |
