Detect stricter constraints on gats where clauses in impls vs trait
This commit is contained in:
parent
fdf65053e9
commit
af9de99f12
8 changed files with 153 additions and 50 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||
use crate::infer::{Subtype, ValuePairs};
|
||||
use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
|
||||
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir as hir;
|
||||
|
@ -11,44 +11,52 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::ty::error::ExpectedFound;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
use rustc_span::{MultiSpan, Span, Symbol};
|
||||
|
||||
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
|
||||
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
|
||||
if let Some(ref error) = self.error {
|
||||
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
|
||||
if let RegionResolutionError::SubSupConflict(
|
||||
_,
|
||||
var_origin,
|
||||
sub_origin,
|
||||
_sub,
|
||||
sup_origin,
|
||||
_sup,
|
||||
) = error.clone()
|
||||
{
|
||||
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
|
||||
(&sup_origin, &sub_origin)
|
||||
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,
|
||||
) = error.clone()
|
||||
{
|
||||
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
|
||||
if let (
|
||||
ValuePairs::Types(sub_expected_found),
|
||||
ValuePairs::Types(sup_expected_found),
|
||||
CompareImplMethodObligation { trait_item_def_id, .. },
|
||||
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
|
||||
{
|
||||
if let (
|
||||
ValuePairs::Types(sub_expected_found),
|
||||
ValuePairs::Types(sup_expected_found),
|
||||
CompareImplMethodObligation { trait_item_def_id, .. },
|
||||
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
|
||||
{
|
||||
if sup_expected_found == sub_expected_found {
|
||||
self.emit_err(
|
||||
var_origin.span(),
|
||||
sub_expected_found.expected,
|
||||
sub_expected_found.found,
|
||||
*trait_item_def_id,
|
||||
);
|
||||
return Some(ErrorReported);
|
||||
}
|
||||
if sup_expected_found == sub_expected_found {
|
||||
self.emit_err(
|
||||
var_origin.span(),
|
||||
sub_expected_found.expected,
|
||||
sub_expected_found.found,
|
||||
*trait_item_def_id,
|
||||
);
|
||||
return Some(ErrorReported);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
|
||||
if let SubregionOrigin::CompareImplTypeObligation {
|
||||
span,
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
} = origin
|
||||
{
|
||||
self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -107,6 +115,25 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn emit_associated_type_err(
|
||||
&self,
|
||||
span: Span,
|
||||
item_name: Symbol,
|
||||
impl_item_def_id: DefId,
|
||||
trait_item_def_id: DefId,
|
||||
) {
|
||||
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, &format!("found"));
|
||||
err.span_label(trait_sp, &format!("expected"));
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
struct TypeParamSpanVisitor<'tcx> {
|
||||
|
|
|
@ -99,6 +99,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
"...so that the definition in impl matches the definition from the trait",
|
||||
);
|
||||
}
|
||||
infer::CompareImplTypeObligation { span, .. } => {
|
||||
label_or_note(
|
||||
span,
|
||||
"...so that the definition in impl matches the definition from the trait",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,6 +362,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
trait_item_def_id,
|
||||
&format!("`{}: {}`", sup, sub),
|
||||
),
|
||||
infer::CompareImplTypeObligation {
|
||||
span,
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
} => self.report_extra_impl_obligation(
|
||||
span,
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
&format!("`{}: {}`", sup, sub),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -427,6 +427,15 @@ pub enum SubregionOrigin<'tcx> {
|
|||
impl_item_def_id: DefId,
|
||||
trait_item_def_id: DefId,
|
||||
},
|
||||
|
||||
/// Comparing the signature and requirements of an impl associated type
|
||||
/// against the containing trait
|
||||
CompareImplTypeObligation {
|
||||
span: Span,
|
||||
item_name: Symbol,
|
||||
impl_item_def_id: DefId,
|
||||
trait_item_def_id: DefId,
|
||||
},
|
||||
}
|
||||
|
||||
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
|
@ -1810,6 +1819,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||
ReferenceOutlivesReferent(_, a) => a,
|
||||
CallReturn(a) => a,
|
||||
CompareImplMethodObligation { span, .. } => span,
|
||||
CompareImplTypeObligation { span, .. } => span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1833,6 +1843,17 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||
trait_item_def_id,
|
||||
},
|
||||
|
||||
traits::ObligationCauseCode::CompareImplTypeObligation {
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
} => SubregionOrigin::CompareImplTypeObligation {
|
||||
span: cause.span,
|
||||
item_name,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
},
|
||||
|
||||
_ => default(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue