Provide more information for HRTB lifetime errors involving closures

This commit is contained in:
Esteban Küber 2020-12-01 00:10:13 -08:00
parent 704e47f78b
commit a8a974245e
18 changed files with 392 additions and 25 deletions

View File

@ -98,7 +98,7 @@ pub(super) fn note_and_explain_region(
// uh oh, hope no user ever sees THIS
ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
ty::RePlaceholder(_) => ("any other region".to_string(), None),
ty::RePlaceholder(_) => return,
// FIXME(#13998) RePlaceholder should probably print like
// ReFree rather than dumping Debug output on the user.
@ -1675,6 +1675,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.check_and_note_conflicting_crates(diag, terr);
self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
if let Some(def_id) = def_id.as_local() {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let span = self.tcx.hir().span(hir_id);
diag.span_note(span, "this closure does not fulfill the lifetime requirements");
}
}
}
// It reads better to have the error origin as the final
// thing.
self.note_error_origin(diag, cause, exp_found);

View File

@ -1,6 +1,7 @@
use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
use crate::infer::{self, InferCtxt, SubregionOrigin};
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Region};
@ -107,14 +108,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, &terr);
note_and_explain_region(self.tcx, &mut err, "", sup, "...");
note_and_explain_region(
self.tcx,
&mut err,
"...does not necessarily outlive ",
sub,
"",
);
match (sub, sup) {
(ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
(ty::RePlaceholder(_), _) => {
note_and_explain_region(
self.tcx,
&mut err,
"",
sup,
" doesn't meet the lifetime requirements",
);
}
(_, ty::RePlaceholder(_)) => {
note_and_explain_region(
self.tcx,
&mut err,
"the required lifetime does not necessarily outlive ",
sub,
"",
);
}
_ => {
note_and_explain_region(self.tcx, &mut err, "", sup, "...");
note_and_explain_region(
self.tcx,
&mut err,
"...does not necessarily outlive ",
sub,
"",
);
}
}
err
}
infer::Reborrow(span) => {
@ -286,13 +310,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
sup: Region<'tcx>,
) -> DiagnosticBuilder<'tcx> {
// I can't think how to do better than this right now. -nikomatsakis
debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
match placeholder_origin {
infer::Subtype(box ref trace)
if matches!(
&trace.cause.code.peel_derives(),
ObligationCauseCode::BindingObligation(..)
) =>
{
// Hack to get around the borrow checker because trace.cause has an `Rc`.
if let ObligationCauseCode::BindingObligation(_, span) =
&trace.cause.code.peel_derives()
{
let span = *span;
let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
err.span_note(span, "the lifetime requirement is introduced here");
err
} else {
unreachable!()
}
}
infer::Subtype(box trace) => {
let terr = TypeError::RegionsPlaceholderMismatch;
self.report_and_explain_type_error(trace, &terr)
return self.report_and_explain_type_error(trace, &terr);
}
_ => self.report_concrete_failure(placeholder_origin, sub, sup),
_ => return self.report_concrete_failure(placeholder_origin, sub, sup),
}
}
}

View File

@ -2,10 +2,15 @@ error[E0308]: mismatched types
--> $DIR/higher-ranked-projection.rs:25:5
|
LL | foo(());
| ^^^ one type is more general than the other
| ^^^ lifetime mismatch
|
= note: expected type `&'a ()`
found type `&()`
note: the lifetime requirement is introduced here
--> $DIR/higher-ranked-projection.rs:15:33
|
LL | where for<'a> &'a T: Mirror<Image=U>
| ^^^^^^^
error: aborting due to previous error

View File

