about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-11-04 07:20:44 -0700
committerGitHub <noreply@github.com>2016-11-04 07:20:44 -0700
commitccfc38f034e3f53cb460936bd9744085d4a63b40 (patch)
tree2f7c7808ef2f74a2c40d4c296808be5e2b8edf03 /src/test
parentd2bc30b03fa4bf5425d080710f681f36f58f1706 (diff)
parent4501e5a52f6268a156e95a8fe72ae17c47bf6ee3 (diff)
downloadrust-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')
-rw-r--r--src/test/compile-fail/issue-14853.rs2
-rw-r--r--src/test/compile-fail/issue-18937.rs53
-rw-r--r--src/test/compile-fail/regions-bound-missing-bound-in-impl.rs2
-rw-r--r--src/test/parse-fail/associated-types-project-from-hrtb-explicit.rs2
-rw-r--r--src/test/parse-fail/generic-non-trailing-defaults.rs2
-rw-r--r--src/test/parse-fail/issue-17904.rs2
-rw-r--r--src/test/parse-fail/lex-bad-octal-literal.rs2
-rw-r--r--src/test/parse-fail/lifetime-no-keyword.rs2
-rw-r--r--src/test/parse-fail/raw-byte-string-literals.rs6
-rw-r--r--src/test/parse-fail/removed-syntax-field-let.rs2
-rw-r--r--src/test/parse-fail/syntax-trait-polarity.rs2
-rw-r--r--src/test/parse-fail/trailing-plus-in-bounds.rs2
-rw-r--r--src/test/parse-fail/trait-bounds-not-on-impl.rs2
-rw-r--r--src/test/parse-fail/use-as-where-use-ends-with-mod-sep.rs2
-rw-r--r--src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs2
-rw-r--r--src/test/run-pass/issue-18937-1.rs30
-rw-r--r--src/test/run-pass/traits-elaborate-type-region.rs58
-rw-r--r--src/test/ui/compare-method/proj-outlives-region.rs27
-rw-r--r--src/test/ui/compare-method/proj-outlives-region.stderr19
-rw-r--r--src/test/ui/compare-method/proj-outlives-region.stdout0
-rw-r--r--src/test/ui/compare-method/region-extra-2.rs (renamed from src/test/compile-fail/region-bound-extra-bound-in-impl.rs)2
-rw-r--r--src/test/ui/compare-method/region-extra-2.stderr11
-rw-r--r--src/test/ui/compare-method/region-extra.rs27
-rw-r--r--src/test/ui/compare-method/region-extra.stderr11
-rw-r--r--src/test/ui/compare-method/region-extra.stdout0
-rw-r--r--src/test/ui/compare-method/region-unrelated.rs28
-rw-r--r--src/test/ui/compare-method/region-unrelated.stderr19
-rw-r--r--src/test/ui/compare-method/region-unrelated.stdout0
-rw-r--r--src/test/ui/compare-method/reordered-type-param.rs (renamed from src/test/compile-fail/issue-2611-5.rs)2
-rw-r--r--src/test/ui/compare-method/reordered-type-param.stderr14
-rw-r--r--src/test/ui/compare-method/trait-bound-on-type-parameter.rs (renamed from src/test/compile-fail/issue-2611-4.rs)9
-rw-r--r--src/test/ui/compare-method/trait-bound-on-type-parameter.stderr11
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-1.rs (renamed from src/test/compile-fail/trait-bounds-impl-comparison-1.rs)14
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-1.stderr65
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-2.rs (renamed from src/test/compile-fail/trait-bounds-impl-comparison-2.rs)2
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-2.stderr11
-rwxr-xr-xsrc/test/ui/update-references.sh4
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