Rollup merge of #99353 - compiler-errors:gat-where-clause-mismatch, r=cjgillot
Slightly improve mismatched GAT where clause error This makes the error reporting a bit more standardized between `where` on GATs and functions. cc #99206 (`@BoxyUwU),` don't want to mark this as as "fixed" because they're still not perfect, but this is still an improvement IMO so I want to land it incrementally. regarding "consider adding where clause to trait definition", we don't actually do that for methods as far as i can tell? i could file an issue to look into that maybe.
This commit is contained in:
@@ -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,7 +2351,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
|
GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(SubregionOrigin::CompareImplMethodObligation {
|
if let Some(SubregionOrigin::CompareImplItemObligation {
|
||||||
span,
|
span,
|
||||||
impl_item_def_id,
|
impl_item_def_id,
|
||||||
trait_item_def_id,
|
trait_item_def_id,
|
||||||
@@ -2788,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",
|
||||||
@@ -2823,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 `()`",
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
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::{SubregionOrigin, Subtype};
|
use crate::infer::Subtype;
|
||||||
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
|
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;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty::print::RegionHighlightMode;
|
use rustc_middle::ty::print::RegionHighlightMode;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
@@ -22,38 +22,22 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||||||
let error = self.error.as_ref()?;
|
let error = self.error.as_ref()?;
|
||||||
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
|
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
|
||||||
if let RegionResolutionError::SubSupConflict(
|
if let RegionResolutionError::SubSupConflict(
|
||||||
_, var_origin, sub_origin, _sub, sup_origin, _sup, _,
|
_,
|
||||||
|
var_origin,
|
||||||
|
sub_origin,
|
||||||
|
_sub,
|
||||||
|
sup_origin,
|
||||||
|
_sup,
|
||||||
|
_,
|
||||||
) = error.clone()
|
) = error.clone()
|
||||||
&& let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin)
|
&& let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin)
|
||||||
&& let (
|
&& let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty()
|
||||||
sub_expected_found @ Some((sub_expected, sub_found)),
|
&& let sup_expected_found @ Some(_) = sup_trace.values.ty()
|
||||||
sup_expected_found @ Some(_),
|
&& let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code()
|
||||||
CompareImplMethodObligation { trait_item_def_id, .. },
|
|
||||||
) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
|
|
||||||
&& sup_expected_found == sub_expected_found
|
&& sup_expected_found == sub_expected_found
|
||||||
{
|
{
|
||||||
let guar = self.emit_err(
|
let guar =
|
||||||
var_origin.span(),
|
self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id);
|
||||||
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,
|
|
||||||
);
|
|
||||||
return Some(guar);
|
return Some(guar);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@@ -147,25 +131,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
err.emit()
|
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> {
|
struct TypeParamSpanVisitor<'tcx> {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -1212,15 +1218,6 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||||||
// `ObligationCause` (and the `FnCtxt`). This is what
|
// `ObligationCause` (and the `FnCtxt`). This is what
|
||||||
// `regionck_item` expects.
|
// `regionck_item` expects.
|
||||||
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
|
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);
|
debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
|
||||||
|
|
||||||
// The predicates declared by the impl definition, the trait and the
|
// The predicates declared by the impl definition, the trait and the
|
||||||
@@ -1239,7 +1236,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||||||
Reveal::UserFacing,
|
Reveal::UserFacing,
|
||||||
hir::Constness::NotConst,
|
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| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
|
||||||
@@ -1247,12 +1244,25 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||||||
|
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
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 } =
|
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::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);
|
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
|
// Check that all obligations are satisfied by the implementation's
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ LL | type Assoc2<T: std::fmt::Display> = Vec<T>;
|
|||||||
| +++++++++++++++++++
|
| +++++++++++++++++++
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
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<T>;
|
LL | type Assoc3<T>;
|
||||||
| -------------- definition of `Assoc3` from trait
|
| -------------- definition of `Assoc3` from trait
|
||||||
...
|
...
|
||||||
LL | type Assoc3<T> = Vec<T> where T: Iterator;
|
LL | type Assoc3<T> = Vec<T> where T: Iterator;
|
||||||
| ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
|
| ^^^^^^^^ impl has extra requirement `T: Iterator`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ struct Fooy<T>(T);
|
|||||||
|
|
||||||
impl<T> Foo for Fooy<T> {
|
impl<T> Foo for Fooy<T> {
|
||||||
type A<'a> = (&'a ()) where Self: 'static;
|
type A<'a> = (&'a ()) where Self: 'static;
|
||||||
//~^ ERROR `impl` associated type
|
//~^ ERROR impl has stricter requirements than trait
|
||||||
type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
|
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
|
//~| ERROR lifetime bound not satisfied
|
||||||
type C = String where Self: Copy;
|
type C = String where Self: Copy;
|
||||||
//~^ ERROR the trait bound `T: Copy` is not satisfied
|
//~^ ERROR the trait bound `T: Copy` is not satisfied
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
error: `impl` associated type signature for `A` doesn't match `trait` associated type signature
|
error[E0276]: impl has stricter requirements than trait
|
||||||
--> $DIR/impl_bounds.rs:15:5
|
--> $DIR/impl_bounds.rs:15:39
|
||||||
|
|
|
|
||||||
LL | type A<'a> where Self: 'a;
|
LL | type A<'a> where Self: 'a;
|
||||||
| ---------- expected
|
| ---------- definition of `A` from trait
|
||||||
...
|
...
|
||||||
LL | type A<'a> = (&'a ()) where Self: 'static;
|
LL | type A<'a> = (&'a ()) where Self: 'static;
|
||||||
| ^^^^^^^^^^ found
|
| ^^^^^^^ impl has extra requirement `T: 'static`
|
||||||
|
|
||||||
error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
|
error[E0276]: impl has stricter requirements than trait
|
||||||
--> $DIR/impl_bounds.rs:17:5
|
--> $DIR/impl_bounds.rs:17:48
|
||||||
|
|
|
|
||||||
LL | type B<'a, 'b> where 'a: 'b;
|
LL | type B<'a, 'b> where 'a: 'b;
|
||||||
| -------------- expected
|
| -------------- definition of `B` from trait
|
||||||
...
|
...
|
||||||
LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
|
LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
|
||||||
| ^^^^^^^^^^^^^^ found
|
| ^^ impl has extra requirement `'b: 'a`
|
||||||
|
|
||||||
error[E0478]: lifetime bound not satisfied
|
error[E0478]: lifetime bound not satisfied
|
||||||
--> $DIR/impl_bounds.rs:17:22
|
--> $DIR/impl_bounds.rs:17:22
|
||||||
@@ -37,24 +37,24 @@ LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
|
|||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `T: Copy` is not satisfied
|
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;
|
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<T>`
|
note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
|
||||||
--> $DIR/impl_bounds.rs:11:10
|
--> $DIR/impl_bounds.rs:11:10
|
||||||
|
|
|
|
||||||
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`
|
||||||
|
|
|
|
||||||
@@ -88,5 +88,5 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
|
|||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0478.
|
Some errors have detailed explanations: E0276, E0277, E0478.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0276`.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
error[E0276]: impl has stricter requirements than trait
|
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<T>;
|
LL | type Assoc3<T>;
|
||||||
| -------------- definition of `Assoc3` from trait
|
| -------------- definition of `Assoc3` from trait
|
||||||
...
|
...
|
||||||
LL | type Assoc3<T> = Vec<T> where T: Iterator;
|
LL | type Assoc3<T> = Vec<T> where T: Iterator;
|
||||||
| ^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
|
| ^^^^^^^^ impl has extra requirement `T: Iterator`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ trait Foo {
|
|||||||
}
|
}
|
||||||
impl Foo for () {
|
impl Foo for () {
|
||||||
type Assoc<'a, 'b> = () where 'a: 'b;
|
type Assoc<'a, 'b> = () where 'a: 'b;
|
||||||
//~^ `impl` associated type
|
//~^ impl has stricter requirements than trait
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature
|
error[E0276]: impl has stricter requirements than trait
|
||||||
--> $DIR/missing-where-clause-on-trait.rs:9:5
|
--> $DIR/missing-where-clause-on-trait.rs:9:39
|
||||||
|
|
|
|
||||||
LL | type Assoc<'a, 'b>;
|
LL | type Assoc<'a, 'b>;
|
||||||
| ------------------ expected
|
| ------------------ definition of `Assoc` from trait
|
||||||
...
|
...
|
||||||
LL | type Assoc<'a, 'b> = () where 'a: 'b;
|
LL | type Assoc<'a, 'b> = () where 'a: 'b;
|
||||||
| ^^^^^^^^^^^^^^^^^^ found
|
| ^^ impl has extra requirement `'a: 'b`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0276`.
|
||||||
|
|||||||
@@ -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 { }
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user