From 6bb7581a5926365ec65d64d15386c3723beff330 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 16 Jul 2022 23:41:43 +0000 Subject: [PATCH] Slightly improve mismatched GAT where clause error --- .../trait_impl_difference.rs | 70 +++++-------------- .../rustc_typeck/src/check/compare_method.rs | 29 ++++---- .../generic-associated-types-where.stderr | 4 +- .../generic-associated-types/impl_bounds.rs | 4 +- .../impl_bounds.stderr | 30 ++++---- .../issue-47206-where-clause.stderr | 4 +- .../missing-where-clause-on-trait.rs | 2 +- .../missing-where-clause-on-trait.stderr | 9 +-- 8 files changed, 62 insertions(+), 90 deletions(-) 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 91bf9695dfc..6123e6cc66e 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 @@ -2,17 +2,17 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use crate::infer::{SubregionOrigin, Subtype}; -use crate::traits::ObligationCauseCode::CompareImplMethodObligation; +use crate::infer::Subtype; +use crate::traits::ObligationCauseCode::{CompareImplMethodObligation, CompareImplTypeObligation}; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; use std::ops::ControlFlow; @@ -22,38 +22,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let error = self.error.as_ref()?; debug!("try_report_impl_not_conforming_to_trait {:?}", error); if let RegionResolutionError::SubSupConflict( - _, var_origin, sub_origin, _sub, sup_origin, _sup, _, + _, + var_origin, + sub_origin, + _sub, + sup_origin, + _sup, + _, ) = error.clone() - && let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) - && let ( - sub_expected_found @ Some((sub_expected, sub_found)), - sup_expected_found @ Some(_), - CompareImplMethodObligation { trait_item_def_id, .. }, - ) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code()) + && 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() && sup_expected_found == sub_expected_found { - let guar = self.emit_err( - var_origin.span(), - sub_expected, - sub_found, - *trait_item_def_id, - ); - return Some(guar); - } - if let RegionResolutionError::ConcreteFailure(origin, _, _) - | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone() - && let SubregionOrigin::CompareImplTypeObligation { - span, - impl_item_def_id, - trait_item_def_id, - } = origin - { - let guar = self.emit_associated_type_err( - span, - self.infcx.tcx.item_name(impl_item_def_id.to_def_id()), - impl_item_def_id, - trait_item_def_id, - ); + let guar = + self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id); return Some(guar); } None @@ -147,25 +132,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } err.emit() } - - fn emit_associated_type_err( - &self, - span: Span, - item_name: Symbol, - impl_item_def_id: LocalDefId, - trait_item_def_id: DefId, - ) -> ErrorGuaranteed { - let impl_sp = self.tcx().def_span(impl_item_def_id); - let trait_sp = self.tcx().def_span(trait_item_def_id); - let mut err = self - .tcx() - .sess - .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name)); - err.span_label(impl_sp, "found"); - err.span_label(trait_sp, "expected"); - - err.emit() - } } struct TypeParamSpanVisitor<'tcx> { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 1a9354f5d20..91364ac35cb 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1212,15 +1212,6 @@ fn compare_type_predicate_entailment<'tcx>( // `ObligationCause` (and the `FnCtxt`). This is what // `regionck_item` expects. let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); - let cause = ObligationCause::new( - impl_ty_span, - impl_ty_hir_id, - ObligationCauseCode::CompareImplTypeObligation { - impl_item_def_id: impl_ty.def_id.expect_local(), - trait_item_def_id: trait_ty.def_id, - }, - ); - debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs); // The predicates declared by the impl definition, the trait and the @@ -1239,7 +1230,7 @@ fn compare_type_predicate_entailment<'tcx>( Reveal::UserFacing, hir::Constness::NotConst, ); - let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause.clone()); + let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); tcx.infer_ctxt().enter(|infcx| { let ocx = ObligationCtxt::new(&infcx); @@ -1247,12 +1238,24 @@ fn compare_type_predicate_entailment<'tcx>( let mut selcx = traits::SelectionContext::new(&infcx); - for predicate in impl_ty_own_bounds.predicates { + assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len()); + for (span, predicate) in + std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates) + { + let cause = ObligationCause::misc(span, impl_ty_hir_id); let traits::Normalized { value: predicate, obligations } = - traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate); + traits::normalize(&mut selcx, param_env, cause, predicate); + let cause = ObligationCause::new( + span, + impl_ty_hir_id, + ObligationCauseCode::CompareImplTypeObligation { + impl_item_def_id: impl_ty.def_id.expect_local(), + trait_item_def_id: trait_ty.def_id, + }, + ); ocx.register_obligations(obligations); - ocx.register_obligation(traits::Obligation::new(cause.clone(), param_env, predicate)); + ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate)); } // Check that all obligations are satisfied by the implementation's 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`.