Skip to content

Commit 2885947

Browse files
committed
Point at individual type arguments on arg count mismatch
1 parent 8e595f5 commit 2885947

File tree

6 files changed

+76
-29
lines changed

6 files changed

+76
-29
lines changed

src/librustc/hir/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::util::nodemap::{NodeMap, FxHashSet};
1616
use crate::mir::mono::Linkage;
1717

1818
use errors::FatalError;
19-
use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
19+
use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan};
2020
use syntax::source_map::Spanned;
2121
use rustc_target::spec::abi::Abi;
2222
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
@@ -624,6 +624,14 @@ impl Generics {
624624
}
625625
None
626626
}
627+
628+
pub fn spans(&self) -> MultiSpan {
629+
if self.params.is_empty() {
630+
self.span.into()
631+
} else {
632+
self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
633+
}
634+
}
627635
}
628636

629637
/// Synthetic type parameters are converted to another form during lowering; this allows

src/librustc_typeck/check/compare_method.rs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
583583
fn compare_number_of_generics<'a, 'tcx>(
584584
tcx: TyCtxt<'a, 'tcx, 'tcx>,
585585
impl_: &ty::AssocItem,
586-
impl_span: Span,
586+
_impl_span: Span,
587587
trait_: &ty::AssocItem,
588588
trait_span: Option<Span>,
589589
) -> Result<(), ErrorReported> {
@@ -600,17 +600,25 @@ fn compare_number_of_generics<'a, 'tcx>(
600600
if impl_count != trait_count {
601601
err_occurred = true;
602602

603-
let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
604-
let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
605-
let span = if impl_item.generics.params.is_empty()
606-
|| impl_item.generics.span.is_dummy() { // argument position impl Trait (#55374)
607-
impl_span
603+
let trait_spans = if let Some(trait_hir_id) = tcx.hir().as_local_hir_id(trait_.def_id) {
604+
let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
605+
Some(if trait_item.generics.params.is_empty() {
606+
vec![trait_item.generics.span]
607+
} else {
608+
trait_item.generics.params.iter().map(|p| p.span).collect::<Vec<Span>>()
609+
})
608610
} else {
609-
impl_item.generics.span
611+
trait_span.map(|s| vec![s])
610612
};
611613

614+
let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
615+
let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
616+
// let span = impl_item.generics.span;
617+
let spans = impl_item.generics.spans();
618+
let span = spans.primary_span();
619+
612620
let mut err = tcx.sess.struct_span_err_with_code(
613-
span,
621+
spans,
614622
&format!(
615623
"method `{}` has {} {kind} parameter{} but its trait \
616624
declaration has {} {kind} parameter{}",
@@ -626,22 +634,32 @@ fn compare_number_of_generics<'a, 'tcx>(
626634

627635
let mut suffix = None;
628636

629-
if let Some(span) = trait_span {
630-
err.span_label(
631-
span,
632-
format!("expected {} {} parameter{}", trait_count, kind,
633-
if trait_count != 1 { "s" } else { "" })
634-
);
637+
if let Some(spans) = trait_spans {
638+
let mut spans = spans.iter();
639+
if let Some(span) = spans.next() {
640+
err.span_label(*span, format!(
641+
"expected {} {} parameter{}",
642+
trait_count,
643+
kind,
644+
if trait_count != 1 { "s" } else { "" },
645+
));
646+
}
647+
for span in spans {
648+
err.span_label(*span, "");
649+
}
635650
} else {
636651
suffix = Some(format!(", expected {}", trait_count));
637652
}
638653

639-
err.span_label(
640-
span,
641-
format!("found {} {} parameter{}{}", impl_count, kind,
654+
if let Some(span) = span {
655+
err.span_label(span, format!(
656+
"found {} {} parameter{}{}",
657+
impl_count,
658+
kind,
642659
if impl_count != 1 { "s" } else { "" },
643-
suffix.unwrap_or_else(|| String::new())),
644-
);
660+
suffix.unwrap_or_else(|| String::new()),
661+
));
662+
}
645663

646664
err.emit();
647665
}

src/test/ui/error-codes/E0049.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,15 @@ impl Foo for Bar {
88
fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
99
}
1010

11+
trait Fuzz {
12+
fn fuzz<A: Default, B>(x: A, y: B) -> Self;
13+
}
14+
15+
struct Baz;
16+
17+
impl Fuzz for Baz {
18+
fn fuzz(x: bool, y: bool) -> Self { Baz } //~ ERROR E0049
19+
}
20+
1121
fn main() {
1222
}

src/test/ui/error-codes/E0049.stderr

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
2-
--> $DIR/E0049.rs:8:5
2+
--> $DIR/E0049.rs:8:11
33
|
44
LL | fn foo<T: Default>(x: T) -> Self;
5-
| --------------------------------- expected 1 type parameter
5+
| - expected 1 type parameter
66
...
77
LL | fn foo(x: bool) -> Self { Bar }
8-
| ^^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters
8+
| ^ found 0 type parameters
99

10-
error: aborting due to previous error
10+
error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters
11+
--> $DIR/E0049.rs:18:12
12+
|
13+
LL | fn fuzz<A: Default, B>(x: A, y: B) -> Self;
14+
| - -
15+
| |
16+
| expected 2 type parameters
17+
...
18+
LL | fn fuzz(x: bool, y: bool) -> Self { Baz }
19+
| ^ found 0 type parameters
20+
21+
error: aborting due to 2 previous errors
1122

1223
For more information about this error, try `rustc --explain E0049`.

src/test/ui/issues/issue-36708.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
2-
--> $DIR/issue-36708.rs:8:11
2+
--> $DIR/issue-36708.rs:8:12
33
|
44
LL | fn foo<T>() {}
5-
| ^^^ found 1 type parameter, expected 0
5+
| ^ found 1 type parameter, expected 0
66

77
error: aborting due to previous error
88

src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
2-
--> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:11
2+
--> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
33
|
44
LL | fn foo(&self, t: Self::T);
5-
| -------------------------- expected 0 type parameters
5+
| - expected 0 type parameters
66
...
77
LL | fn foo(&self, t: impl Clone) {}
8-
| ^ found 1 type parameter
8+
| ^^^^^^^^^^ found 1 type parameter
99

1010
error: aborting due to previous error
1111

0 commit comments

Comments
 (0)