Skip to content

Commit 025c7b5

Browse files
committed
issue better error message when LUB/GLB diverge under new behavior
1 parent 14c6408 commit 025c7b5

File tree

8 files changed

+141
-3
lines changed

8 files changed

+141
-3
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,16 +764,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
764764
}
765765
}
766766

767-
self.note_error_origin(diag, &cause);
768767
self.check_and_note_conflicting_crates(diag, terr, span);
769768
self.tcx.note_and_explain_type_err(diag, terr, span);
769+
self.check_and_note_conflicting_crates(diag, terr, span);
770+
771+
// It reads better to have the error origin as the final
772+
// thing.
773+
self.note_error_origin(diag, &cause);
770774
}
771775

772776
pub fn report_and_explain_type_error(&self,
773777
trace: TypeTrace<'tcx>,
774778
terr: &TypeError<'tcx>)
775779
-> DiagnosticBuilder<'tcx>
776780
{
781+
debug!("report_and_explain_type_error(trace={:?}, terr={:?})",
782+
trace,
783+
terr);
784+
777785
let span = trace.cause.span;
778786
let failure_str = trace.cause.as_failure_str();
779787
let mut diag = match trace.cause.code {

src/librustc/infer/glb.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,19 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
7575
-> RelateResult<'tcx, ty::Binder<T>>
7676
where T: Relate<'tcx>
7777
{
78+
debug!("binders(a={:?}, b={:?})", a, b);
7879
let was_error = self.infcx().probe(|_snapshot| {
79-
self.fields.higher_ranked_glb(a, b, self.a_is_expected).is_ok()
80+
self.fields.higher_ranked_glb(a, b, self.a_is_expected).is_err()
8081
});
82+
debug!("binders: was_error={:?}", was_error);
8183

8284
// When higher-ranked types are involved, computing the LUB is
8385
// very challenging, switch to invariance. This is obviously
8486
// overly conservative but works ok in practice.
8587
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
8688
Ok(_) => Ok(a.clone()),
8789
Err(err) => {
90+
debug!("binders: error occurred, was_error={:?}", was_error);
8891
if !was_error {
8992
Err(TypeError::OldStyleLUB(Box::new(err)))
9093
} else {

src/librustc/infer/lub.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,19 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
7575
-> RelateResult<'tcx, ty::Binder<T>>
7676
where T: Relate<'tcx>
7777
{
78+
debug!("binders(a={:?}, b={:?})", a, b);
7879
let was_error = self.infcx().probe(|_snapshot| {
79-
self.fields.higher_ranked_lub(a, b, self.a_is_expected).is_ok()
80+
self.fields.higher_ranked_lub(a, b, self.a_is_expected).is_err()
8081
});
82+
debug!("binders: was_error={:?}", was_error);
8183

8284
// When higher-ranked types are involved, computing the LUB is
8385
// very challenging, switch to invariance. This is obviously
8486
// overly conservative but works ok in practice.
8587
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
8688
Ok(_) => Ok(a.clone()),
8789
Err(err) => {
90+
debug!("binders: error occurred, was_error={:?}", was_error);
8891
if !was_error {
8992
Err(TypeError::OldStyleLUB(Box::new(err)))
9093
} else {

src/librustc/ty/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
298298
db.span_note(found.origin_span,
299299
"...that also applies to the same type variable here");
300300
}
301+
OldStyleLUB(err) => {
302+
db.note("this was previously accepted by the compiler but has been phased out");
303+
db.note("for more information, see https://github.com/rust-lang/rust/issues/45852");
304+
305+
self.note_and_explain_type_err(db, &err, sp);
306+
}
301307
_ => {}
302308
}
303309
}

src/test/ui/lub-glb/old-lub-glb-hr.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we give a note when the old LUB/GLB algorithm would have
12+
// succeeded but the new code (which is stricter) gives an error.
13+
14+
fn foo(
15+
x: fn(&u8, &u8),
16+
y: for<'a> fn(&'a u8, &'a u8),
17+
) {
18+
let z = match 22 {
19+
0 => x,
20+
_ => y,
21+
};
22+
}
23+
24+
fn bar(
25+
x: fn(&u8, &u8),
26+
y: for<'a> fn(&'a u8, &'a u8),
27+
) {
28+
let z = match 22 {
29+
// No error with an explicit cast:
30+
0 => x as for<'a> fn(&'a u8, &'a u8),
31+
_ => y,
32+
};
33+
}
34+
35+
fn main() {
36+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: match arms have incompatible types
2+
--> $DIR/old-lub-glb-hr.rs:18:13
3+
|
4+
18 | let z = match 22 {
5+
| _____________^
6+
19 | | 0 => x,
7+
20 | | _ => y,
8+
21 | | };
9+
| |_____^ expected bound lifetime parameter, found concrete lifetime
10+
|
11+
= note: expected type `for<'r, 's> fn(&'r u8, &'s u8)`
12+
found type `for<'a> fn(&'a u8, &'a u8)`
13+
= note: this was previously accepted by the compiler but has been phased out
14+
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
15+
note: match arm with an incompatible type
16+
--> $DIR/old-lub-glb-hr.rs:20:14
17+
|
18+
20 | _ => y,
19+
| ^
20+
21+
error: aborting due to previous error
22+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we give a note when the old LUB/GLB algorithm would have
12+
// succeeded but the new code (which is stricter) gives an error.
13+
14+
trait Foo<T, U> { }
15+
16+
fn foo(
17+
x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
18+
y: &for<'a> Foo<&'a u8, &'a u8>,
19+
) {
20+
let z = match 22 {
21+
0 => x,
22+
_ => y,
23+
};
24+
}
25+
26+
fn bar(
27+
x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
28+
y: &for<'a> Foo<&'a u8, &'a u8>,
29+
) {
30+
// Accepted with explicit case:
31+
let z = match 22 {
32+
0 => x as &for<'a> Foo<&'a u8, &'a u8>,
33+
_ => y,
34+
};
35+
}
36+
37+
fn main() {
38+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: match arms have incompatible types
2+
--> $DIR/old-lub-glb-object.rs:20:13
3+
|
4+
20 | let z = match 22 {
5+
| _____________^
6+
21 | | 0 => x,
7+
22 | | _ => y,
8+
23 | | };
9+
| |_____^ expected bound lifetime parameter 'a, found concrete lifetime
10+
|
11+
= note: expected type `&for<'a, 'b> Foo<&'a u8, &'b u8>`
12+
found type `&for<'a> Foo<&'a u8, &'a u8>`
13+
= note: this was previously accepted by the compiler but has been phased out
14+
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
15+
note: match arm with an incompatible type
16+
--> $DIR/old-lub-glb-object.rs:22:14
17+
|
18+
22 | _ => y,
19+
| ^
20+
21+
error: aborting due to previous error
22+

0 commit comments

Comments
 (0)