From 1eb79f3c375f4d7834a30b40c20a9c8ec1c31b4c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 9 Feb 2021 20:56:45 +0000 Subject: [PATCH 1/7] Use longer lifetime in `try_report_from_nll` return type --- .../src/infer/error_reporting/nice_region_error/mod.rs | 2 +- .../error_reporting/nice_region_error/named_anon_conflict.rs | 2 +- .../error_reporting/nice_region_error/placeholder_error.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index cc8f1816bc3f4..0599c78ebfd07 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -43,7 +43,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { self.infcx.tcx } - pub fn try_report_from_nll(&self) -> Option> { + pub fn try_report_from_nll(&self) -> Option> { // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // the nice region errors are required when running under the MIR borrow checker. self.try_report_named_anon_conflict().or_else(|| self.try_report_placeholder_conflict()) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index e3c613b1d6a12..2f622231a081e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -9,7 +9,7 @@ use rustc_middle::ty; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// When given a `ConcreteFailure` for a function with parameters containing a named region and /// an anonymous region, emit an descriptive diagnostic error. - pub(super) fn try_report_named_anon_conflict(&self) -> Option> { + pub(super) fn try_report_named_anon_conflict(&self) -> Option> { let (span, sub, sup) = self.regions()?; debug!( diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index e8e0326d97865..fc211a15afc05 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -16,7 +16,7 @@ use std::fmt::{self, Write}; impl NiceRegionError<'me, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit a descriptive diagnostic error. - pub(super) fn try_report_placeholder_conflict(&self) -> Option> { + pub(super) fn try_report_placeholder_conflict(&self) -> Option> { match &self.error { /////////////////////////////////////////////////////////////////////////// // NB. The ordering of cases in this match is very @@ -199,7 +199,7 @@ impl NiceRegionError<'me, 'tcx> { trait_def_id: DefId, expected_substs: SubstsRef<'tcx>, actual_substs: SubstsRef<'tcx>, - ) -> DiagnosticBuilder<'me> { + ) -> DiagnosticBuilder<'tcx> { debug!( "try_report_placeholders_trait(\ vid={:?}, \ From 638980a07f72e20fcbcdab12b74b2a1a8663741d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 9 Feb 2021 21:03:00 +0000 Subject: [PATCH 2/7] Using tracing macros in placeholder_error.rs --- .../nice_region_error/placeholder_error.rs | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index fc211a15afc05..8c933df8ca00d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -190,6 +190,7 @@ impl NiceRegionError<'me, 'tcx> { // = note: Due to a where-clause on the function `all`, // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`. // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. + #[instrument(level = "debug", skip(self))] fn try_report_placeholders_trait( &self, vid: Option>, @@ -200,17 +201,6 @@ impl NiceRegionError<'me, 'tcx> { expected_substs: SubstsRef<'tcx>, actual_substs: SubstsRef<'tcx>, ) -> DiagnosticBuilder<'tcx> { - debug!( - "try_report_placeholders_trait(\ - vid={:?}, \ - sub_placeholder={:?}, \ - sup_placeholder={:?}, \ - trait_def_id={:?}, \ - expected_substs={:?}, \ - actual_substs={:?})", - vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs - ); - let span = cause.span(self.tcx()); let msg = format!( "implementation of `{}` is not general enough", @@ -285,17 +275,13 @@ impl NiceRegionError<'me, 'tcx> { let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid; - debug!("try_report_placeholders_trait: actual_has_vid={:?}", actual_has_vid); - debug!("try_report_placeholders_trait: expected_has_vid={:?}", expected_has_vid); - debug!("try_report_placeholders_trait: has_sub={:?}", has_sub); - debug!("try_report_placeholders_trait: has_sup={:?}", has_sup); - debug!( - "try_report_placeholders_trait: actual_self_ty_has_vid={:?}", - actual_self_ty_has_vid - ); debug!( - "try_report_placeholders_trait: expected_self_ty_has_vid={:?}", - expected_self_ty_has_vid + ?actual_has_vid, + ?expected_has_vid, + ?has_sub, + ?has_sup, + ?actual_self_ty_has_vid, + ?expected_self_ty_has_vid, ); self.explain_actual_impl_that_was_found( From c2066cf0694c304c0fc43f17bebefb518b066619 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 9 Feb 2021 21:16:00 +0000 Subject: [PATCH 3/7] Remove unnecessary note on errors Seeing the trait definition doesn't help with implementation not general enough errors, so don't make the error message larger to show it. --- .../nice_region_error/placeholder_error.rs | 4 -- .../associated-types-eq-hr.stderr | 55 ++++--------------- .../ui/generator/auto-trait-regions.stderr | 12 ---- src/test/ui/hrtb/due-to-where-clause.stderr | 3 - .../ui/hrtb/hrtb-cache-issue-54302.stderr | 3 - src/test/ui/hrtb/hrtb-conflate-regions.stderr | 9 +-- ...b-exists-forall-trait-contravariant.stderr | 3 - .../hrtb-exists-forall-trait-invariant.stderr | 3 - src/test/ui/hrtb/hrtb-just-for-static.stderr | 18 ++---- src/test/ui/hrtb/issue-46989.stderr | 3 - src/test/ui/issues/issue-54302-cases.stderr | 36 +++--------- src/test/ui/issues/issue-54302.stderr | 3 - src/test/ui/issues/issue-55731.stderr | 9 +-- .../ui/where-clauses/where-for-self-2.stderr | 9 +-- 14 files changed, 28 insertions(+), 142 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 8c933df8ca00d..d99e79005fbb8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -207,10 +207,6 @@ impl NiceRegionError<'me, 'tcx> { self.tcx().def_path_str(trait_def_id), ); let mut err = self.tcx().sess.struct_span_err(span, &msg); - err.span_label( - self.tcx().def_span(trait_def_id), - format!("trait `{}` defined here", self.tcx().def_path_str(trait_def_id)), - ); let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code { err.span_label(span, "doesn't satisfy where-clause"); diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 127ab8673556d..6188d9ca979cf 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -31,15 +31,8 @@ LL | bar::(); error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | / pub trait TheTrait { -LL | | type A; -LL | | -LL | | fn get(&self, t: T) -> Self::A; -LL | | } - | |_- trait `TheTrait` defined here -... -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` @@ -47,15 +40,8 @@ LL | tuple_one::(); error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | / pub trait TheTrait { -LL | | type A; -LL | | -LL | | fn get(&self, t: T) -> Self::A; -LL | | } - | |_- trait `TheTrait` defined here -... -LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` @@ -63,15 +49,8 @@ LL | tuple_one::(); error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:102:5 | -LL | / pub trait TheTrait { -LL | | type A; -LL | | -LL | | fn get(&self, t: T) -> Self::A; -LL | | } - | |_- trait `TheTrait` defined here -... -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` @@ -79,15 +58,8 @@ LL | tuple_two::(); error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:102:5 | -LL | / pub trait TheTrait { -LL | | type A; -LL | | -LL | | fn get(&self, t: T) -> Self::A; -LL | | } - | |_- trait `TheTrait` defined here -... -LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` @@ -95,15 +67,8 @@ LL | tuple_two::(); error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:112:5 | -LL | / pub trait TheTrait { -LL | | type A; -LL | | -LL | | fn get(&self, t: T) -> Self::A; -LL | | } - | |_- trait `TheTrait` defined here -... -LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 5ec462e10465f..5fe4193905c72 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,9 +1,6 @@ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | -LL | auto trait Foo {} - | ----------------- trait `Foo` defined here -... LL | assert_foo(gen); | ^^^^^^^^^^ implementation of `Foo` is not general enough | @@ -13,9 +10,6 @@ LL | assert_foo(gen); error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | -LL | auto trait Foo {} - | ----------------- trait `Foo` defined here -... LL | assert_foo(gen); | ^^^^^^^^^^ implementation of `Foo` is not general enough | @@ -25,9 +19,6 @@ LL | assert_foo(gen); error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:50:5 | -LL | auto trait Foo {} - | ----------------- trait `Foo` defined here -... LL | assert_foo(gen); | ^^^^^^^^^^ implementation of `Foo` is not general enough | @@ -37,9 +28,6 @@ LL | assert_foo(gen); error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:50:5 | -LL | auto trait Foo {} - | ----------------- trait `Foo` defined here -... LL | assert_foo(gen); | ^^^^^^^^^^ implementation of `Foo` is not general enough | diff --git a/src/test/ui/hrtb/due-to-where-clause.stderr b/src/test/ui/hrtb/due-to-where-clause.stderr index e4096ec059a6e..520938a633514 100644 --- a/src/test/ui/hrtb/due-to-where-clause.stderr +++ b/src/test/ui/hrtb/due-to-where-clause.stderr @@ -3,9 +3,6 @@ error: implementation of `Foo` is not general enough | LL | test::(&mut 42); | ^^^^^^^^^^^^ implementation of `Foo` is not general enough -... -LL | trait Foo<'a> {} - | ---------------- trait `Foo` defined here | = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`... = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1` diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index 003f32659351f..f014eab8601fa 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -1,9 +1,6 @@ error: implementation of `Deserialize` is not general enough --> $DIR/hrtb-cache-issue-54302.rs:19:5 | -LL | trait Deserialize<'de> {} - | ------------------------- trait `Deserialize` defined here -... LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough | diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 45573814d13c0..7a0ede5af201c 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,13 +1,8 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | / trait Foo { -LL | | fn foo(&self, x: X) { } -LL | | } - | |_- trait `Foo` defined here -... -LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index fe8209d054c8a..2f946c7d9bfe8 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -1,9 +1,6 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | -LL | trait Trait {} - | ----------------- trait `Trait` defined here -... LL | foo::<()>(); | ^^^^^^^^^ implementation of `Trait` is not general enough | diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 8bd23aa9018df..ba244e0f2ebc7 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -1,9 +1,6 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | trait Trait {} - | ----------------- trait `Trait` defined here -... LL | foo::<()>(); | ^^^^^^^^^ implementation of `Trait` is not general enough | diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 5e3014317f5bc..0d46a130e093e 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,13 +1,8 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | / trait Foo { -LL | | fn foo(&self, x: X) { } -LL | | } - | |_- trait `Foo` defined here -... -LL | want_hrtb::() - | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` @@ -15,13 +10,8 @@ LL | want_hrtb::() error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 | -LL | / trait Foo { -LL | | fn foo(&self, x: X) { } -LL | | } - | |_- trait `Foo` defined here -... -LL | want_hrtb::<&'a u32>() - | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0`... = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index c85c37ff9239e..f3d906cae4cc3 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -1,9 +1,6 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-46989.rs:38:5 | -LL | trait Foo {} - | ------------ trait `Foo` defined here -... LL | assert_foo::(); | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 3ed2779164301..baa75f28d37f3 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -1,13 +1,8 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | -LL | / trait Foo<'x, T> { -LL | | fn foo(self) -> &'x T; -LL | | } - | |_- trait `Foo` defined here -... -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` @@ -15,13 +10,8 @@ LL | >::ref_foo(a) error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | -LL | / trait Foo<'x, T> { -LL | | fn foo(self) -> &'x T; -LL | | } - | |_- trait `Foo` defined here -... -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` @@ -29,13 +19,8 @@ LL | >::ref_foo(a) error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | -LL | / trait Foo<'x, T> { -LL | | fn foo(self) -> &'x T; -LL | | } - | |_- trait `Foo` defined here -... -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` @@ -43,13 +28,8 @@ LL | >::ref_foo(a) error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | -LL | / trait Foo<'x, T> { -LL | | fn foo(self) -> &'x T; -LL | | } - | |_- trait `Foo` defined here -... -LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index 1b3f57ba188a3..26c46571f9cb2 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -1,9 +1,6 @@ error: implementation of `Deserialize` is not general enough --> $DIR/issue-54302.rs:13:5 | -LL | trait Deserialize<'de> {} - | ------------------------- trait `Deserialize` defined here -... LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough | diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr index f44c842187cc2..de327cd3cc23c 100644 --- a/src/test/ui/issues/issue-55731.stderr +++ b/src/test/ui/issues/issue-55731.stderr @@ -1,13 +1,8 @@ error: implementation of `DistributedIteratorMulti` is not general enough --> $DIR/issue-55731.rs:48:5 | -LL | / trait DistributedIteratorMulti { -LL | | type Item; -LL | | } - | |_- trait `DistributedIteratorMulti` defined here -... -LL | multi(Map { - | ^^^^^ implementation of `DistributedIteratorMulti` is not general enough +LL | multi(Map { + | ^^^^^ implementation of `DistributedIteratorMulti` is not general enough | = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 30eb78b2da4f7..4f8b19291db40 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,13 +1,8 @@ error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:23:5 | -LL | / trait Bar { -LL | | fn bar(&self); -LL | | } - | |_- trait `Bar` defined here -... -LL | foo(&X); - | ^^^ implementation of `Bar` is not general enough +LL | foo(&X); + | ^^^ implementation of `Bar` is not general enough | = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` From daab6db1a02b680a71976fcbeed577ff102b31e4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 9 Feb 2021 22:28:09 +0000 Subject: [PATCH 4/7] Avoid repeating self type in placeholder error --- .../nice_region_error/placeholder_error.rs | 20 +++++++++++++++++-- .../associated-types-eq-hr.stderr | 10 +++++----- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 2 +- ...b-exists-forall-trait-contravariant.stderr | 2 +- .../hrtb-exists-forall-trait-invariant.stderr | 2 +- src/test/ui/hrtb/hrtb-just-for-static.stderr | 2 +- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d99e79005fbb8..09be0b076705c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -370,6 +370,8 @@ impl NiceRegionError<'me, 'tcx> { value: trait_ref, }; + let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty(); + let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref); expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub); expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup); @@ -385,7 +387,16 @@ impl NiceRegionError<'me, 'tcx> { } }; - let mut note = if passive_voice { + let mut note = if same_self_type { + let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); + self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); + format!( + "{}`{}` must implement `{}`", + if leading_ellipsis { "..." } else { "" }, + self_ty, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), + ) + } else if passive_voice { format!( "{}`{}` would have to be implemented for the type `{}`", if leading_ellipsis { "..." } else { "" }, @@ -431,7 +442,12 @@ impl NiceRegionError<'me, 'tcx> { None => true, }; - let mut note = if passive_voice { + let mut note = if same_self_type { + format!( + "...but it actually implements `{}`", + actual_trait_ref.map(|tr| tr.print_only_trait_path()), + ) + } else if passive_voice { format!( "...but `{}` is actually implemented for the type `{}`", actual_trait_ref.map(|tr| tr.print_only_trait_path()), diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 6188d9ca979cf..6897b31fe4685 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -35,7 +35,7 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -44,7 +44,7 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:102:5 @@ -53,7 +53,7 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:102:5 @@ -62,7 +62,7 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:112:5 @@ -71,7 +71,7 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough | = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to 7 previous errors diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 7a0ede5af201c..b1d4c0bf37505 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -5,7 +5,7 @@ LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 2f946c7d9bfe8..613f4dc4951ec 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -5,7 +5,7 @@ LL | foo::<()>(); | ^^^^^^^^^ implementation of `Trait` is not general enough | = note: `()` must implement `Trait fn(&'b u32)>` - = note: ...but `()` actually implements `Trait`, for some specific lifetime `'0` + = note: ...but it actually implements `Trait`, for some specific lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index ba244e0f2ebc7..b487ce3e0ffa1 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -5,7 +5,7 @@ LL | foo::<()>(); | ^^^^^^^^^ implementation of `Trait` is not general enough | = note: `()` must implement `Trait fn(Cell<&'b u32>)>` - = note: ...but `()` actually implements `Trait)>`, for some specific lifetime `'0` + = note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 0d46a130e093e..38d7c12d4ec03 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -5,7 +5,7 @@ LL | want_hrtb::() | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... - = note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` + = note: ...but it actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 From 94c11dfe78c9c2e81ababe51b04231db4c90d07f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 9 Feb 2021 22:59:32 +0000 Subject: [PATCH 5/7] Report "nice" placeholder errors more often If we have a cause containing `ValuePairs::PolyTraitRefs` but neither TraitRef has any escaping bound regions then we report the same error as for `ValuePairs::TraitRefs`. --- .../nice_region_error/placeholder_error.rs | 142 +++++++++--------- .../hrtb/hrtb-perfect-forwarding.nll.stderr | 38 ++--- src/test/ui/hrtb/hrtb-perfect-forwarding.rs | 39 +++-- .../ui/hrtb/hrtb-perfect-forwarding.stderr | 41 ++--- src/test/ui/issues/issue-57843.nll.stderr | 2 +- src/test/ui/issues/issue-57843.rs | 6 +- src/test/ui/issues/issue-57843.stderr | 16 +- src/test/ui/lifetimes/issue-79187.rs | 2 +- src/test/ui/lifetimes/issue-79187.stderr | 19 +-- .../closure-arg-type-mismatch.rs | 4 +- .../closure-arg-type-mismatch.stderr | 36 +---- src/test/ui/rfc1623.rs | 2 +- src/test/ui/rfc1623.stderr | 9 +- .../issue-57611-trait-alias.nll.stderr | 13 +- .../issue-57611-trait-alias.rs | 6 +- .../issue-57611-trait-alias.stderr | 39 ++--- .../unboxed-closures/issue-30906.nll.stderr | 2 +- src/test/ui/unboxed-closures/issue-30906.rs | 12 +- .../ui/unboxed-closures/issue-30906.stderr | 16 +- 19 files changed, 181 insertions(+), 263 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 09be0b076705c..285666b7acb99 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -30,157 +30,153 @@ impl NiceRegionError<'me, 'tcx> { Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sub_placeholder @ ty::RePlaceholder(_), _, sup_placeholder @ ty::RePlaceholder(_), - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, Some(sub_placeholder), Some(sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sub_placeholder @ ty::RePlaceholder(_), _, _, - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, Some(sub_placeholder), None, - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::SubSupConflict( vid, _, - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), _, _, sup_placeholder @ ty::RePlaceholder(_), - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, None, Some(*sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::SubSupConflict( vid, _, _, _, - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sup_placeholder @ ty::RePlaceholder(_), - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, None, Some(*sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::UpperBoundUniverseConflict( vid, _, _, - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sup_placeholder @ ty::RePlaceholder(_), - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, None, Some(*sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sub_region @ ty::RePlaceholder(_), sup_region @ ty::RePlaceholder(_), - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( None, cause, Some(*sub_region), Some(*sup_region), - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sub_region @ ty::RePlaceholder(_), sup_region, - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(sup_region), cause, Some(*sub_region), None, - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::Subtype(box TypeTrace { - cause, - values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), - }), + SubregionOrigin::Subtype(box TypeTrace { cause, values }), sub_region, sup_region @ ty::RePlaceholder(_), - )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + )) => self.try_report_trait_placeholder_mismatch( Some(sub_region), cause, None, Some(*sup_region), - expected.def_id, - expected.substs, - found.substs, - )), + values, + ), _ => None, } } + fn try_report_trait_placeholder_mismatch( + &self, + vid: Option>, + cause: &ObligationCause<'tcx>, + sub_placeholder: Option>, + sup_placeholder: Option>, + value_pairs: &ValuePairs<'tcx>, + ) -> Option> { + let (expected_substs, found_substs, trait_def_id) = match value_pairs { + ValuePairs::TraitRefs(ExpectedFound { expected, found }) + if expected.def_id == found.def_id => + { + (expected.substs, found.substs, expected.def_id) + } + ValuePairs::PolyTraitRefs(ExpectedFound { expected, found }) + if expected.def_id() == found.def_id() => + { + // It's possible that the placeholders come from a binder + // outside of this value pair. Use `no_bound_vars` as a + // simple heuristic for that. + (expected.no_bound_vars()?.substs, found.no_bound_vars()?.substs, expected.def_id()) + } + _ => return None, + }; + + Some(self.report_trait_placeholder_mismatch( + vid, + cause, + sub_placeholder, + sup_placeholder, + trait_def_id, + expected_substs, + found_substs, + )) + } + // error[E0308]: implementation of `Foo` does not apply to enough lifetimes // --> /home/nmatsakis/tmp/foo.rs:12:5 // | @@ -191,7 +187,7 @@ impl NiceRegionError<'me, 'tcx> { // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`. // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. #[instrument(level = "debug", skip(self))] - fn try_report_placeholders_trait( + fn report_trait_placeholder_mismatch( &self, vid: Option>, cause: &ObligationCause<'tcx>, diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr index edce0e6702ee1..c3dd794957540 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr @@ -1,11 +1,11 @@ warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:22:1 + --> $DIR/hrtb-perfect-forwarding.rs:16:1 | -LL | / fn no_hrtb<'b,T>(mut t: T) -LL | | where T : Bar<&'b isize> +LL | / fn no_hrtb<'b, T>(mut t: T) +LL | | where +LL | | T: Bar<&'b isize>, LL | | { -LL | | // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that -LL | | // `&mut T : Bar<&'b isize>`. +... | LL | | no_hrtb(&mut t); | | --------------- recursive call site LL | | } @@ -15,12 +15,12 @@ LL | | } = help: a `loop` may express intention better if this is on purpose warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:30:1 + --> $DIR/hrtb-perfect-forwarding.rs:25:1 | LL | / fn bar_hrtb(mut t: T) -LL | | where T : for<'b> Bar<&'b isize> +LL | | where +LL | | T: for<'b> Bar<&'b isize>, LL | | { -LL | | // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above ... | LL | | bar_hrtb(&mut t); | | ---------------- recursive call site @@ -30,25 +30,26 @@ LL | | } = help: a `loop` may express intention better if this is on purpose warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:39:1 + --> $DIR/hrtb-perfect-forwarding.rs:35:1 | -LL | / fn foo_hrtb_bar_not<'b,T>(mut t: T) -LL | | where T : for<'a> Foo<&'a isize> + Bar<&'b isize> +LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T) +LL | | where +LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, LL | | { -LL | | // Not OK -- The forwarding impl for `Foo` requires that `Bar` also ... | LL | | foo_hrtb_bar_not(&mut t); | | ------------------------ recursive call site LL | | +LL | | LL | | } | |_^ cannot return without recursing | = help: a `loop` may express intention better if this is on purpose error: lifetime may not live long enough - --> $DIR/hrtb-perfect-forwarding.rs:46:5 + --> $DIR/hrtb-perfect-forwarding.rs:43:5 | -LL | fn foo_hrtb_bar_not<'b,T>(mut t: T) +LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) | -- lifetime `'b` defined here ... LL | foo_hrtb_bar_not(&mut t); @@ -57,18 +58,19 @@ LL | foo_hrtb_bar_not(&mut t); = help: consider replacing `'b` with `'static` error: higher-ranked subtype error - --> $DIR/hrtb-perfect-forwarding.rs:46:5 + --> $DIR/hrtb-perfect-forwarding.rs:43:5 | LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:50:1 + --> $DIR/hrtb-perfect-forwarding.rs:48:1 | LL | / fn foo_hrtb_bar_hrtb(mut t: T) -LL | | where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize> +LL | | where +LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, LL | | { -LL | | // OK -- now we have `T : for<'b> Bar&'b isize>`. +LL | | // OK -- now we have `T : for<'b> Bar<&'b isize>`. LL | | foo_hrtb_bar_hrtb(&mut t); | | ------------------------- recursive call site LL | | } diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs index 0303a764c12de..441a788359e03 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs @@ -2,25 +2,20 @@ // is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730. trait Foo { - fn foo(&mut self, x: X) { } + fn foo(&mut self, x: X) {} } trait Bar { - fn bar(&mut self, x: X) { } + fn bar(&mut self, x: X) {} } -impl<'a,X,F> Foo for &'a mut F - where F : Foo + Bar -{ -} +impl<'a, X, F> Foo for &'a mut F where F: Foo + Bar {} -impl<'a,X,F> Bar for &'a mut F - where F : Bar -{ -} +impl<'a, X, F> Bar for &'a mut F where F: Bar {} -fn no_hrtb<'b,T>(mut t: T) - where T : Bar<&'b isize> +fn no_hrtb<'b, T>(mut t: T) +where + T: Bar<&'b isize>, { // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that // `&mut T : Bar<&'b isize>`. @@ -28,7 +23,8 @@ fn no_hrtb<'b,T>(mut t: T) } fn bar_hrtb(mut t: T) - where T : for<'b> Bar<&'b isize> +where + T: for<'b> Bar<&'b isize>, { // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above // ensures that `&mut T : for<'b> Bar<&'b isize>`. This is an @@ -36,22 +32,25 @@ fn bar_hrtb(mut t: T) bar_hrtb(&mut t); } -fn foo_hrtb_bar_not<'b,T>(mut t: T) - where T : for<'a> Foo<&'a isize> + Bar<&'b isize> +fn foo_hrtb_bar_not<'b, T>(mut t: T) +where + T: for<'a> Foo<&'a isize> + Bar<&'b isize>, { // Not OK -- The forwarding impl for `Foo` requires that `Bar` also // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where // clause only specifies `T : Bar<&'b isize>`. - foo_hrtb_bar_not(&mut t); //~ ERROR mismatched types - //~| ERROR mismatched types + foo_hrtb_bar_not(&mut t); + //~^ ERROR implementation of `Bar` is not general enough + //~| ERROR implementation of `Bar` is not general enough } fn foo_hrtb_bar_hrtb(mut t: T) - where T : for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize> +where + T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, { - // OK -- now we have `T : for<'b> Bar&'b isize>`. + // OK -- now we have `T : for<'b> Bar<&'b isize>`. foo_hrtb_bar_hrtb(&mut t); } -fn main() { } +fn main() {} diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index ed810d443bef7..e265f53cd2a7f 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -1,41 +1,20 @@ -error[E0308]: mismatched types - --> $DIR/hrtb-perfect-forwarding.rs:46:5 +error: implementation of `Bar` is not general enough + --> $DIR/hrtb-perfect-forwarding.rs:43:5 | LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^ lifetime mismatch + | ^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | - = 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> - | ^^^^^^^^^^^^^^^^^^^^^^ + = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` -error[E0308]: mismatched types - --> $DIR/hrtb-perfect-forwarding.rs:46:5 +error: implementation of `Bar` is not general enough + --> $DIR/hrtb-perfect-forwarding.rs:43:5 | LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^ 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 + | ^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | -LL | where T : for<'a> Foo<&'a isize> + Bar<&'b isize> - | ^^^^^^^^^^^^^^^^^^^^^^ + = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-57843.nll.stderr b/src/test/ui/issues/issue-57843.nll.stderr index 70310780b4330..70d16cc9a1da6 100644 --- a/src/test/ui/issues/issue-57843.nll.stderr +++ b/src/test/ui/issues/issue-57843.nll.stderr @@ -1,5 +1,5 @@ error: higher-ranked subtype error - --> $DIR/issue-57843.rs:23:9 + --> $DIR/issue-57843.rs:25:9 | LL | Foo(Box::new(|_| ())); | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-57843.rs b/src/test/ui/issues/issue-57843.rs index 466082552667b..11629690ecc5e 100644 --- a/src/test/ui/issues/issue-57843.rs +++ b/src/test/ui/issues/issue-57843.rs @@ -11,7 +11,9 @@ trait ClonableFn { } impl ClonableFn for F -where F: Fn(T) + Clone { +where + F: Fn(T) + Clone, +{ fn clone(&self) -> Box { Box::new(self.clone()) } @@ -20,5 +22,5 @@ where F: Fn(T) + Clone { struct Foo(Box ClonableFn<&'a bool>>); fn main() { - Foo(Box::new(|_| ())); //~ ERROR mismatched types + Foo(Box::new(|_| ())); //~ ERROR implementation of `FnOnce` is not general enough } diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr index 7699e97da99ad..acd48b6c7e5ba 100644 --- a/src/test/ui/issues/issue-57843.stderr +++ b/src/test/ui/issues/issue-57843.stderr @@ -1,17 +1,11 @@ -error[E0308]: mismatched types - --> $DIR/issue-57843.rs:23:9 +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-57843.rs:25:9 | LL | Foo(Box::new(|_| ())); - | ^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = 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(|_| ())); - | ^^^^^^ + = note: `[closure@$DIR/issue-57843.rs:25:18: 25:24]` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/issue-79187.rs b/src/test/ui/lifetimes/issue-79187.rs index bf331d8a6068e..2ee69ee2234ee 100644 --- a/src/test/ui/lifetimes/issue-79187.rs +++ b/src/test/ui/lifetimes/issue-79187.rs @@ -2,5 +2,5 @@ fn thing(x: impl FnOnce(&u32)) {} fn main() { let f = |_| (); - thing(f); //~ERROR mismatched types + thing(f); //~ERROR implementation of `FnOnce` is not general enough } diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr index 63f501e08fce4..3627ab5ed1e97 100644 --- a/src/test/ui/lifetimes/issue-79187.stderr +++ b/src/test/ui/lifetimes/issue-79187.stderr @@ -1,22 +1,11 @@ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | LL | thing(f); - | ^^^^^ lifetime mismatch + | ^^^^^ implementation of `FnOnce` is not general enough | - = 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)) {} - | ^^^^^^^^^^^^ + = note: `[closure@$DIR/issue-79187.rs:4:13: 4:19]` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index e278049c8cc42..2d485d14a8d6b 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -8,8 +8,8 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { baz(f); - //~^ ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR mismatched types //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 02ba60f7f4b73..67c5a68ed83c6 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -41,24 +41,14 @@ note: the lifetime requirement is introduced here LL | fn baz(_: F) {} | ^^^^^^^^^^^^^ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); - | ^^^ 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 + | ^^^ implementation of `FnOnce` is not general enough | -LL | fn baz(_: F) {} - | ^^^^^^^^^^^^^ + = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 @@ -79,24 +69,14 @@ note: the lifetime requirement is introduced here LL | fn baz(_: F) {} | ^^^^^^^^^^^^^ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); - | ^^^ 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 + | ^^^ implementation of `FnOnce` is not general enough | -LL | fn baz(_: F) {} - | ^^^^^^^^^^^^^ + = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 7 previous errors diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index aa6b1c0012c93..9ff4813d11286 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -22,7 +22,7 @@ static SOME_STRUCT: &SomeStruct = &SomeStruct { foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR mismatched types + //~^ ERROR implementation of `FnOnce` is not general enough }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index 2835e47fa4515..e95e68c8e6d26 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,12 +1,11 @@ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623.rs:24:8 | LL | f: &id, - | ^^^ one type is more general than the other + | ^^^ implementation of `FnOnce` is not general enough | - = note: expected type `FnOnce<(&'a Foo<'b>,)>` - found type `FnOnce<(&Foo<'_>,)>` + = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index be1dd1a8524c8..59b14eedc24ba 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -24,19 +24,14 @@ note: this closure does not fulfill the lifetime requirements LL | |x| x | ^^^^^ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = 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 - | ^^^^^ + = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 3372b81404ecb..561528c2abbd5 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -15,9 +15,9 @@ struct X; impl Foo for X { type Bar = impl Baz; - //~^ ERROR mismatched types - //~| ERROR mismatched types - //~| ERROR mismatched types + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough //~| ERROR mismatched types //~| ERROR mismatched types diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index 9d9293e958eeb..59c91d52cca98 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -1,16 +1,11 @@ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other - | - = 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 + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | -LL | |x| x - | ^^^^^ + = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -26,19 +21,14 @@ note: this closure does not fulfill the lifetime requirements LL | |x| x | ^^^^^ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = 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 - | ^^^^^ + = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -54,19 +44,14 @@ note: this closure does not fulfill the lifetime requirements LL | |x| x | ^^^^^ -error[E0308]: mismatched types +error: implementation of `FnOnce` is not general enough --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz; - | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = 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 - | ^^^^^ + = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/src/test/ui/unboxed-closures/issue-30906.nll.stderr b/src/test/ui/unboxed-closures/issue-30906.nll.stderr index 5a2cbab9a1500..2db392e8b8b9f 100644 --- a/src/test/ui/unboxed-closures/issue-30906.nll.stderr +++ b/src/test/ui/unboxed-closures/issue-30906.nll.stderr @@ -1,5 +1,5 @@ error: higher-ranked subtype error - --> $DIR/issue-30906.rs:15:5 + --> $DIR/issue-30906.rs:18:5 | LL | test(Compose(f, |_| {})); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/unboxed-closures/issue-30906.rs b/src/test/ui/unboxed-closures/issue-30906.rs index 03cce83277515..e2d219e470384 100644 --- a/src/test/ui/unboxed-closures/issue-30906.rs +++ b/src/test/ui/unboxed-closures/issue-30906.rs @@ -2,9 +2,12 @@ fn test FnOnce<(&'x str,)>>(_: F) {} -struct Compose(F,G); -impl FnOnce<(T,)> for Compose -where F: FnOnce<(T,)>, G: FnOnce<(F::Output,)> { +struct Compose(F, G); +impl FnOnce<(T,)> for Compose +where + F: FnOnce<(T,)>, + G: FnOnce<(F::Output,)>, +{ type Output = G::Output; extern "rust-call" fn call_once(self, (x,): (T,)) -> G::Output { (self.1)((self.0)(x)) @@ -12,7 +15,8 @@ where F: FnOnce<(T,)>, G: FnOnce<(F::Output,)> { } fn bad(f: fn(&'static str) -> T) { - test(Compose(f, |_| {})); //~ ERROR: mismatched types + test(Compose(f, |_| {})); + //~^ ERROR: implementation of `FnOnce` is not general enough } fn main() {} diff --git a/src/test/ui/unboxed-closures/issue-30906.stderr b/src/test/ui/unboxed-closures/issue-30906.stderr index ecf3a96b5a8dc..35b1e454c02b4 100644 --- a/src/test/ui/unboxed-closures/issue-30906.stderr +++ b/src/test/ui/unboxed-closures/issue-30906.stderr @@ -1,17 +1,11 @@ -error[E0308]: mismatched types - --> $DIR/issue-30906.rs:15:5 +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-30906.rs:18:5 | LL | test(Compose(f, |_| {})); - | ^^^^ lifetime mismatch + | ^^^^ implementation of `FnOnce` is not general enough | - = 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 FnOnce<(&'x str,)>>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. From 9337d4fde89ded13243d67bec0b03f7fc553cbf9 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 9 Feb 2021 23:00:33 +0000 Subject: [PATCH 6/7] Print closure signatures when reporting placeholder errors --- .../nice_region_error/placeholder_error.rs | 38 ++++++++++++++++--- src/test/ui/issues/issue-57843.stderr | 2 +- src/test/ui/lifetimes/issue-79187.stderr | 2 +- .../issue-57611-trait-alias.nll.stderr | 2 +- .../issue-57611-trait-alias.stderr | 6 +-- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 285666b7acb99..46986d8d58b64 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -386,12 +386,38 @@ impl NiceRegionError<'me, 'tcx> { let mut note = if same_self_type { let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); - format!( - "{}`{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - self_ty, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - ) + + if self_ty.value.is_closure() + && self + .tcx() + .fn_trait_kind_from_lang_item(expected_trait_ref.value.def_id) + .is_some() + { + let closure_sig = self_ty.map(|closure| { + if let ty::Closure(_, substs) = closure.kind() { + self.tcx().signature_unclosure( + substs.as_closure().sig(), + rustc_hir::Unsafety::Normal, + ) + } else { + bug!("type is not longer closure"); + } + }); + + format!( + "{}closure with signature `{}` must implement `{}`", + if leading_ellipsis { "..." } else { "" }, + closure_sig, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), + ) + } else { + format!( + "{}`{}` must implement `{}`", + if leading_ellipsis { "..." } else { "" }, + self_ty, + expected_trait_ref.map(|tr| tr.print_only_trait_path()), + ) + } } else if passive_voice { format!( "{}`{}` would have to be implemented for the type `{}`", diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr index acd48b6c7e5ba..2ab49ec61cf59 100644 --- a/src/test/ui/issues/issue-57843.stderr +++ b/src/test/ui/issues/issue-57843.stderr @@ -4,7 +4,7 @@ error: implementation of `FnOnce` is not general enough LL | Foo(Box::new(|_| ())); | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `[closure@$DIR/issue-57843.rs:25:18: 25:24]` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... + = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr index 3627ab5ed1e97..3c0439fb660e5 100644 --- a/src/test/ui/lifetimes/issue-79187.stderr +++ b/src/test/ui/lifetimes/issue-79187.stderr @@ -4,7 +4,7 @@ error: implementation of `FnOnce` is not general enough LL | thing(f); | ^^^^^ implementation of `FnOnce` is not general enough | - = note: `[closure@$DIR/issue-79187.rs:4:13: 4:19]` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index 59b14eedc24ba..a5409582288f2 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -30,7 +30,7 @@ error: implementation of `FnOnce` is not general enough LL | type Bar = impl Baz; | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index 59c91d52cca98..91c9d459ad8ce 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -4,7 +4,7 @@ error: implementation of `FnOnce` is not general enough LL | type Bar = impl Baz; | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: closure with signature `fn(&'2 X) -> &X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error[E0308]: mismatched types @@ -27,7 +27,7 @@ error: implementation of `FnOnce` is not general enough LL | type Bar = impl Baz; | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error[E0308]: mismatched types @@ -50,7 +50,7 @@ error: implementation of `FnOnce` is not general enough LL | type Bar = impl Baz; | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: `[closure@$DIR/issue-57611-trait-alias.rs:25:9: 25:14]` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... + = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors From f852160a99721f89a6bc206bae337291c485069e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 10 Feb 2021 20:00:36 +0000 Subject: [PATCH 7/7] Keep existing names of regions in placeholder_error --- .../nice_region_error/placeholder_error.rs | 8 ++++---- src/test/ui/generator/auto-trait-regions.stderr | 8 ++++---- src/test/ui/hrtb/hrtb-just-for-static.stderr | 2 +- src/test/ui/hrtb/hrtb-perfect-forwarding.stderr | 4 ++-- .../ui/mismatched_types/closure-arg-type-mismatch.stderr | 8 ++++---- .../issue-57611-trait-alias.nll.stderr | 4 ++-- src/test/ui/where-clauses/where-for-self-2.stderr | 4 ++-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 46986d8d58b64..4aecc2f40b874 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -118,9 +118,9 @@ impl NiceRegionError<'me, 'tcx> { sub_region @ ty::RePlaceholder(_), sup_region, )) => self.try_report_trait_placeholder_mismatch( - Some(sup_region), + (!sup_region.has_name()).then_some(sup_region), cause, - Some(*sub_region), + Some(sub_region), None, values, ), @@ -130,10 +130,10 @@ impl NiceRegionError<'me, 'tcx> { sub_region, sup_region @ ty::RePlaceholder(_), )) => self.try_report_trait_placeholder_mismatch( - Some(sub_region), + (!sub_region.has_name()).then_some(sub_region), cause, None, - Some(*sup_region), + Some(sup_region), values, ), diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 5fe4193905c72..da3d3249f0e7e 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -4,8 +4,8 @@ error: implementation of `Foo` is not general enough LL | assert_foo(gen); | ^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`... - = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` + = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 @@ -13,8 +13,8 @@ error: implementation of `Foo` is not general enough LL | assert_foo(gen); | ^^^^^^^^^^ implementation of `Foo` is not general enough | - = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`... - = note: ...but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` + = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:50:5 diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 38d7c12d4ec03..ffc83aab4af4d 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -5,7 +5,7 @@ LL | want_hrtb::() | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` + = note: ...but it actually implements `Foo<&'static isize>` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index e265f53cd2a7f..07ff9b96e44ff 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -5,7 +5,7 @@ LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` + = note: ...but it actually implements `Bar<&'b isize>` error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 @@ -14,7 +14,7 @@ LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` + = note: ...but it actually implements `Bar<&'b isize>` error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 67c5a68ed83c6..521de3742b03f 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -47,8 +47,8 @@ error: implementation of `FnOnce` is not general enough LL | baz(f); | ^^^ implementation of `FnOnce` is not general enough | - = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` + = note: `fn(*mut &'a u32)` must implement `FnOnce<(*mut &'0 u32,)>`, for any lifetime `'0`... + = note: ...but it actually implements `FnOnce<(*mut &'a u32,)>` error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 @@ -75,8 +75,8 @@ error: implementation of `FnOnce` is not general enough LL | baz(f); | ^^^ implementation of `FnOnce` is not general enough | - = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` + = note: `fn(*mut &'a u32)` must implement `FnOnce<(*mut &'0 u32,)>`, for any lifetime `'0`... + = note: ...but it actually implements `FnOnce<(*mut &'a u32,)>` error: aborting due to 7 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index a5409582288f2..998e178966a22 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -30,8 +30,8 @@ error: implementation of `FnOnce` is not general enough LL | type Bar = impl Baz; | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough | - = note: closure with signature `fn(&'2 X) -> &'2 X` must implement `FnOnce<(&'1 X,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 X,)>`, for some specific lifetime `'2` + = note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`... + = note: ...but it actually implements `FnOnce<(&'static X,)>` error: aborting due to 4 previous errors diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 4f8b19291db40..6da46e20c09c0 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -4,8 +4,8 @@ error: implementation of `Bar` is not general enough LL | foo(&X); | ^^^ implementation of `Bar` is not general enough | - = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... - = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` + = note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to previous error