From 6bb7581a5926365ec65d64d15386c3723beff330 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 16 Jul 2022 23:41:43 +0000 Subject: Slightly improve mismatched GAT where clause error --- .../generic-associated-types-where.stderr | 4 +-- .../ui/generic-associated-types/impl_bounds.rs | 4 +-- .../ui/generic-associated-types/impl_bounds.stderr | 30 ++++++++++++---------- .../issue-47206-where-clause.stderr | 4 +-- .../missing-where-clause-on-trait.rs | 2 +- .../missing-where-clause-on-trait.stderr | 9 ++++--- 6 files changed, 28 insertions(+), 25 deletions(-) (limited to 'src/test') diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr index c7ebb9880f7..e866b3bab79 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr @@ -11,13 +11,13 @@ LL | type Assoc2 = Vec; | +++++++++++++++++++ error[E0276]: impl has stricter requirements than trait - --> $DIR/generic-associated-types-where.rs:22:5 + --> $DIR/generic-associated-types-where.rs:22:38 | LL | type Assoc3; | -------------- definition of `Assoc3` from trait ... LL | type Assoc3 = Vec where T: Iterator; - | ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` + | ^^^^^^^^ impl has extra requirement `T: Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index bb5992c88f0..01403a352d4 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -13,9 +13,9 @@ struct Fooy(T); impl Foo for Fooy { type A<'a> = (&'a ()) where Self: 'static; - //~^ ERROR `impl` associated type + //~^ ERROR the parameter type `T` may not live long enoug type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - //~^ ERROR `impl` associated type + //~^ ERROR impl has stricter requirements than trait //~| ERROR lifetime bound not satisfied type C = String where Self: Copy; //~^ ERROR the trait bound `T: Copy` is not satisfied diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 6aa52b179a3..6d63f187d86 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -1,20 +1,22 @@ -error: `impl` associated type signature for `A` doesn't match `trait` associated type signature - --> $DIR/impl_bounds.rs:15:5 +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/impl_bounds.rs:15:39 | -LL | type A<'a> where Self: 'a; - | ---------- expected -... LL | type A<'a> = (&'a ()) where Self: 'static; - | ^^^^^^^^^^ found + | ^^^^^^^ ...so that the definition in impl matches the definition from the trait + | +help: consider adding an explicit lifetime bound... + | +LL | impl Foo for Fooy { + | +++++++++ -error: `impl` associated type signature for `B` doesn't match `trait` associated type signature - --> $DIR/impl_bounds.rs:17:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/impl_bounds.rs:17:48 | LL | type B<'a, 'b> where 'a: 'b; - | -------------- expected + | -------------- definition of `B` from trait ... LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^^^^^^^^^^^^^ found + | ^^ impl has extra requirement `'b: 'a` error[E0478]: lifetime bound not satisfied --> $DIR/impl_bounds.rs:17:22 @@ -37,10 +39,10 @@ LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; | ^^ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:20:5 + --> $DIR/impl_bounds.rs:20:33 | LL | type C = String where Self: Copy; - | ^^^^^^ the trait `Copy` is not implemented for `T` + | ^^^^ the trait `Copy` is not implemented for `T` | note: required because of the requirements on the impl of `Copy` for `Fooy` --> $DIR/impl_bounds.rs:11:10 @@ -88,5 +90,5 @@ LL | impl Foo for Fooy { error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0478. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0276, E0277, E0310, E0478. +For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr index c560e2405d5..31948a878ed 100644 --- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr +++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -1,11 +1,11 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/issue-47206-where-clause.rs:12:5 + --> $DIR/issue-47206-where-clause.rs:12:38 | LL | type Assoc3; | -------------- definition of `Assoc3` from trait ... LL | type Assoc3 = Vec where T: Iterator; - | ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` + | ^^^^^^^^ impl has extra requirement `T: Iterator` error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs index 5fb8f7a4773..8171dc0ae28 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -7,7 +7,7 @@ trait Foo { } impl Foo for () { type Assoc<'a, 'b> = () where 'a: 'b; - //~^ `impl` associated type + //~^ impl has stricter requirements than trait } fn main() {} diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr index 0256d2f20fc..edd1f9367d1 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -1,11 +1,12 @@ -error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature - --> $DIR/missing-where-clause-on-trait.rs:9:5 +error[E0276]: impl has stricter requirements than trait + --> $DIR/missing-where-clause-on-trait.rs:9:39 | LL | type Assoc<'a, 'b>; - | ------------------ expected + | ------------------ definition of `Assoc` from trait ... LL | type Assoc<'a, 'b> = () where 'a: 'b; - | ^^^^^^^^^^^^^^^^^^ found + | ^^ impl has extra requirement `'a: 'b` error: aborting due to previous error +For more information about this error, try `rustc --explain E0276`. -- cgit 1.4.1-3-g733a5 From 2bbcdc73339c2b7c3e57c2fc0d3bc574945c0023 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Jul 2022 18:57:41 +0000 Subject: Handle additional lifetime bounds on GATs like on methods --- .../rustc_infer/src/infer/error_reporting/mod.rs | 24 ++++++++++++++-------- .../ui/generic-associated-types/impl_bounds.rs | 2 +- .../ui/generic-associated-types/impl_bounds.stderr | 14 ++++++------- 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src/test') diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 4e87ec86658..a990c359e0a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2351,18 +2351,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { GenericKind::Projection(ref p) => format!("the associated type `{}`", p), }; - if let Some(SubregionOrigin::CompareImplMethodObligation { - span, - impl_item_def_id, - trait_item_def_id, - }) = origin - { - return self.report_extra_impl_obligation( + match origin { + Some(SubregionOrigin::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id, - &format!("`{}: {}`", bound_kind, sub), - ); + } | SubregionOrigin::CompareImplTypeObligation { + span, + impl_item_def_id, + trait_item_def_id, + }) => { + return self.report_extra_impl_obligation( + span, + impl_item_def_id, + trait_item_def_id, + &format!("`{}: {}`", bound_kind, sub), + ); + } + _ => {} } fn binding_suggestion<'tcx, S: fmt::Display>( diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 01403a352d4..ec1d171c044 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -13,7 +13,7 @@ struct Fooy(T); impl Foo for Fooy { type A<'a> = (&'a ()) where Self: 'static; - //~^ ERROR the parameter type `T` may not live long enoug + //~^ ERROR impl has stricter requirements than trait type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; //~^ ERROR impl has stricter requirements than trait //~| ERROR lifetime bound not satisfied diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 6d63f187d86..c3311e21959 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -1,13 +1,11 @@ -error[E0310]: the parameter type `T` may not live long enough +error[E0276]: impl has stricter requirements than trait --> $DIR/impl_bounds.rs:15:39 | +LL | type A<'a> where Self: 'a; + | ---------- definition of `A` from trait +... LL | type A<'a> = (&'a ()) where Self: 'static; - | ^^^^^^^ ...so that the definition in impl matches the definition from the trait - | -help: consider adding an explicit lifetime bound... - | -LL | impl Foo for Fooy { - | +++++++++ + | ^^^^^^^ impl has extra requirement `T: 'static` error[E0276]: impl has stricter requirements than trait --> $DIR/impl_bounds.rs:17:48 @@ -90,5 +88,5 @@ LL | impl Foo for Fooy { error: aborting due to 5 previous errors -Some errors have detailed explanations: E0276, E0277, E0310, E0478. +Some errors have detailed explanations: E0276, E0277, E0478. For more information about an error, try `rustc --explain E0276`. -- cgit 1.4.1-3-g733a5 From 3bbe95ca0cb50260aa23a507642af05a83652a4e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Jul 2022 19:33:26 +0000 Subject: Combine redundant obligation cause codes --- .../rustc_infer/src/infer/error_reporting/mod.rs | 48 +++++++++++++--------- .../nice_region_error/trait_impl_difference.rs | 5 +-- .../rustc_infer/src/infer/error_reporting/note.rs | 18 +------- compiler/rustc_infer/src/infer/mod.rs | 27 +++--------- compiler/rustc_middle/src/traits/mod.rs | 12 +----- compiler/rustc_middle/src/ty/assoc.rs | 10 +++++ compiler/rustc_middle/src/ty/error.rs | 8 +--- compiler/rustc_middle/src/ty/structural_impls.rs | 1 + .../src/traits/error_reporting/mod.rs | 7 +--- .../src/traits/error_reporting/suggestions.rs | 40 ++---------------- compiler/rustc_typeck/src/astconv/mod.rs | 9 +--- compiler/rustc_typeck/src/check/compare_method.rs | 15 +++++-- .../associated-const-impl-wrong-lifetime.rs | 2 +- .../associated-const-impl-wrong-lifetime.stderr | 2 +- .../ui/generic-associated-types/impl_bounds.stderr | 10 ++--- src/test/ui/nll/trait-associated-constant.rs | 2 +- src/test/ui/nll/trait-associated-constant.stderr | 2 +- 17 files changed, 80 insertions(+), 138 deletions(-) (limited to 'src/test') diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index a990c359e0a..e06af1fac06 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1883,7 +1883,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { exp_span, exp_found.expected, exp_found.found, ); - if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() { + if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() { return; } @@ -2351,24 +2351,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { GenericKind::Projection(ref p) => format!("the associated type `{}`", p), }; - match origin { - Some(SubregionOrigin::CompareImplMethodObligation { - span, - impl_item_def_id, - trait_item_def_id, - } | SubregionOrigin::CompareImplTypeObligation { + if let Some(SubregionOrigin::CompareImplItemObligation { + span, + impl_item_def_id, + trait_item_def_id, + }) = origin + { + return self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, - }) => { - return self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", bound_kind, sub), - ); - } - _ => {} + &format!("`{}: {}`", bound_kind, sub), + ); } fn binding_suggestion<'tcx, S: fmt::Display>( @@ -2794,8 +2788,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; match self.code() { - CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), - CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"), + CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => { + Error0308("method not compatible with trait") + } + CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => { + Error0308("type not compatible with trait") + } + CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => { + Error0308("const not compatible with trait") + } MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => { Error0308(match source { hir::MatchSource::TryDesugar => "`?` operator has incompatible types", @@ -2829,8 +2830,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { fn as_requirement_str(&self) -> &'static str { use crate::traits::ObligationCauseCode::*; match self.code() { - CompareImplMethodObligation { .. } => "method type is compatible with trait", - CompareImplTypeObligation { .. } => "associated type is compatible with trait", + CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => { + "method type is compatible with trait" + } + CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => { + "associated type is compatible with trait" + } + CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => { + "const is compatible with trait" + } ExprAssignable => "expression is assignable", IfExpression { .. } => "`if` and `else` have incompatible types", IfExpressionWithNoElse => "`if` missing an `else` returns `()`", diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 6123e6cc66e..da465a76429 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -3,7 +3,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::Subtype; -use crate::traits::ObligationCauseCode::{CompareImplMethodObligation, CompareImplTypeObligation}; +use crate::traits::ObligationCauseCode::CompareImplItemObligation; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -33,8 +33,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin) && let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty() && let sup_expected_found @ Some(_) = sup_trace.values.ty() - && let CompareImplMethodObligation { trait_item_def_id, .. } - | CompareImplTypeObligation { trait_item_def_id, .. } = sub_trace.cause.code() + && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code() && sup_expected_found == sub_expected_found { let guar = diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index b6d41bedd56..c1940c5c082 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -86,13 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "...so that the declared lifetime parameter bounds are satisfied", ); } - infer::CompareImplMethodObligation { span, .. } => { - label_or_note( - span, - "...so that the definition in impl matches the definition from the trait", - ); - } - infer::CompareImplTypeObligation { span, .. } => { + infer::CompareImplItemObligation { span, .. } => { label_or_note( span, "...so that the definition in impl matches the definition from the trait", @@ -329,15 +323,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); err } - infer::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id } => { - self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - ) - } - infer::CompareImplTypeObligation { span, impl_item_def_id, trait_item_def_id } => self + infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self .report_extra_impl_obligation( span, impl_item_def_id, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 85692e109be..5e7c0661728 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -405,15 +405,7 @@ pub enum SubregionOrigin<'tcx> { /// Comparing the signature and requirements of an impl method against /// the containing trait. - CompareImplMethodObligation { - span: Span, - impl_item_def_id: LocalDefId, - trait_item_def_id: DefId, - }, - - /// Comparing the signature and requirements of an impl associated type - /// against the containing trait - CompareImplTypeObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId }, + CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId }, /// Checking that the bounds of a trait's associated type hold for a given impl CheckAssociatedTypeBounds { @@ -1945,8 +1937,7 @@ impl<'tcx> SubregionOrigin<'tcx> { ReborrowUpvar(a, _) => a, DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, - CompareImplMethodObligation { span, .. } => span, - CompareImplTypeObligation { span, .. } => span, + CompareImplItemObligation { span, .. } => span, CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), } } @@ -1960,19 +1951,11 @@ impl<'tcx> SubregionOrigin<'tcx> { SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) } - traits::ObligationCauseCode::CompareImplMethodObligation { - impl_item_def_id, - trait_item_def_id, - } => SubregionOrigin::CompareImplMethodObligation { - span: cause.span, - impl_item_def_id, - trait_item_def_id, - }, - - traits::ObligationCauseCode::CompareImplTypeObligation { + traits::ObligationCauseCode::CompareImplItemObligation { impl_item_def_id, trait_item_def_id, - } => SubregionOrigin::CompareImplTypeObligation { + kind: _, + } => SubregionOrigin::CompareImplItemObligation { span: cause.span, impl_item_def_id, trait_item_def_id, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c55971557fa..72b848c3ee2 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -311,18 +311,10 @@ pub enum ObligationCauseCode<'tcx> { }, /// Error derived when matching traits/impls; see ObligationCause for more details - CompareImplConstObligation, - - /// Error derived when matching traits/impls; see ObligationCause for more details - CompareImplMethodObligation { - impl_item_def_id: LocalDefId, - trait_item_def_id: DefId, - }, - - /// Error derived when matching traits/impls; see ObligationCause for more details - CompareImplTypeObligation { + CompareImplItemObligation { impl_item_def_id: LocalDefId, trait_item_def_id: DefId, + kind: ty::AssocKind, }, /// Checking that the bounds of a trait's associated type hold for a given impl diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 2c93af50667..eb732148e3e 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -105,6 +105,16 @@ impl AssocKind { } } +impl std::fmt::Display for AssocKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AssocKind::Fn => write!(f, "method"), + AssocKind::Const => write!(f, "associated const"), + AssocKind::Type => write!(f, "associated type"), + } + } +} + /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name. /// /// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 49a518b101d..91246051316 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -660,12 +660,8 @@ impl Trait for X { | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }), ) ); - let impl_comparison = matches!( - cause_code, - ObligationCauseCode::CompareImplMethodObligation { .. } - | ObligationCauseCode::CompareImplTypeObligation { .. } - | ObligationCauseCode::CompareImplConstObligation - ); + let impl_comparison = + matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. }); let assoc = self.associated_item(proj_ty.item_def_id); if !callable_scope || impl_comparison { // We do not want to suggest calling functions when the reason of the diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a4be3d02d19..7467d9cf995 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -224,6 +224,7 @@ TrivialTypeTraversalAndLiftImpls! { // general `Region`. crate::ty::BoundRegionKind, crate::ty::AssocItem, + crate::ty::AssocKind, crate::ty::Placeholder, crate::ty::ClosureKind, crate::ty::FreeRegion, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 2f92a77a795..41c5087c43d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -301,13 +301,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span = obligation.cause.span; } } - if let ObligationCauseCode::CompareImplMethodObligation { - impl_item_def_id, - trait_item_def_id, - } - | ObligationCauseCode::CompareImplTypeObligation { + if let ObligationCauseCode::CompareImplItemObligation { impl_item_def_id, trait_item_def_id, + kind: _, } = *obligation.cause.code() { self.report_extra_impl_obligation( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7ab85e7fa66..89d7c050c40 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2682,11 +2682,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) }); } - ObligationCauseCode::CompareImplMethodObligation { trait_item_def_id, .. } => { + ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => { let item_name = self.tcx.item_name(trait_item_def_id); let msg = format!( - "the requirement `{}` appears on the impl method `{}` but not on the \ - corresponding trait method", + "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \ + corresponding trait's {kind}", predicate, item_name, ); let sp = self @@ -2697,7 +2697,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut assoc_span: MultiSpan = sp.into(); assoc_span.push_span_label( sp, - format!("this trait method doesn't have the requirement `{}`", predicate), + format!("this trait's {kind} doesn't have the requirement `{}`", predicate), ); if let Some(ident) = self .tcx @@ -2708,38 +2708,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } err.span_note(assoc_span, &msg); } - ObligationCauseCode::CompareImplTypeObligation { trait_item_def_id, .. } => { - let item_name = self.tcx.item_name(trait_item_def_id); - let msg = format!( - "the requirement `{}` appears on the associated impl type `{}` but not on the \ - corresponding associated trait type", - predicate, item_name, - ); - let sp = self.tcx.def_span(trait_item_def_id); - let mut assoc_span: MultiSpan = sp.into(); - assoc_span.push_span_label( - sp, - format!( - "this trait associated type doesn't have the requirement `{}`", - predicate, - ), - ); - if let Some(ident) = self - .tcx - .opt_associated_item(trait_item_def_id) - .and_then(|i| self.tcx.opt_item_ident(i.container.id())) - { - assoc_span.push_span_label(ident.span, "in this trait"); - } - err.span_note(assoc_span, &msg); - } - ObligationCauseCode::CompareImplConstObligation => { - err.note(&format!( - "the requirement `{}` appears on the associated impl constant \ - but not on the corresponding associated trait constant", - predicate - )); - } ObligationCauseCode::TrivialBound => { err.help("see issue #48214"); if tcx.sess.opts.unstable_features.is_nightly_build() { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7111812f0b0..04f2eb459cf 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1150,17 +1150,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .expect("missing associated type"); if !assoc_item.vis.is_accessible_from(def_scope, tcx) { - let kind = match assoc_item.kind { - ty::AssocKind::Type => "type", - ty::AssocKind::Const => "const", - _ => unreachable!(), - }; tcx.sess .struct_span_err( binding.span, - &format!("associated {kind} `{}` is private", binding.item_name), + &format!("{} `{}` is private", assoc_item.kind, binding.item_name), ) - .span_label(binding.span, &format!("private associated {kind}")) + .span_label(binding.span, &format!("private {}", assoc_item.kind)) .emit(); } tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 91364ac35cb..af77efc3c2d 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -90,9 +90,10 @@ fn compare_predicate_entailment<'tcx>( let mut cause = ObligationCause::new( impl_m_span, impl_m_hir_id, - ObligationCauseCode::CompareImplMethodObligation { + ObligationCauseCode::CompareImplItemObligation { impl_item_def_id: impl_m.def_id.expect_local(), trait_item_def_id: trait_m.def_id, + kind: impl_m.kind, }, ); @@ -223,9 +224,10 @@ fn compare_predicate_entailment<'tcx>( let cause = ObligationCause::new( span, impl_m_hir_id, - ObligationCauseCode::CompareImplMethodObligation { + ObligationCauseCode::CompareImplItemObligation { impl_item_def_id: impl_m.def_id.expect_local(), trait_item_def_id: trait_m.def_id, + kind: impl_m.kind, }, ); ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate)); @@ -1079,7 +1081,11 @@ pub(crate) fn compare_const_impl<'tcx>( let mut cause = ObligationCause::new( impl_c_span, impl_c_hir_id, - ObligationCauseCode::CompareImplConstObligation, + ObligationCauseCode::CompareImplItemObligation { + impl_item_def_id: impl_c.def_id.expect_local(), + trait_item_def_id: trait_c.def_id, + kind: impl_c.kind, + }, ); // There is no "body" here, so just pass dummy id. @@ -1249,9 +1255,10 @@ fn compare_type_predicate_entailment<'tcx>( let cause = ObligationCause::new( span, impl_ty_hir_id, - ObligationCauseCode::CompareImplTypeObligation { + ObligationCauseCode::CompareImplItemObligation { impl_item_def_id: impl_ty.def_id.expect_local(), trait_item_def_id: trait_ty.def_id, + kind: impl_ty.kind, }, ); ocx.register_obligations(obligations); diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs index 08260ec8f4d..63bac96135b 100644 --- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs +++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs @@ -5,7 +5,7 @@ trait Foo { impl<'a> Foo for &'a () { const NAME: &'a str = "unit"; - //~^ ERROR mismatched types [E0308] + //~^ ERROR const not compatible with trait } fn main() {} diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr index f71fb2ee18a..de1d9589e99 100644 --- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched types +error[E0308]: const not compatible with trait --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5 | LL | const NAME: &'a str = "unit"; diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index c3311e21959..ce79c635add 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -47,14 +47,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy` | LL | #[derive(Copy, Clone)] | ^^^^ -note: the requirement `Fooy: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type - --> $DIR/impl_bounds.rs:7:5 +note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type + --> $DIR/impl_bounds.rs:7:10 | LL | trait Foo { | --- in this trait ... LL | type C where Self: Clone; - | ^^^^^^ this trait associated type doesn't have the requirement `Fooy: Copy` + | ^ this trait's associated type doesn't have the requirement `Fooy: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -72,14 +72,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy` | LL | #[derive(Copy, Clone)] | ^^^^ -note: the requirement `Fooy: Copy` appears on the impl method `d` but not on the corresponding trait method +note: the requirement `Fooy: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method --> $DIR/impl_bounds.rs:8:8 | LL | trait Foo { | --- in this trait ... LL | fn d() where Self: Clone; - | ^ this trait method doesn't have the requirement `Fooy: Copy` + | ^ this trait's method doesn't have the requirement `Fooy: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | diff --git a/src/test/ui/nll/trait-associated-constant.rs b/src/test/ui/nll/trait-associated-constant.rs index 31dc58185e9..e13ae80f918 100644 --- a/src/test/ui/nll/trait-associated-constant.rs +++ b/src/test/ui/nll/trait-associated-constant.rs @@ -19,7 +19,7 @@ struct FailStruct { } impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { const AC: Option<&'c str> = None; - //~^ ERROR: mismatched types + //~^ ERROR: const not compatible with trait } struct OKStruct2 { } diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index 000ebc71657..ae0ffd904e7 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched types +error[E0308]: const not compatible with trait --> $DIR/trait-associated-constant.rs:21:5 | LL | const AC: Option<&'c str> = None; -- cgit 1.4.1-3-g733a5 From f85f37583d91152b967cd0d1bd7253b339a26d42 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 22 Jul 2022 15:53:00 +0900 Subject: suggest removing the tuple struct field for the unwrapped value add a test case for macro --- compiler/rustc_typeck/src/check/demand.rs | 15 ++++++++ .../suggest-removing-tulpe-struct-field.fixed | 17 +++++++++ .../suggest-removing-tulpe-struct-field.rs | 17 +++++++++ .../suggest-removing-tulpe-struct-field.stderr | 41 ++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed create mode 100644 src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs create mode 100644 src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr (limited to 'src/test') diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index a2d8765289c..381c3a4ea1f 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -287,6 +287,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, ) { if let ty::Adt(expected_adt, substs) = expected.kind() { + if let hir::ExprKind::Field(base, ident) = expr.kind { + let base_ty = self.typeck_results.borrow().expr_ty(base); + if self.can_eq(self.param_env, base_ty, expected).is_ok() + && let Some(base_span) = base.span.find_ancestor_inside(expr.span) + { + err.span_suggestion_verbose( + expr.span.with_lo(base_span.hi()), + format!("consider removing the tuple struct field `{ident}`"), + "", + Applicability::MaybeIncorrect, + ); + return + } + } + // If the expression is of type () and it's the return expression of a block, // we suggest adding a separate return expression instead. // (To avoid things like suggesting `Ok(while .. { .. })`.) diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed b/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed new file mode 100644 index 00000000000..63b65ab20fe --- /dev/null +++ b/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +macro_rules! my_wrapper { + ($expr:expr) => { MyWrapper($expr) } +} + +pub struct MyWrapper(u32); + +fn main() { + let value = MyWrapper(123); + some_fn(value); //~ ERROR mismatched types + some_fn(my_wrapper!(123)); //~ ERROR mismatched types +} + +fn some_fn(wrapped: MyWrapper) { + drop(wrapped); +} diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs b/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs new file mode 100644 index 00000000000..2ab4e3955f3 --- /dev/null +++ b/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs @@ -0,0 +1,17 @@ +// run-rustfix + +macro_rules! my_wrapper { + ($expr:expr) => { MyWrapper($expr) } +} + +pub struct MyWrapper(u32); + +fn main() { + let value = MyWrapper(123); + some_fn(value.0); //~ ERROR mismatched types + some_fn(my_wrapper!(123).0); //~ ERROR mismatched types +} + +fn some_fn(wrapped: MyWrapper) { + drop(wrapped); +} diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr b/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr new file mode 100644 index 00000000000..82a7f276372 --- /dev/null +++ b/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched types + --> $DIR/suggest-removing-tulpe-struct-field.rs:11:13 + | +LL | some_fn(value.0); + | ------- ^^^^^^^ expected struct `MyWrapper`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-removing-tulpe-struct-field.rs:15:4 + | +LL | fn some_fn(wrapped: MyWrapper) { + | ^^^^^^^ ------------------ +help: consider removing the tuple struct field `0` + | +LL - some_fn(value.0); +LL + some_fn(value); + | + +error[E0308]: mismatched types + --> $DIR/suggest-removing-tulpe-struct-field.rs:12:13 + | +LL | some_fn(my_wrapper!(123).0); + | ------- ^^^^^^^^^^^^^^^^^^ expected struct `MyWrapper`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-removing-tulpe-struct-field.rs:15:4 + | +LL | fn some_fn(wrapped: MyWrapper) { + | ^^^^^^^ ------------------ +help: consider removing the tuple struct field `0` + | +LL - some_fn(my_wrapper!(123).0); +LL + some_fn(my_wrapper!(123)); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. -- cgit 1.4.1-3-g733a5 From 5f40a4f7a0aa6552e615fe89a6018e36c93f672e Mon Sep 17 00:00:00 2001 From: Tomasz Miąsko Date: Mon, 25 Jul 2022 00:00:00 +0000 Subject: Remove reachable coverage without counters Remove reachable coverage without counters to maintain invariant that either there is no coverage at all or there is a live coverage counter left that provides the function source hash. The motivating example would be a following closure: ```rust let f = |x: bool| { debug_assert!(x); }; ``` Which, with span changes from #93967, with disabled debug assertions, after the final CFG simplifications but before removal of dead blocks, gives rise to MIR: ```rust fn main::{closure#0}(_1: &[closure@a.rs:2:13: 2:22], _2: bool) -> () { debug x => _2; let mut _0: (); bb0: { Coverage::Expression(4294967295) = 1 - 2; return; } ... } ``` --- compiler/rustc_mir_transform/src/simplify.rs | 12 ++++++- .../expected_show_coverage.inline-dead.txt | 39 +++++++++++++--------- src/test/run-make-fulldeps/coverage/inline-dead.rs | 9 ++++- 3 files changed, 42 insertions(+), 18 deletions(-) (limited to 'src/test') diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index d305960b485..180f4c7dcd6 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -315,7 +315,7 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { /// with `0` executions. /// /// If there are no live `Counter` `Coverage` statements remaining, we remove -/// dead `Coverage` statements along with the dead blocks. Since at least one +/// `Coverage` statements along with the dead blocks. Since at least one /// counter per function is required by LLVM (and necessary, to add the /// `function_hash` to the counter's call to the LLVM intrinsic /// `instrprof.increment()`). @@ -342,6 +342,16 @@ fn save_unreachable_coverage( } } + for block in &mut basic_blocks.raw[..first_dead_block] { + for statement in &mut block.statements { + let StatementKind::Coverage(_) = &statement.kind else { continue }; + let instance = statement.source_info.scope.inlined_instance(source_scopes); + if !live.contains(&instance) { + statement.make_nop(); + } + } + } + if live.is_empty() { return; } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt index d102d9ecf7d..effdef80e8e 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline-dead.txt @@ -1,21 +1,28 @@ 1| |// Regression test for issue #98833. - 2| |// compile-flags: -Zinline-mir + 2| |// compile-flags: -Zinline-mir -Cdebug-assertions=off 3| | 4| 1|fn main() { 5| 1| println!("{}", live::()); - 6| 1|} - 7| | - 8| |#[inline] - 9| 1|fn live() -> u32 { - 10| 1| if B { - 11| 0| dead() - 12| | } else { - 13| 1| 0 - 14| | } - 15| 1|} - 16| | - 17| |#[inline] - 18| 0|fn dead() -> u32 { - 19| 0| 42 - 20| 0|} + 6| 1| + 7| 1| let f = |x: bool| { + 8| | debug_assert!( + 9| | x + 10| | ); + 11| 1| }; + 12| 1| f(false); + 13| 1|} + 14| | + 15| |#[inline] + 16| 1|fn live() -> u32 { + 17| 1| if B { + 18| 0| dead() + 19| | } else { + 20| 1| 0 + 21| | } + 22| 1|} + 23| | + 24| |#[inline] + 25| 0|fn dead() -> u32 { + 26| 0| 42 + 27| 0|} diff --git a/src/test/run-make-fulldeps/coverage/inline-dead.rs b/src/test/run-make-fulldeps/coverage/inline-dead.rs index cd1ae911a5f..854fa062967 100644 --- a/src/test/run-make-fulldeps/coverage/inline-dead.rs +++ b/src/test/run-make-fulldeps/coverage/inline-dead.rs @@ -1,8 +1,15 @@ // Regression test for issue #98833. -// compile-flags: -Zinline-mir +// compile-flags: -Zinline-mir -Cdebug-assertions=off fn main() { println!("{}", live::()); + + let f = |x: bool| { + debug_assert!( + x + ); + }; + f(false); } #[inline] -- cgit 1.4.1-3-g733a5