issue better error message when LUB/GLB diverge under new behavior
This commit is contained in:
parent
397973b601
commit
b224397b7c
@ -762,9 +762,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.note_error_origin(diag, &cause);
|
|
||||||
self.check_and_note_conflicting_crates(diag, terr, span);
|
self.check_and_note_conflicting_crates(diag, terr, span);
|
||||||
self.tcx.note_and_explain_type_err(diag, terr, span);
|
self.tcx.note_and_explain_type_err(diag, terr, span);
|
||||||
|
|
||||||
|
// It reads better to have the error origin as the final
|
||||||
|
// thing.
|
||||||
|
self.note_error_origin(diag, &cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_and_explain_type_error(&self,
|
pub fn report_and_explain_type_error(&self,
|
||||||
@ -772,6 +775,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
terr: &TypeError<'tcx>)
|
terr: &TypeError<'tcx>)
|
||||||
-> DiagnosticBuilder<'tcx>
|
-> DiagnosticBuilder<'tcx>
|
||||||
{
|
{
|
||||||
|
debug!("report_and_explain_type_error(trace={:?}, terr={:?})",
|
||||||
|
trace,
|
||||||
|
terr);
|
||||||
|
|
||||||
let span = trace.cause.span;
|
let span = trace.cause.span;
|
||||||
let failure_str = trace.cause.as_failure_str();
|
let failure_str = trace.cause.as_failure_str();
|
||||||
let mut diag = match trace.cause.code {
|
let mut diag = match trace.cause.code {
|
||||||
|
@ -75,6 +75,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
-> RelateResult<'tcx, ty::Binder<T>>
|
-> RelateResult<'tcx, ty::Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
|
debug!("binders(a={:?}, b={:?})", a, b);
|
||||||
let was_error = self.infcx().probe(|_snapshot| {
|
let was_error = self.infcx().probe(|_snapshot| {
|
||||||
// Subtle: use a fresh combine-fields here because we recover
|
// Subtle: use a fresh combine-fields here because we recover
|
||||||
// from Err. Doing otherwise could propagate obligations out
|
// from Err. Doing otherwise could propagate obligations out
|
||||||
@ -84,6 +85,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
.higher_ranked_glb(a, b, self.a_is_expected)
|
.higher_ranked_glb(a, b, self.a_is_expected)
|
||||||
.is_err()
|
.is_err()
|
||||||
});
|
});
|
||||||
|
debug!("binders: was_error={:?}", was_error);
|
||||||
|
|
||||||
// When higher-ranked types are involved, computing the LUB is
|
// When higher-ranked types are involved, computing the LUB is
|
||||||
// very challenging, switch to invariance. This is obviously
|
// very challenging, switch to invariance. This is obviously
|
||||||
@ -91,6 +93,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
|
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
|
||||||
Ok(_) => Ok(a.clone()),
|
Ok(_) => Ok(a.clone()),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
debug!("binders: error occurred, was_error={:?}", was_error);
|
||||||
if !was_error {
|
if !was_error {
|
||||||
Err(TypeError::OldStyleLUB(Box::new(err)))
|
Err(TypeError::OldStyleLUB(Box::new(err)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,6 +75,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
-> RelateResult<'tcx, ty::Binder<T>>
|
-> RelateResult<'tcx, ty::Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
|
debug!("binders(a={:?}, b={:?})", a, b);
|
||||||
let was_error = self.infcx().probe(|_snapshot| {
|
let was_error = self.infcx().probe(|_snapshot| {
|
||||||
// Subtle: use a fresh combine-fields here because we recover
|
// Subtle: use a fresh combine-fields here because we recover
|
||||||
// from Err. Doing otherwise could propagate obligations out
|
// from Err. Doing otherwise could propagate obligations out
|
||||||
@ -84,6 +85,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
.higher_ranked_lub(a, b, self.a_is_expected)
|
.higher_ranked_lub(a, b, self.a_is_expected)
|
||||||
.is_err()
|
.is_err()
|
||||||
});
|
});
|
||||||
|
debug!("binders: was_error={:?}", was_error);
|
||||||
|
|
||||||
// When higher-ranked types are involved, computing the LUB is
|
// When higher-ranked types are involved, computing the LUB is
|
||||||
// very challenging, switch to invariance. This is obviously
|
// very challenging, switch to invariance. This is obviously
|
||||||
@ -91,6 +93,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
|
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
|
||||||
Ok(_) => Ok(a.clone()),
|
Ok(_) => Ok(a.clone()),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
debug!("binders: error occurred, was_error={:?}", was_error);
|
||||||
if !was_error {
|
if !was_error {
|
||||||
Err(TypeError::OldStyleLUB(Box::new(err)))
|
Err(TypeError::OldStyleLUB(Box::new(err)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -298,6 +298,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
db.span_note(found.origin_span,
|
db.span_note(found.origin_span,
|
||||||
"...that also applies to the same type variable here");
|
"...that also applies to the same type variable here");
|
||||||
}
|
}
|
||||||
|
OldStyleLUB(err) => {
|
||||||
|
db.note("this was previously accepted by the compiler but has been phased out");
|
||||||
|
db.note("for more information, see https://github.com/rust-lang/rust/issues/45852");
|
||||||
|
|
||||||
|
self.note_and_explain_type_err(db, &err, sp);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
36
src/test/ui/lub-glb/old-lub-glb-hr.rs
Normal file
36
src/test/ui/lub-glb/old-lub-glb-hr.rs
Normal 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() {
|
||||||
|
}
|
22
src/test/ui/lub-glb/old-lub-glb-hr.stderr
Normal file
22
src/test/ui/lub-glb/old-lub-glb-hr.stderr
Normal 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
|
||||||
|
|
38
src/test/ui/lub-glb/old-lub-glb-object.rs
Normal file
38
src/test/ui/lub-glb/old-lub-glb-object.rs
Normal 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() {
|
||||||
|
}
|
22
src/test/ui/lub-glb/old-lub-glb-object.stderr
Normal file
22
src/test/ui/lub-glb/old-lub-glb-object.stderr
Normal 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user