Rollup merge of #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 #24626. Follow up to PR #36371. If PR #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.
This commit is contained in:
commit
7f2853fda3
@ -1131,7 +1131,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
if !is_implemented {
|
||||
if !is_provided {
|
||||
missing_items.push(trait_item.name());
|
||||
missing_items.push(trait_item);
|
||||
} else if associated_type_overridden {
|
||||
invalidated_items.push(trait_item.name());
|
||||
}
|
||||
@ -1139,16 +1139,25 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
if !missing_items.is_empty() {
|
||||
struct_span_err!(tcx.sess, impl_span, E0046,
|
||||
let mut err = struct_span_err!(tcx.sess, impl_span, E0046,
|
||||
"not all trait items implemented, missing: `{}`",
|
||||
missing_items.iter()
|
||||
.map(|name| name.to_string())
|
||||
.collect::<Vec<_>>().join("`, `"))
|
||||
.span_label(impl_span, &format!("missing `{}` in implementation",
|
||||
.map(|trait_item| trait_item.name().to_string())
|
||||
.collect::<Vec<_>>().join("`, `"));
|
||||
err.span_label(impl_span, &format!("missing `{}` in implementation",
|
||||
missing_items.iter()
|
||||
.map(|name| name.to_string())
|
||||
.collect::<Vec<_>>().join("`, `"))
|
||||
).emit();
|
||||
.map(|trait_item| trait_item.name().to_string())
|
||||
.collect::<Vec<_>>().join("`, `")));
|
||||
for trait_item in missing_items {
|
||||
if let Some(span) = tcx.map.span_if_local(trait_item.def_id()) {
|
||||
err.span_label(span, &format!("`{}` from trait", trait_item.name()));
|
||||
} else {
|
||||
err.note(&format!("`{}` from trait: `{}`",
|
||||
trait_item.name(),
|
||||
signature(trait_item)));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
if !invalidated_items.is_empty() {
|
||||
@ -1163,6 +1172,14 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn signature<'a, 'tcx>(item: &ty::ImplOrTraitItem) -> String {
|
||||
match *item {
|
||||
ty::MethodTraitItem(ref item) => format!("{}", item.fty.sig.0),
|
||||
ty::TypeTraitItem(ref item) => format!("type {};", item.name.to_string()),
|
||||
ty::ConstTraitItem(ref item) => format!("const {}: {:?};", item.name.to_string(), item.ty),
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks a constant with a given type.
|
||||
fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
|
10
src/test/run-make/missing-items/Makefile
Normal file
10
src/test/run-make/missing-items/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) m1.rs -C prefer-dynamic
|
||||
$(RUSTC) m2.rs 2>&1 | grep "error\[E0046\]: not all trait items implemented, missing: .*"
|
||||
$(RUSTC) m2.rs 2>&1 | grep " --> m2.rs:18:1"
|
||||
$(RUSTC) m2.rs 2>&1 | grep " | ^ missing .CONSTANT., .Type., .method. in implementation"
|
||||
$(RUSTC) m2.rs 2>&1 | grep " = note: .CONSTANT. from trait: .const CONSTANT: u32;."
|
||||
$(RUSTC) m2.rs 2>&1 | grep " = note: .Type. from trait: .type Type;."
|
||||
$(RUSTC) m2.rs 2>&1 | grep " = note: .method. from trait: .fn(&Self, std::string::String) -> <Self as m1::X>::Type."
|
17
src/test/run-make/missing-items/m1.rs
Normal file
17
src/test/run-make/missing-items/m1.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_consts)]
|
||||
#![crate_type = "dylib"]
|
||||
pub trait X {
|
||||
const CONSTANT: u32;
|
||||
type Type;
|
||||
fn method(&self, s: String) -> Self::Type;
|
||||
}
|
19
src/test/run-make/missing-items/m2.rs
Normal file
19
src/test/run-make/missing-items/m2.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_consts)]
|
||||
#![crate_type = "dylib"]
|
||||
extern crate m1;
|
||||
|
||||
struct X {
|
||||
}
|
||||
|
||||
impl m1::X for X {
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
|
||||
trait Foo {
|
||||
fn foo();
|
||||
//~^ NOTE `foo` from trait
|
||||
}
|
||||
|
||||
struct Bar;
|
11
src/test/ui/span/E0046.stderr
Normal file
11
src/test/ui/span/E0046.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0046]: not all trait items implemented, missing: `foo`
|
||||
--> $DIR/E0046.rs:18:1
|
||||
|
|
||||
12 | fn foo();
|
||||
| --------- `foo` from trait
|
||||
...
|
||||
18 | impl Foo for Bar {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -10,11 +10,11 @@
|
||||
|
||||
#![feature(associated_consts)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
//~^ NOTE item in trait
|
||||
//~| NOTE item in trait
|
||||
const MY_CONST: u32; //~ NOTE item in trait
|
||||
const MY_CONST: u32;
|
||||
}
|
||||
|
||||
pub struct FooConstForMethod;
|
||||
@ -50,4 +50,7 @@ impl Foo for FooTypeForMethod {
|
||||
const MY_CONST: u32 = 1;
|
||||
}
|
||||
|
||||
impl Debug for FooTypeForMethod {
|
||||
}
|
||||
|
||||
fn main () {}
|
64
src/test/ui/span/impl-wrong-item-for-trait.stderr
Normal file
64
src/test/ui/span/impl-wrong-item-for-trait.stderr
Normal file
@ -0,0 +1,64 @@
|
||||
error[E0323]: item `bar` is an associated const, which doesn't match its trait `<FooConstForMethod as Foo>`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:25:5
|
||||
|
|
||||
16 | fn bar(&self);
|
||||
| -------------- item in trait
|
||||
...
|
||||
25 | const bar: u64 = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^ does not match trait
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `bar`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:22:1
|
||||
|
|
||||
16 | fn bar(&self);
|
||||
| -------------- `bar` from trait
|
||||
...
|
||||
22 | impl Foo for FooConstForMethod {
|
||||
| ^ missing `bar` in implementation
|
||||
|
||||
error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `<FooMethodForConst as Foo>`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:37:5
|
||||
|
|
||||
17 | const MY_CONST: u32;
|
||||
| -------------------- item in trait
|
||||
...
|
||||
37 | fn MY_CONST() {}
|
||||
| ^^^^^^^^^^^^^^^^ does not match trait
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `MY_CONST`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:33:1
|
||||
|
|
||||
17 | const MY_CONST: u32;
|
||||
| -------------------- `MY_CONST` from trait
|
||||
...
|
||||
33 | impl Foo for FooMethodForConst {
|
||||
| ^ missing `MY_CONST` in implementation
|
||||
|
||||
error[E0325]: item `bar` is an associated type, which doesn't match its trait `<FooTypeForMethod as Foo>`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:47:5
|
||||
|
|
||||
16 | fn bar(&self);
|
||||
| -------------- item in trait
|
||||
...
|
||||
47 | type bar = u64;
|
||||
| ^^^^^^^^^^^^^^^ does not match trait
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `bar`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:44:1
|
||||
|
|
||||
16 | fn bar(&self);
|
||||
| -------------- `bar` from trait
|
||||
...
|
||||
44 | impl Foo for FooTypeForMethod {
|
||||
| ^ missing `bar` in implementation
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `fmt`
|
||||
--> $DIR/impl-wrong-item-for-trait.rs:53:1
|
||||
|
|
||||
53 | impl Debug for FooTypeForMethod {
|
||||
| ^ missing `fmt` in implementation
|
||||
|
|
||||
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
@ -20,6 +20,7 @@ fn main() {
|
||||
impl Iterator for Recurrence {
|
||||
//~^ ERROR E0046
|
||||
//~| NOTE missing `Item` in implementation
|
||||
//~| NOTE `Item` from trait: `type Item;`
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<u64> {
|
||||
if self.pos < 2 {
|
10
src/test/ui/span/issue-23729.stderr
Normal file
10
src/test/ui/span/issue-23729.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error[E0046]: not all trait items implemented, missing: `Item`
|
||||
--> $DIR/issue-23729.rs:20:9
|
||||
|
|
||||
20 | impl Iterator for Recurrence {
|
||||
| ^ missing `Item` in implementation
|
||||
|
|
||||
= note: `Item` from trait: `type Item;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -36,6 +36,7 @@ impl<C: Component> FnMut<(C,)> for Prototype {
|
||||
impl<C: Component> FnOnce<(C,)> for Prototype {
|
||||
//~^ ERROR E0046
|
||||
//~| NOTE missing `Output` in implementation
|
||||
//~| NOTE `Output` from trait: `type Output;`
|
||||
extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype {
|
||||
Fn::call(&self, (comp,))
|
||||
}
|
10
src/test/ui/span/issue-23827.stderr
Normal file
10
src/test/ui/span/issue-23827.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error[E0046]: not all trait items implemented, missing: `Output`
|
||||
--> $DIR/issue-23827.rs:36:1
|
||||
|
|
||||
36 | impl<C: Component> FnOnce<(C,)> for Prototype {
|
||||
| ^ missing `Output` in implementation
|
||||
|
|
||||
= note: `Output` from trait: `type Output;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -30,6 +30,7 @@ fn main() {
|
||||
impl Deref for Thing {
|
||||
//~^ ERROR E0046
|
||||
//~| NOTE missing `Target` in implementation
|
||||
//~| NOTE `Target` from trait: `type Target;`
|
||||
fn deref(&self) -> i8 { self.0 }
|
||||
}
|
||||
|
10
src/test/ui/span/issue-24356.stderr
Normal file
10
src/test/ui/span/issue-24356.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error[E0046]: not all trait items implemented, missing: `Target`
|
||||
--> $DIR/issue-24356.rs:30:9
|
||||
|
|
||||
30 | impl Deref for Thing {
|
||||
| ^ missing `Target` in implementation
|
||||
|
|
||||
= note: `Target` from trait: `type Target;`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user