Skip to content

Commit 40c2c0f

Browse files
committed
Include type of missing trait methods in error
Provide either a span pointing to the original definition of missing trait items, or a message with the inferred definitions.
1 parent ac968c4 commit 40c2c0f

14 files changed

+186
-11
lines changed

src/librustc_typeck/check/mod.rs

+25-8
Original file line numberDiff line numberDiff line change
@@ -1114,24 +1114,33 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
11141114

11151115
if !is_implemented {
11161116
if !is_provided {
1117-
missing_items.push(trait_item.name());
1117+
missing_items.push(trait_item);
11181118
} else if associated_type_overridden {
11191119
invalidated_items.push(trait_item.name());
11201120
}
11211121
}
11221122
}
11231123

11241124
if !missing_items.is_empty() {
1125-
struct_span_err!(tcx.sess, impl_span, E0046,
1125+
let mut err = struct_span_err!(tcx.sess, impl_span, E0046,
11261126
"not all trait items implemented, missing: `{}`",
11271127
missing_items.iter()
1128-
.map(|name| name.to_string())
1129-
.collect::<Vec<_>>().join("`, `"))
1130-
.span_label(impl_span, &format!("missing `{}` in implementation",
1128+
.map(|trait_item| trait_item.name().to_string())
1129+
.collect::<Vec<_>>().join("`, `"));
1130+
err.span_label(impl_span, &format!("missing `{}` in implementation",
11311131
missing_items.iter()
1132-
.map(|name| name.to_string())
1133-
.collect::<Vec<_>>().join("`, `"))
1134-
).emit();
1132+
.map(|trait_item| trait_item.name().to_string())
1133+
.collect::<Vec<_>>().join("`, `")));
1134+
for trait_item in missing_items {
1135+
if let Some(span) = tcx.map.span_if_local(trait_item.def_id()) {
1136+
err.span_label(span, &format!("`{}` from trait", trait_item.name()));
1137+
} else {
1138+
err.note(&format!("`{}` from trait: `{}`",
1139+
trait_item.name(),
1140+
signature(trait_item)));
1141+
}
1142+
}
1143+
err.emit();
11351144
}
11361145

11371146
if !invalidated_items.is_empty() {
@@ -1146,6 +1155,14 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
11461155
}
11471156
}
11481157

1158+
fn signature<'a, 'tcx>(item: &ty::ImplOrTraitItem) -> String {
1159+
match *item {
1160+
ty::MethodTraitItem(ref item) => format!("{}", item.fty.sig.0),
1161+
ty::TypeTraitItem(ref item) => format!("type {};", item.name.to_string()),
1162+
ty::ConstTraitItem(ref item) => format!("const {}: {:?};", item.name.to_string(), item.ty),
1163+
}
1164+
}
1165+
11491166
/// Checks a constant with a given type.
11501167
fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
11511168
expr: &'tcx hir::Expr,
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-include ../tools.mk
2+
3+
all:
4+
$(RUSTC) m1.rs -C prefer-dynamic
5+
$(RUSTC) m2.rs 2>&1 | grep "error\[E0046\]: not all trait items implemented, missing: .*"
6+
$(RUSTC) m2.rs 2>&1 | grep " --> m2.rs:18:1"
7+
$(RUSTC) m2.rs 2>&1 | grep " | ^ missing .CONSTANT., .Type., .method. in implementation"
8+
$(RUSTC) m2.rs 2>&1 | grep " = note: .CONSTANT. from trait: .const CONSTANT: u32;."
9+
$(RUSTC) m2.rs 2>&1 | grep " = note: .Type. from trait: .type Type;."
10+
$(RUSTC) m2.rs 2>&1 | grep " = note: .method. from trait: .fn(&Self, std::string::String) -> <Self as m1::X>::Type."

src/test/run-make/missing-items/m1.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(associated_consts)]
12+
#![crate_type = "dylib"]
13+
pub trait X {
14+
const CONSTANT: u32;
15+
type Type;
16+
fn method(&self, s: String) -> Self::Type;
17+
}

src/test/run-make/missing-items/m2.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(associated_consts)]
12+
#![crate_type = "dylib"]
13+
extern crate m1;
14+
15+
struct X {
16+
}
17+
18+
impl m1::X for X {
19+
}

src/test/compile-fail/E0046.rs src/test/ui/span/E0046.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
trait Foo {
1212
fn foo();
13+
//~^ NOTE `foo` from trait
1314
}
1415

1516
struct Bar;

src/test/ui/span/E0046.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0046]: not all trait items implemented, missing: `foo`
2+
--> $DIR/E0046.rs:18:1
3+
|
4+
12 | fn foo();
5+
| --------- `foo` from trait
6+
...
7+
18 | impl Foo for Bar {}
8+
| ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
9+
10+
error: aborting due to previous error
11+

src/test/compile-fail/impl-wrong-item-for-trait.rs src/test/ui/span/impl-wrong-item-for-trait.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
#![feature(associated_consts)]
1212

13+
use std::fmt::Debug;
14+
1315
trait Foo {
1416
fn bar(&self);
15-
//~^ NOTE item in trait
16-
//~| NOTE item in trait
17-
const MY_CONST: u32; //~ NOTE item in trait
17+
const MY_CONST: u32;
1818
}
1919

