]> git.lizzy.rs Git - rust.git/commitdiff
Point at individual type arguments on arg count mismatch
authorEsteban Küber <esteban@kuber.com.ar>
Sat, 1 Jun 2019 17:35:31 +0000 (10:35 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Sat, 1 Jun 2019 17:35:31 +0000 (10:35 -0700)
src/librustc/hir/mod.rs
src/librustc_typeck/check/compare_method.rs
src/test/ui/error-codes/E0049.rs
src/test/ui/error-codes/E0049.stderr
src/test/ui/issues/issue-36708.stderr
src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr

index f03a8ddc90825a7a23086878d2150da9d2bb744d..d9c98d60b958d3ab8ca4c24f76bc6a358931fe2a 100644 (file)
@@ -16,7 +16,7 @@
 use crate::mir::mono::Linkage;
 
 use errors::FatalError;
-use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
+use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan};
 use syntax::source_map::Spanned;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
@@ -624,6 +624,14 @@ pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> {
         }
         None
     }
+
+    pub fn spans(&self) -> MultiSpan {
+        if self.params.is_empty() {
+            self.span.into()
+        } else {
+            self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
+        }
+    }
 }
 
 /// Synthetic type parameters are converted to another form during lowering; this allows
index cc074b64cc01c0c3497e78e0e9af3eb26f53789c..742f6ed5215cb7c7ad404827e30b659a27c2ec98 100644 (file)
@@ -583,7 +583,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn compare_number_of_generics<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     impl_: &ty::AssocItem,
-    impl_span: Span,
+    _impl_span: Span,
     trait_: &ty::AssocItem,
     trait_span: Option<Span>,
 ) -> Result<(), ErrorReported> {
@@ -600,17 +600,25 @@ fn compare_number_of_generics<'a, 'tcx>(
         if impl_count != trait_count {
             err_occurred = true;
 
-            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
-            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
-            let span = if impl_item.generics.params.is_empty()
-                || impl_item.generics.span.is_dummy() { // argument position impl Trait (#55374)
-                impl_span
+            let trait_spans = if let Some(trait_hir_id) = tcx.hir().as_local_hir_id(trait_.def_id) {
+                let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
+                Some(if trait_item.generics.params.is_empty() {
+                    vec![trait_item.generics.span]
+                } else {
+                    trait_item.generics.params.iter().map(|p| p.span).collect::<Vec<Span>>()
+                })
             } else {
-                impl_item.generics.span
+                trait_span.map(|s| vec![s])
             };
 
+            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
+            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
+            // let span = impl_item.generics.span;
+            let spans = impl_item.generics.spans();
+            let span = spans.primary_span();
+
             let mut err = tcx.sess.struct_span_err_with_code(
-                span,
+                spans,
                 &format!(
                     "method `{}` has {} {kind} parameter{} but its trait \
                      declaration has {} {kind} parameter{}",
@@ -626,22 +634,32 @@ fn compare_number_of_generics<'a, 'tcx>(
 
             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 { "" })
-                );
+            if let Some(spans) = trait_spans {
+                let mut spans = spans.iter();
+                if let Some(span) = spans.next() {
+                    err.span_label(*span, format!(
+                        "expected {} {} parameter{}",
+                        trait_count,
+                        kind,
+                        if trait_count != 1 { "s" } else { "" },
+                    ));
+                }
+                for span in spans {
+                    err.span_label(*span, "");
+                }
             } else {
                 suffix = Some(format!(", expected {}", trait_count));
             }
 
-            err.span_label(
-                span,
-                format!("found {} {} parameter{}{}", impl_count, kind,
+            if let Some(span) = span {
+                err.span_label(span, format!(
+                    "found {} {} parameter{}{}",
+                    impl_count,
+                    kind,
                     if impl_count != 1 { "s" } else { "" },
-                    suffix.unwrap_or_else(|| String::new())),
-            );
+                    suffix.unwrap_or_else(|| String::new()),
+                ));
+            }
 
             err.emit();
         }
index c141f8a882820f05ada27e1c02bb711c6ebe4cae..3dd910019bfd08337c6a9db1f118e8e0e5488643 100644 (file)
@@ -8,5 +8,15 @@ impl Foo for Bar {
     fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
 }
 
+trait Fuzz {
+    fn fuzz<A: Default, B>(x: A, y: B) -> Self;
+}
+
+struct Baz;
+
+impl Fuzz for Baz {
+    fn fuzz(x: bool, y: bool) -> Self { Baz } //~ ERROR E0049
+}
+
 fn main() {
 }
index 7e9b9e8efb9a815fd4586501459accfdd3dcf444..c0cd31faa90d60056cc31fe6d5a0446fe7b28e43 100644 (file)
@@ -1,12 +1,23 @@
 error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
-  --> $DIR/E0049.rs:8:5
+  --> $DIR/E0049.rs:8:11
    |
 LL |     fn foo<T: Default>(x: T) -> Self;
-   |     --------------------------------- expected 1 type parameter
+   |            - expected 1 type parameter
 ...
 LL |     fn foo(x: bool) -> Self { Bar }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters
+   |           ^ found 0 type parameters
 
-error: aborting due to previous error
+error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters
+  --> $DIR/E0049.rs:18:12
+   |
+LL |     fn fuzz<A: Default, B>(x: A, y: B) -> Self;
+   |             -           -
+   |             |
+   |             expected 2 type parameters
+...
+LL |     fn fuzz(x: bool, y: bool) -> Self { Baz }
+   |            ^ found 0 type parameters
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0049`.
index 835094c4fdc5e2822a584d010d1650cf0c8526fc..140f19f1ff7746f0ed898c405acb7bd5564d4b8d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/issue-36708.rs:8:11
+  --> $DIR/issue-36708.rs:8:12
    |
 LL |     fn foo<T>() {}
-   |           ^^^ found 1 type parameter, expected 0
+   |            ^ found 1 type parameter, expected 0
 
 error: aborting due to previous error
 
index 3f1b10fab27f356f0797f7a03a55ea87dae2a6d7..953284735553c3d805d21cdba30b6143cea41117 100644 (file)
@@ -1,11 +1,11 @@
 error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:11
+  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
    |
 LL |     fn foo(&self, t: Self::T);
-   |     -------------------------- expected 0 type parameters
+   |           - expected 0 type parameters
 ...
 LL |     fn foo(&self, t: impl Clone) {}
-   |           ^ found 1 type parameter
+   |                      ^^^^^^^^^^ found 1 type parameter
 
 error: aborting due to previous error