Auto merge of #45853 - nikomatsakis:chalk-simplify-hr-lub-glb, r=arielb1

Simplify higher-ranked LUB/GLB

This is a better version of https://github.com/rust-lang/rust/pull/44211. It still makes higher-ranked LUB/GLB into a hard equality test, however, it does try to identify that something changed and issue a notice to the user. I wroteup https://github.com/rust-lang/rust/issues/45852 as a tracking issue for this change.

Currently, this moves straight to a hard-error, on the basis that the crater run in #44211 saw no impact. It might be good to retest -- or perhaps to try for a warning period. Trying to do the latter in a precise way would be somewhat painful, but an imprecise way might suffice -- that is, we could issue warning *whenever* a LUB/GLB operation succeeds that will later fail, even if it doesn't ultimately impact the type check. I could experiment with this.

~~I am *mildly* wary about landing this independently of other code that moves to a universe-based system. In particular, I was nervous that this change would make coherence accepts new pairs of impls that will later be errors. I have the code for the universe-based approach available, I hope to open an PR and run some tests on its impact very shortly.~~ @arielb1 points out that I was being silly.

r? @arielb1
This commit is contained in:
bors 2017-11-17 22:16:11 +00:00
commit 18d8acf41d
14 changed files with 232 additions and 226 deletions

View file

@ -0,0 +1,24 @@
// 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 for a specific corner case: when we compute the LUB of two fn
// types and their parameters have unbound variables. In that case, we
// wind up relating those two variables. This was causing an ICE in an
// in-progress PR.
fn main() {
let a_f: fn(_) = |_| ();
let b_f: fn(_) = |_| ();
let c_f = match 22 {
0 => a_f,
_ => b_f,
};
c_f(4);
}

View file

@ -0,0 +1,36 @@
// Copyright 2017 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 give a note when the old LUB/GLB algorithm would have
// succeeded but the new code (which is stricter) gives an error.
fn foo(
x: fn(&u8, &u8),
y: for<'a> fn(&'a u8, &'a u8),
) {
let z = match 22 {
0 => x,
_ => y,
};
}
fn bar(
x: fn(&u8, &u8),
y: for<'a> fn(&'a u8, &'a u8),
) {
let z = match 22 {
// No error with an explicit cast:
0 => x as for<'a> fn(&'a u8, &'a u8),
_ => y,
};
}
fn main() {
}

View file

@ -0,0 +1,22 @@
error[E0308]: match arms have incompatible types
--> $DIR/old-lub-glb-hr.rs:18:13
|
18 | let z = match 22 {
| _____________^
19 | | 0 => x,
20 | | _ => y,
21 | | };
| |_____^ expected bound lifetime parameter, found concrete lifetime
|
= note: expected type `for<'r, 's> fn(&'r u8, &'s u8)`
found type `for<'a> fn(&'a u8, &'a u8)`
= note: this was previously accepted by the compiler but has been phased out
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
note: match arm with an incompatible type
--> $DIR/old-lub-glb-hr.rs:20:14
|
20 | _ => y,
| ^
error: aborting due to previous error

View file

@ -0,0 +1,38 @@
// Copyright 2017 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 give a note when the old LUB/GLB algorithm would have
// succeeded but the new code (which is stricter) gives an error.
trait Foo<T, U> { }
fn foo(
x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
y: &for<'a> Foo<&'a u8, &'a u8>,
) {
let z = match 22 {
0 => x,
_ => y,
};
}
fn bar(
x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
y: &for<'a> Foo<&'a u8, &'a u8>,
) {
// Accepted with explicit case:
let z = match 22 {
0 => x as &for<'a> Foo<&'a u8, &'a u8>,
_ => y,
};
}
fn main() {
}

View file

@ -0,0 +1,22 @@
error[E0308]: match arms have incompatible types
--> $DIR/old-lub-glb-object.rs:20:13
|
20 | let z = match 22 {
| _____________^
21 | | 0 => x,
22 | | _ => y,
23 | | };
| |_____^ expected bound lifetime parameter 'a, found concrete lifetime
|
= note: expected type `&for<'a, 'b> Foo<&'a u8, &'b u8>`
found type `&for<'a> Foo<&'a u8, &'a u8>`
= note: this was previously accepted by the compiler but has been phased out
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
note: match arm with an incompatible type
--> $DIR/old-lub-glb-object.rs:22:14
|
22 | _ => y,
| ^
error: aborting due to previous error