about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/compare_method.rs113
1 files changed, 68 insertions, 45 deletions
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 59766e7e47d..32640d7d9a8 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -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;
-
-    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
-        };
+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();
+
+    let matchings = [
+        ("type", trait_own_counts.types, impl_own_counts.types),
+        ("const", trait_own_counts.consts, impl_own_counts.consts),
+    ];
+
+    let mut err_occurred = false;
+    for &(kind, trait_count, impl_count) in &matchings {
+        if impl_count != trait_count {
+            err_occurred = true;
+
+            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
+            };
 
-        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 = 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;
+            let mut suffix = None;
 
-        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));
-        }
-
-        err.span_label(span,
-                       format!("found {}{}",
-                           potentially_plural_count(num_impl_m_type_params, "type parameter"),
-                           suffix.as_ref().map(|s| &s[..]).unwrap_or("")));
+            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.emit();
+            err.span_label(
+                span,
+                format!("found {} {} parameter{}{}", impl_count, kind,
+                    if impl_count != 1 { "s" } else { "" },
+                    suffix.unwrap_or_else(|| String::new())),
+            );
 
-        return Err(ErrorReported);
+            err.emit();
+        }
     }
 
-    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))