@ -2,19 +2,47 @@ error[E0308]: mismatched types
--> $DIR/resume-arg-late-bound.rs:15:5
|
LL | test(gen);
| ^^^^ one type is more general than the other
| ^^^^ lifetime mismatch
|
= note: expected type `for<'a> Generator<&'a mut bool>`
found type `Generator<&mut bool>`
note: the required lifetime does not necessarily outlive the anonymous lifetime #1 defined on the body at 11:15
--> $DIR/resume-arg-late-bound.rs:11:15
|
LL | let gen = |arg: &mut bool| {
| _______________^
LL | | yield ();
LL | | *arg = true;
LL | | };
| |_____^
note: the lifetime requirement is introduced here
--> $DIR/resume-arg-late-bound.rs:8:17
|
LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/resume-arg-late-bound.rs:15:5
|
LL | test(gen);
| ^^^^ one type is more general than the other
| ^^^^ lifetime mismatch
|
= note: expected type `for<'a> Generator<&'a mut bool>`
found type `Generator<&mut bool>`
note: the anonymous lifetime #1 defined on the body at 11:15 doesn't meet the lifetime requirements
--> $DIR/resume-arg-late-bound.rs:11:15
|
LL | let gen = |arg: &mut bool| {
| _______________^
LL | | yield ();
LL | | *arg = true;
LL | | };
| |_____^
note: the lifetime requirement is introduced here
--> $DIR/resume-arg-late-bound.rs:8:17
|
LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -2,19 +2,39 @@ error[E0308]: mismatched types
--> $DIR/hrtb-perfect-forwarding.rs:46:5
|
LL | foo_hrtb_bar_not(&mut t);
| ^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `Bar<&'a isize>`
found type `Bar<&'b isize>`
note: the required lifetime does not necessarily outlive the lifetime `'b` as defined on the function body at 39:21
--> $DIR/hrtb-perfect-forwarding.rs:39:21
|
LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
| ^^
note: the lifetime requirement is introduced here
--> $DIR/hrtb-perfect-forwarding.rs:40:15
|
LL | where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
| ^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/hrtb-perfect-forwarding.rs:46:5
|
LL | foo_hrtb_bar_not(&mut t);
| ^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `Bar<&'a isize>`
found type `Bar<&'b isize>`
note: the lifetime `'b` as defined on the function body at 39:21 doesn't meet the lifetime requirements
--> $DIR/hrtb-perfect-forwarding.rs:39:21
|
LL | fn foo_hrtb_bar_not<'b,T>(mut t: T)
| ^^
note: the lifetime requirement is introduced here
--> $DIR/hrtb-perfect-forwarding.rs:40:15
|
LL | where T : for<'a> Foo<&'a isize> + Bar<&'b isize>
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -3,8 +3,6 @@ error[E0477]: the type `&'a i32` does not fulfill the required lifetime
|
LL | foo::<&'a i32>();
| ^^^^^^^^^^^^^^
|
= note: type must outlive any other region
error: aborting due to previous error

View File

@ -6,6 +6,11 @@ LL | Foo(Box::new(|_| ()));
|
= note: expected type `FnOnce<(&'a bool,)>`
found type `FnOnce<(&bool,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57843.rs:23:18
|
LL | Foo(Box::new(|_| ()));
| ^^^^^^
error: aborting due to previous error

View File

@ -0,0 +1,44 @@
error: lifetime may not live long enough
--> $DIR/issue-79187-2.rs:9:24
|
LL | take_foo(|a: &i32| a);
| - - ^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure is &'2 i32
| let's call the lifetime of this reference `'1`
error: lifetime may not live long enough
--> $DIR/issue-79187-2.rs:10:34
|
LL | take_foo(|a: &i32| -> &i32 { a });
| - - ^ returning this value requires that `'1` must outlive `'2`
| | |
| | let's call the lifetime of this reference `'2`
| let's call the lifetime of this reference `'1`
error: higher-ranked subtype error
--> $DIR/issue-79187-2.rs:8:5
|
LL | take_foo(|a| a);
| ^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/issue-79187-2.rs:8:5
|
LL | take_foo(|a| a);
| ^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/issue-79187-2.rs:9:5
|
LL | take_foo(|a: &i32| a);
| ^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/issue-79187-2.rs:10:5
|
LL | take_foo(|a: &i32| -> &i32 { a });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View File

