1
Fork 0

Combine redundant obligation cause codes

This commit is contained in:
Michael Goulet 2022-07-24 19:33:26 +00:00
parent 2bbcdc7333
commit 3bbe95ca0c
17 changed files with 80 additions and 138 deletions

View file

@ -1883,7 +1883,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
exp_span, exp_found.expected, exp_found.found, exp_span, exp_found.expected, exp_found.found,
); );
if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() { if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
return; return;
} }
@ -2351,24 +2351,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
GenericKind::Projection(ref p) => format!("the associated type `{}`", p), GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
}; };
match origin { if let Some(SubregionOrigin::CompareImplItemObligation {
Some(SubregionOrigin::CompareImplMethodObligation { span,
impl_item_def_id,
trait_item_def_id,
}) = origin
{
return self.report_extra_impl_obligation(
span, span,
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,
} | SubregionOrigin::CompareImplTypeObligation { &format!("`{}: {}`", bound_kind, sub),
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>( fn binding_suggestion<'tcx, S: fmt::Display>(
@ -2794,8 +2788,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
use self::FailureCode::*; use self::FailureCode::*;
use crate::traits::ObligationCauseCode::*; use crate::traits::ObligationCauseCode::*;
match self.code() { match self.code() {
CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"), 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, .. }) => { MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
Error0308(match source { Error0308(match source {
hir::MatchSource::TryDesugar => "`?` operator has incompatible types", 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 { fn as_requirement_str(&self) -> &'static str {
use crate::traits::ObligationCauseCode::*; use crate::traits::ObligationCauseCode::*;
match self.code() { match self.code() {
CompareImplMethodObligation { .. } => "method type is compatible with trait", CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
CompareImplTypeObligation { .. } => "associated type is compatible with trait", "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", ExprAssignable => "expression is assignable",
IfExpression { .. } => "`if` and `else` have incompatible types", IfExpression { .. } => "`if` and `else` have incompatible types",
IfExpressionWithNoElse => "`if` missing an `else` returns `()`", IfExpressionWithNoElse => "`if` missing an `else` returns `()`",

View file

@ -3,7 +3,7 @@
use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::Subtype; use crate::infer::Subtype;
use crate::traits::ObligationCauseCode::{CompareImplMethodObligation, CompareImplTypeObligation}; use crate::traits::ObligationCauseCode::CompareImplItemObligation;
use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_errors::{ErrorGuaranteed, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; 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 (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
&& let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty() && let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
&& let sup_expected_found @ Some(_) = sup_trace.values.ty() && let sup_expected_found @ Some(_) = sup_trace.values.ty()
&& let CompareImplMethodObligation { trait_item_def_id, .. } && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
| CompareImplTypeObligation { trait_item_def_id, .. } = sub_trace.cause.code()
&& sup_expected_found == sub_expected_found && sup_expected_found == sub_expected_found
{ {
let guar = let guar =

View file

@ -86,13 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"...so that the declared lifetime parameter bounds are satisfied", "...so that the declared lifetime parameter bounds are satisfied",
); );
} }
infer::CompareImplMethodObligation { span, .. } => { infer::CompareImplItemObligation { span, .. } => {
label_or_note(
span,
"...so that the definition in impl matches the definition from the trait",
);
}
infer::CompareImplTypeObligation { span, .. } => {
label_or_note( label_or_note(
span, span,
"...so that the definition in impl matches the definition from the trait", "...so that the definition in impl matches the definition from the trait",
@ -329,15 +323,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
); );
err err
} }
infer::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id } => { infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
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
.report_extra_impl_obligation( .report_extra_impl_obligation(
span, span,
impl_item_def_id, impl_item_def_id,

View file

@ -405,15 +405,7 @@ pub enum SubregionOrigin<'tcx> {
/// Comparing the signature and requirements of an impl method against /// Comparing the signature and requirements of an impl method against
/// the containing trait. /// the containing trait.
CompareImplMethodObligation { CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
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 },
/// Checking that the bounds of a trait's associated type hold for a given impl /// Checking that the bounds of a trait's associated type hold for a given impl
CheckAssociatedTypeBounds { CheckAssociatedTypeBounds {
@ -1945,8 +1937,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
ReborrowUpvar(a, _) => a, ReborrowUpvar(a, _) => a,
DataBorrowed(_, a) => a, DataBorrowed(_, a) => a,
ReferenceOutlivesReferent(_, a) => a, ReferenceOutlivesReferent(_, a) => a,
CompareImplMethodObligation { span, .. } => span, CompareImplItemObligation { span, .. } => span,
CompareImplTypeObligation { span, .. } => span,
CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
} }
} }
@ -1960,19 +1951,11 @@ impl<'tcx> SubregionOrigin<'tcx> {
SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
} }
traits::ObligationCauseCode::CompareImplMethodObligation { traits::ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,
} => SubregionOrigin::CompareImplMethodObligation { kind: _,
span: cause.span, } => SubregionOrigin::CompareImplItemObligation {
impl_item_def_id,
trait_item_def_id,
},
traits::ObligationCauseCode::CompareImplTypeObligation {
impl_item_def_id,
trait_item_def_id,
} => SubregionOrigin::CompareImplTypeObligation {
span: cause.span, span: cause.span,
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,

View file

@ -311,18 +311,10 @@ pub enum ObligationCauseCode<'tcx> {
}, },
/// Error derived when matching traits/impls; see ObligationCause for more details /// Error derived when matching traits/impls; see ObligationCause for more details
CompareImplConstObligation, CompareImplItemObligation {
/// 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 {
impl_item_def_id: LocalDefId, impl_item_def_id: LocalDefId,
trait_item_def_id: DefId, trait_item_def_id: DefId,
kind: ty::AssocKind,
}, },
/// Checking that the bounds of a trait's associated type hold for a given impl /// Checking that the bounds of a trait's associated type hold for a given impl

View file

@ -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. /// 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 /// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since

View file

@ -660,12 +660,8 @@ impl<T> Trait<T> for X {
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }), | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
) )
); );
let impl_comparison = matches!( let impl_comparison =
cause_code, matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
ObligationCauseCode::CompareImplMethodObligation { .. }
| ObligationCauseCode::CompareImplTypeObligation { .. }
| ObligationCauseCode::CompareImplConstObligation
);
let assoc = self.associated_item(proj_ty.item_def_id); let assoc = self.associated_item(proj_ty.item_def_id);
if !callable_scope || impl_comparison { if !callable_scope || impl_comparison {
// We do not want to suggest calling functions when the reason of the // We do not want to suggest calling functions when the reason of the

View file

@ -224,6 +224,7 @@ TrivialTypeTraversalAndLiftImpls! {
// general `Region`. // general `Region`.
crate::ty::BoundRegionKind, crate::ty::BoundRegionKind,
crate::ty::AssocItem, crate::ty::AssocItem,
crate::ty::AssocKind,
crate::ty::Placeholder<crate::ty::BoundRegionKind>, crate::ty::Placeholder<crate::ty::BoundRegionKind>,
crate::ty::ClosureKind, crate::ty::ClosureKind,
crate::ty::FreeRegion, crate::ty::FreeRegion,

View file

@ -301,13 +301,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span = obligation.cause.span; span = obligation.cause.span;
} }
} }
if let ObligationCauseCode::CompareImplMethodObligation { if let ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id,
trait_item_def_id,
}
| ObligationCauseCode::CompareImplTypeObligation {
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,
kind: _,
} = *obligation.cause.code() } = *obligation.cause.code()
{ {
self.report_extra_impl_obligation( self.report_extra_impl_obligation(

View file

@ -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 item_name = self.tcx.item_name(trait_item_def_id);
let msg = format!( let msg = format!(
"the requirement `{}` appears on the impl method `{}` but not on the \ "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
corresponding trait method", corresponding trait's {kind}",
predicate, item_name, predicate, item_name,
); );
let sp = self let sp = self
@ -2697,7 +2697,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let mut assoc_span: MultiSpan = sp.into(); let mut assoc_span: MultiSpan = sp.into();
assoc_span.push_span_label( assoc_span.push_span_label(
sp, 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 if let Some(ident) = self
.tcx .tcx
@ -2708,38 +2708,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
err.span_note(assoc_span, &msg); 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 => { ObligationCauseCode::TrivialBound => {
err.help("see issue #48214"); err.help("see issue #48214");
if tcx.sess.opts.unstable_features.is_nightly_build() { if tcx.sess.opts.unstable_features.is_nightly_build() {

View file

@ -1150,17 +1150,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.expect("missing associated type"); .expect("missing associated type");
if !assoc_item.vis.is_accessible_from(def_scope, tcx) { 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 tcx.sess
.struct_span_err( .struct_span_err(
binding.span, 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(); .emit();
} }
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);

View file

@ -90,9 +90,10 @@ fn compare_predicate_entailment<'tcx>(
let mut cause = ObligationCause::new( let mut cause = ObligationCause::new(
impl_m_span, impl_m_span,
impl_m_hir_id, impl_m_hir_id,
ObligationCauseCode::CompareImplMethodObligation { ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_m.def_id.expect_local(), impl_item_def_id: impl_m.def_id.expect_local(),
trait_item_def_id: trait_m.def_id, 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( let cause = ObligationCause::new(
span, span,
impl_m_hir_id, impl_m_hir_id,
ObligationCauseCode::CompareImplMethodObligation { ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_m.def_id.expect_local(), impl_item_def_id: impl_m.def_id.expect_local(),
trait_item_def_id: trait_m.def_id, trait_item_def_id: trait_m.def_id,
kind: impl_m.kind,
}, },
); );
ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate)); 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( let mut cause = ObligationCause::new(
impl_c_span, impl_c_span,
impl_c_hir_id, 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. // There is no "body" here, so just pass dummy id.
@ -1249,9 +1255,10 @@ fn compare_type_predicate_entailment<'tcx>(
let cause = ObligationCause::new( let cause = ObligationCause::new(
span, span,
impl_ty_hir_id, impl_ty_hir_id,
ObligationCauseCode::CompareImplTypeObligation { ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_ty.def_id.expect_local(), impl_item_def_id: impl_ty.def_id.expect_local(),
trait_item_def_id: trait_ty.def_id, trait_item_def_id: trait_ty.def_id,
kind: impl_ty.kind,
}, },
); );
ocx.register_obligations(obligations); ocx.register_obligations(obligations);

View file

@ -5,7 +5,7 @@ trait Foo {
impl<'a> Foo for &'a () { impl<'a> Foo for &'a () {
const NAME: &'a str = "unit"; const NAME: &'a str = "unit";
//~^ ERROR mismatched types [E0308] //~^ ERROR const not compatible with trait
} }
fn main() {} fn main() {}

View file

@ -1,4 +1,4 @@
error[E0308]: mismatched types error[E0308]: const not compatible with trait
--> $DIR/associated-const-impl-wrong-lifetime.rs:7:5 --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5
| |
LL | const NAME: &'a str = "unit"; LL | const NAME: &'a str = "unit";

View file

@ -47,14 +47,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
| |
LL | #[derive(Copy, Clone)] LL | #[derive(Copy, Clone)]
| ^^^^ | ^^^^
note: the requirement `Fooy<T>: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type note: the requirement `Fooy<T>: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type
--> $DIR/impl_bounds.rs:7:5 --> $DIR/impl_bounds.rs:7:10
| |
LL | trait Foo { LL | trait Foo {
| --- in this trait | --- in this trait
... ...
LL | type C where Self: Clone; LL | type C where Self: Clone;
| ^^^^^^ this trait associated type doesn't have the requirement `Fooy<T>: Copy` | ^ this trait's associated type doesn't have the requirement `Fooy<T>: Copy`
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) = 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` help: consider restricting type parameter `T`
| |
@ -72,14 +72,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
| |
LL | #[derive(Copy, Clone)] LL | #[derive(Copy, Clone)]
| ^^^^ | ^^^^
note: the requirement `Fooy<T>: Copy` appears on the impl method `d` but not on the corresponding trait method note: the requirement `Fooy<T>: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method
--> $DIR/impl_bounds.rs:8:8 --> $DIR/impl_bounds.rs:8:8
| |
LL | trait Foo { LL | trait Foo {
| --- in this trait | --- in this trait
... ...
LL | fn d() where Self: Clone; LL | fn d() where Self: Clone;
| ^ this trait method doesn't have the requirement `Fooy<T>: Copy` | ^ this trait's method doesn't have the requirement `Fooy<T>: Copy`
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) = 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` help: consider restricting type parameter `T`
| |

View file

@ -19,7 +19,7 @@ struct FailStruct { }
impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
const AC: Option<&'c str> = None; const AC: Option<&'c str> = None;
//~^ ERROR: mismatched types //~^ ERROR: const not compatible with trait
} }
struct OKStruct2 { } struct OKStruct2 { }

View file

@ -1,4 +1,4 @@
error[E0308]: mismatched types error[E0308]: const not compatible with trait
--> $DIR/trait-associated-constant.rs:21:5 --> $DIR/trait-associated-constant.rs:21:5
| |
LL | const AC: Option<&'c str> = None; LL | const AC: Option<&'c str> = None;