2020
pub struct FooConstForMethod;
@@ -50,4 +50,7 @@ impl Foo for FooTypeForMethod {
5050
const MY_CONST: u32 = 1;
5151
}
5252

53+
impl Debug for FooTypeForMethod {
54+
}
55+
5356
fn main () {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
error[E0323]: item `bar` is an associated const, which doesn't match its trait `<FooConstForMethod as Foo>`
2+
--> $DIR/impl-wrong-item-for-trait.rs:25:5
3+
|
4+
16 | fn bar(&self);
5+
| -------------- item in trait
6+
...
7+
25 | const bar: u64 = 1;
8+
| ^^^^^^^^^^^^^^^^^^^ does not match trait
9+
10+
error[E0046]: not all trait items implemented, missing: `bar`
11+
--> $DIR/impl-wrong-item-for-trait.rs:22:1
12+
|
13+
16 | fn bar(&self);
14+
| -------------- `bar` from trait
15+
...
16+
22 | impl Foo for FooConstForMethod {
17+
| ^ missing `bar` in implementation
18+
19+
error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `<FooMethodForConst as Foo>`
20+
--> $DIR/impl-wrong-item-for-trait.rs:37:5
21+
|
22+
17 | const MY_CONST: u32;
23+
| -------------------- item in trait
24+
...
25+
37 | fn MY_CONST() {}
26+
| ^^^^^^^^^^^^^^^^ does not match trait
27+
28+
error[E0046]: not all trait items implemented, missing: `MY_CONST`
29+
--> $DIR/impl-wrong-item-for-trait.rs:33:1
30+
|
31+
17 | const MY_CONST: u32;
32+
| -------------------- `MY_CONST` from trait
33+
...
34+
33 | impl Foo for FooMethodForConst {
35+
| ^ missing `MY_CONST` in implementation
36+
37+
error[E0325]: item `bar` is an associated type, which doesn't match its trait `<FooTypeForMethod as Foo>`
38+
--> $DIR/impl-wrong-item-for-trait.rs:47:5
39+
|
40+
16 | fn bar(&self);
41+
| -------------- item in trait
42+
...
43+
47 | type bar = u64;
44+
| ^^^^^^^^^^^^^^^ does not match trait
45+
46+
error[E0046]: not all trait items implemented, missing: `bar`
47+
--> $DIR/impl-wrong-item-for-trait.rs:44:1
48+
|
49+
16 | fn bar(&self);
50+
| -------------- `bar` from trait
51+
...
52+
44 | impl Foo for FooTypeForMethod {
53+
| ^ missing `bar` in implementation
54+
55+
error[E0046]: not all trait items implemented, missing: `fmt`
56+
--> $DIR/impl-wrong-item-for-trait.rs:53:1
57+
|
58+
53 | impl Debug for FooTypeForMethod {
59+
| ^ missing `fmt` in implementation
60+
|
61+
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
62+
63+
error: aborting due to 7 previous errors
64+

src/test/compile-fail/issue-23729.rs src/test/ui/span/issue-23729.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ fn main() {
2020
impl Iterator for Recurrence {
2121
//~^ ERROR E0046
2222
//~| NOTE missing `Item` in implementation
23+
//~| NOTE `Item` from trait: `type Item;`
2324
#[inline]
2425
fn next(&mut self) -> Option<u64> {
2526
if self.pos < 2 {

src/test/ui/span/issue-23729.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0046]: not all trait items implemented, missing: `Item`
2+
--> $DIR/issue-23729.rs:20:9
3+
|
4+
20 | impl Iterator for Recurrence {
5+
| ^ missing `Item` in implementation
6+
|
7+
= note: `Item` from trait: `type Item;`
8+
9+
error: aborting due to previous error
10+

src/test/compile-fail/issue-23827.rs src/test/ui/span/issue-23827.rs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl<C: Component> FnMut<(C,)> for Prototype {
3636
impl<C: Component> FnOnce<(C,)> for Prototype {
3737
//~^ ERROR E0046
3838
//~| NOTE missing `Output` in implementation
39+
//~| NOTE `Output` from trait: `type Output;`
3940
extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype {
4041
Fn::call(&self, (comp,))
4142
}

src/test/ui/span/issue-23827.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0046]: not all trait items implemented, missing: `Output`
2+
--> $DIR/issue-23827.rs:36:1
3+
|
4+
36 | impl<C: Component> FnOnce<(C,)> for Prototype {
5+
| ^ missing `Output` in implementation
6+
|
7+
= note: `Output` from trait: `type Output;`
8+
9+
error: aborting due to previous error
10+

src/test/compile-fail/issue-24356.rs src/test/ui/span/issue-24356.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn main() {
3030
impl Deref for Thing {
3131
//~^ ERROR E0046
3232
//~| NOTE missing `Target` in implementation
33+
//~| NOTE `Target` from trait: `type Target;`
3334
fn deref(&self) -> i8 { self.0 }
3435
}
3536

src/test/ui/span/issue-24356.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0046]: not all trait items implemented, missing: `Target`
2+
--> $DIR/issue-24356.rs:30:9
3+
|
4+
30 | impl Deref for Thing {
5+
| ^ missing `Target` in implementation
6+
|
7+
= note: `Target` from trait: `type Target;`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)