@ -0,0 +1,23 @@
trait Foo {}
impl<F> Foo for F where F: Fn(&i32) -> &i32 {}
fn take_foo(_: impl Foo) {}
fn main() {
take_foo(|a| a); //~ ERROR mismatched types
take_foo(|a: &i32| a); //~ ERROR mismatched types
take_foo(|a: &i32| -> &i32 { a }); //~ ERROR mismatched types
// OK
take_foo(identity(|a| a));
take_foo(identity(|a: &i32| a));
take_foo(identity(|a: &i32| -> &i32 { a }));
fn identity<F>(t: F) -> F
where
F: Fn(&i32) -> &i32,
{
t
}
}

View File

@ -0,0 +1,60 @@
error[E0308]: mismatched types
--> $DIR/issue-79187-2.rs:8:5
|
LL | take_foo(|a| a);
| ^^^^^^^^ lifetime mismatch
|
= note: expected type `for<'r> Fn<(&'r i32,)>`
found type `Fn<(&i32,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-79187-2.rs:8:14
|
LL | take_foo(|a| a);
| ^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-79187-2.rs:5:21
|
LL | fn take_foo(_: impl Foo) {}
| ^^^
error[E0308]: mismatched types
--> $DIR/issue-79187-2.rs:9:5
|
LL | take_foo(|a: &i32| a);
| ^^^^^^^^ lifetime mismatch
|
= note: expected reference `&i32`
found reference `&i32`
note: the anonymous lifetime #1 defined on the body at 9:14 doesn't meet the lifetime requirements
--> $DIR/issue-79187-2.rs:9:14
|
LL | take_foo(|a: &i32| a);
| ^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-79187-2.rs:5:21
|
LL | fn take_foo(_: impl Foo) {}
| ^^^
error[E0308]: mismatched types
--> $DIR/issue-79187-2.rs:10:5
|
LL | take_foo(|a: &i32| -> &i32 { a });
| ^^^^^^^^ lifetime mismatch
|
= note: expected reference `&i32`
found reference `&i32`
note: the anonymous lifetime #1 defined on the body at 10:14 doesn't meet the lifetime requirements
--> $DIR/issue-79187-2.rs:10:14
|
LL | take_foo(|a: &i32| -> &i32 { a });
| ^^^^^^^^^^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-79187-2.rs:5:21
|
LL | fn take_foo(_: impl Foo) {}
| ^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/issue-79187.rs:5:5
|
LL | thing(f);
| ^^^^^^^^
error: higher-ranked subtype error
--> $DIR/issue-79187.rs:5:5
|
LL | thing(f);
| ^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -0,0 +1,6 @@
fn thing(x: impl FnOnce(&u32)) {}
fn main() {
let f = |_| ();
thing(f); //~ERROR mismatched types
}

View File

@ -0,0 +1,22 @@
error[E0308]: mismatched types
--> $DIR/issue-79187.rs:5:5
|
LL | thing(f);
| ^^^^^ lifetime mismatch
|
= note: expected type `FnOnce<(&u32,)>`
found type `FnOnce<(&u32,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-79187.rs:4:13
|
LL | let f = |_| ();
| ^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-79187.rs:1:18
|
LL | fn thing(x: impl FnOnce(&u32)) {}
| ^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -26,37 +26,77 @@ error[E0308]: mismatched types
--> $DIR/closure-arg-type-mismatch.rs:10:5
|
LL | baz(f);
| ^^^ one type is more general than the other
| ^^^ lifetime mismatch
|
= note: expected type `for<'r> Fn<(*mut &'r u32,)>`
found type `Fn<(*mut &'a u32,)>`
note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10
--> $DIR/closure-arg-type-mismatch.rs:9:10
|
LL | fn _test<'a>(f: fn(*mut &'a u32)) {
| ^^
note: the lifetime requirement is introduced here
--> $DIR/closure-arg-type-mismatch.rs:8:11
|
LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
| ^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/closure-arg-type-mismatch.rs:10:5
|
LL | baz(f);
| ^^^ one type is more general than the other
| ^^^ lifetime mismatch
|
= note: expected type `FnOnce<(*mut &u32,)>`
found type `FnOnce<(*mut &'a u32,)>`
note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10
--> $DIR/closure-arg-type-mismatch.rs:9:10
|
LL | fn _test<'a>(f: fn(*mut &'a u32)) {
| ^^
note: the lifetime requirement is introduced here
--> $DIR/closure-arg-type-mismatch.rs:8:11
|
LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
| ^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/closure-arg-type-mismatch.rs:10:5
|
LL | baz(f);
| ^^^ one type is more general than the other
| ^^^ lifetime mismatch
|
= note: expected type `for<'r> Fn<(*mut &'r u32,)>`
found type `Fn<(*mut &'a u32,)>`
note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements
--> $DIR/closure-arg-type-mismatch.rs:9:10
|
LL | fn _test<'a>(f: fn(*mut &'a u32)) {
| ^^
note: the lifetime requirement is introduced here
--> $DIR/closure-arg-type-mismatch.rs:8:11
|
LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
| ^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/closure-arg-type-mismatch.rs:10:5
|
LL | baz(f);
| ^^^ one type is more general than the other
| ^^^ lifetime mismatch
|
= note: expected type `FnOnce<(*mut &u32,)>`
found type `FnOnce<(*mut &'a u32,)>`
note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements
--> $DIR/closure-arg-type-mismatch.rs:9:10
|
LL | fn _test<'a>(f: fn(*mut &'a u32)) {
| ^^
note: the lifetime requirement is introduced here
--> $DIR/closure-arg-type-mismatch.rs:8:11
|
LL | fn baz<F: Fn(*mut &u32)>(_: F) {}
| ^^^^^^^^^^^^^
error: aborting due to 7 previous errors

View File

@ -2,10 +2,20 @@ error[E0308]: mismatched types
--> $DIR/closure-mismatch.rs:8:5
|
LL | baz(|_| ());
| ^^^ one type is more general than the other
| ^^^ lifetime mismatch
|
= note: expected type `for<'r> Fn<(&'r (),)>`
found type `Fn<(&(),)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/closure-mismatch.rs:8:9
|
LL | baz(|_| ());
| ^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/closure-mismatch.rs:5:11
|
LL | fn baz<T: Foo>(_: T) {}
| ^^^
error: aborting due to previous error

View File

@ -18,6 +18,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `for<'r> Fn<(&'r X,)>`
found type `Fn<(&'static X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error[E0308]: mismatched types
--> $DIR/issue-57611-trait-alias.rs:17:16
@ -27,6 +32,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&'static X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error: aborting due to 4 previous errors

View File

@ -6,6 +6,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error[E0308]: mismatched types
--> $DIR/issue-57611-trait-alias.rs:17:16
@ -15,6 +20,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `for<'r> Fn<(&'r X,)>`
found type `Fn<(&'<empty> X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error[E0308]: mismatched types
--> $DIR/issue-57611-trait-alias.rs:17:16
@ -24,6 +34,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&'<empty> X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error[E0308]: mismatched types
--> $DIR/issue-57611-trait-alias.rs:17:16
@ -33,6 +48,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `for<'r> Fn<(&'r X,)>`
found type `Fn<(&'<empty> X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error[E0308]: mismatched types
--> $DIR/issue-57611-trait-alias.rs:17:16
@ -42,6 +62,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&'<empty> X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:25:9
|
LL | |x| x
| ^^^^^
error: aborting due to 5 previous errors

View File

@ -2,10 +2,15 @@ error[E0308]: mismatched types
--> $DIR/issue-30906.rs:15:5
|
LL | test(Compose(f, |_| {}));
| ^^^^ one type is more general than the other
| ^^^^ lifetime mismatch
|
= note: expected type `FnOnce<(&'x str,)>`
found type `FnOnce<(&str,)>`
note: the lifetime requirement is introduced here
--> $DIR/issue-30906.rs:3:12
|
LL | fn test<F: for<'x> FnOnce<(&'x str,)>>(_: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error