Skip to content

Commit 7f2853f

Browse files
authored
Rollup merge of rust-lang#37370 - estebank:signature-2-empire-strikes-back, r=nikomatsakis
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. Fixes rust-lang#24626. Follow up to PR rust-lang#36371. If PR rust-lang#37369 lands, missing trait items that present a multiline span will be able to show the entirety of the item definition on the error itself, instead of just the first line.
2 parents 6c7b433 + 40c2c0f commit 7f2853f

14 files changed

+186
-11
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,24 +1131,33 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
11311131

11321132
if !is_implemented {
11331133
if !is_provided {
1134-
missing_items.push(trait_item.name());
1134+
missing_items.push(trait_item);
11351135
} else if associated_type_overridden {
11361136
invalidated_items.push(trait_item.name());
11371137
}
11381138
}
11391139
}
11401140

11411141
if !missing_items.is_empty() {
1142-
struct_span_err!(tcx.sess, impl_span, E0046,
1142+
let mut err = struct_span_err!(tcx.sess, impl_span, E0046,
11431143
"not all trait items implemented, missing: `{}`",
11441144
missing_items.iter()
1145-
.map(|name| name.to_string())
1146-
.collect::<Vec<_>>().join("`, `"))
1147-
.span_label(impl_span, &format!("missing `{}` in implementation",
1145+
.map(|trait_item| trait_item.name().to_string())
1146+
.collect::<Vec<_>>().join("`, `"));
1147+
err.span_label(impl_span, &format!("missing `{}` in implementation",
11481148
missing_items.iter()
1149-
.map(|name| name.to_string())
1150-
.collect::<Vec<_>>().join("`, `"))
1151-
).emit();
1149+
.map(|trait_item| trait_item.name().to_string())
1150+
.collect::<Vec<_>>().join("`, `")));
1151+
for trait_item in missing_items {
1152+
if let Some(span) = tcx.map.span_if_local(trait_item.def_id()) {
1153+
err.span_label(span, &format!("`{}` from trait", trait_item.name()));
1154+
} else {
1155+
err.note(&format!("`{}` from trait: `{}`",
1156+
trait_item.name(),
1157+
signature(trait_item)));
1158+
}
1159+
}
1160+
err.emit();
11521161
}
11531162

11541163
if !invalidated_items.is_empty() {
@@ -1163,6 +1172,14 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
11631172
}
11641173
}
11651174

1175+
fn signature<'a, 'tcx>(item: &ty::ImplOrTraitItem) -> String {
1176+
match *item {
1177+
ty::MethodTraitItem(ref item) => format!("{}", item.fty.sig.0),
1178+
ty::TypeTraitItem(ref item) => format!("type {};", item.name.to_string()),
1179+
ty::ConstTraitItem(ref item) => format!("const {}: {:?};", item.name.to_string(), item.ty),
1180+
}
1181+
}
1182+
11661183
/// Checks a constant with a given type.
11671184
fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
11681185
expr: &'tcx hir::Expr,
Lines changed: 10 additions & 0 deletions
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

Lines changed: 17 additions & 0 deletions
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

Lines changed: 19 additions & 0 deletions
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 renamed to src/test/ui/span/E0046.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 11 additions & 0 deletions
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 renamed to src/test/ui/span/impl-wrong-item-for-trait.rs

Lines changed: 6 additions & 3 deletions
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 () {}
Lines changed: 64 additions & 0 deletions
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 renamed to src/test/ui/span/issue-23729.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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 renamed to src/test/ui/span/issue-23827.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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 renamed to src/test/ui/span/issue-24356.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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)