Refactor compare_method
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
parent
f7cd97f786
commit
a8361eb6fa
1 changed files with 68 additions and 45 deletions
|
@ -6,7 +6,7 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
|||
use rustc::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc::ty::subst::{Subst, InternalSubsts, SubstsRef};
|
||||
use rustc::util::common::ErrorReported;
|
||||
use errors::Applicability;
|
||||
use errors::{Applicability, DiagnosticId};
|
||||
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
@ -576,55 +576,78 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
impl_m_span: Span,
|
||||
trait_m: &ty::AssociatedItem,
|
||||
trait_item_span: Option<Span>)
|
||||
-> Result<(), ErrorReported> {
|
||||
let impl_m_generics = tcx.generics_of(impl_m.def_id);
|
||||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
let num_impl_m_type_params = impl_m_generics.own_counts().types;
|
||||
let num_trait_m_type_params = trait_m_generics.own_counts().types;
|
||||
fn compare_number_of_generics<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_: &ty::AssociatedItem,
|
||||
impl_span: Span,
|
||||
trait_: &ty::AssociatedItem,
|
||||
trait_span: Option<Span>,
|
||||
) -> Result<(), ErrorReported> {
|
||||
let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
|
||||
let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
|
||||
|
||||
if num_impl_m_type_params != num_trait_m_type_params {
|
||||
let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap();
|
||||
let impl_m_item = tcx.hir().expect_impl_item(impl_m_node_id);
|
||||
let span = if impl_m_item.generics.params.is_empty()
|
||||
|| impl_m_item.generics.span.is_dummy() // impl Trait in argument position (#55374)
|
||||
{
|
||||
impl_m_span
|
||||
} else {
|
||||
impl_m_item.generics.span
|
||||
};
|
||||
let matchings = [
|
||||
("type", trait_own_counts.types, impl_own_counts.types),
|
||||
("const", trait_own_counts.consts, impl_own_counts.consts),
|
||||
];
|
||||
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0049,
|
||||
"method `{}` has {} but its trait declaration has {}",
|
||||
trait_m.ident,
|
||||
potentially_plural_count(num_impl_m_type_params, "type parameter"),
|
||||
potentially_plural_count(num_trait_m_type_params, "type parameter")
|
||||
);
|
||||
let mut err_occurred = false;
|
||||
for &(kind, trait_count, impl_count) in &matchings {
|
||||
if impl_count != trait_count {
|
||||
err_occurred = true;
|
||||
|
||||
let mut suffix = None;
|
||||
let impl_node_id = tcx.hir().as_local_node_id(impl_.def_id).unwrap();
|
||||
let impl_item = tcx.hir().expect_impl_item(impl_node_id);
|
||||
let span = if impl_item.generics.params.is_empty()
|
||||
|| impl_item.generics.span.is_dummy() { // argument position impl Trait (#55374)
|
||||
impl_span
|
||||
} else {
|
||||
impl_item.generics.span
|
||||
};
|
||||
|
||||
if let Some(span) = trait_item_span {
|
||||
err.span_label(span, format!("expected {}",
|
||||
potentially_plural_count(num_trait_m_type_params, "type parameter")));
|
||||
} else {
|
||||
suffix = Some(format!(", expected {}", num_trait_m_type_params));
|
||||
let mut err = tcx.sess.struct_span_err_with_code(
|
||||
span,
|
||||
&format!(
|
||||
"method `{}` has {} {kind} parameter{} but its trait \
|
||||
declaration has {} {kind} parameter{}",
|
||||
trait_.ident,
|
||||
impl_count,
|
||||
if impl_count != 1 { "s" } else { "" },
|
||||
trait_count,
|
||||
if trait_count != 1 { "s" } else { "" },
|
||||
kind = kind,
|
||||
),
|
||||
DiagnosticId::Error("E0049".into()),
|
||||
);
|
||||
|
||||
let mut suffix = None;
|
||||
|
||||
if let Some(span) = trait_span {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("expected {} {} parameter{}", trait_count, kind,
|
||||
if trait_count != 1 { "s" } else { "" })
|
||||
);
|
||||
} else {
|
||||
suffix = Some(format!(", expected {}", trait_count));
|
||||
}
|
||||
|
||||
err.span_label(
|
||||
span,
|
||||
format!("found {} {} parameter{}{}", impl_count, kind,
|
||||
if impl_count != 1 { "s" } else { "" },
|
||||
suffix.unwrap_or_else(|| String::new())),
|
||||
);
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
err.span_label(span,
|
||||
format!("found {}{}",
|
||||
potentially_plural_count(num_impl_m_type_params, "type parameter"),
|
||||
suffix.as_ref().map(|s| &s[..]).unwrap_or("")));
|
||||
|
||||
err.emit();
|
||||
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if err_occurred {
|
||||
Err(ErrorReported)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -725,12 +748,12 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
|
||||
});
|
||||
let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
|
||||
}
|
||||
});
|
||||
for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue