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:
Eduard-Mihai Burtescu 2016-11-09 20:51:16 +02:00 committed by GitHub
commit 7f2853fda3
14 changed files with 186 additions and 11 deletions

View File

@ -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,

View 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."

View 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;
}

View 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 {
}

View File

@ -10,6 +10,7 @@
trait Foo {
fn foo();
//~^ NOTE `foo` from trait
}
struct Bar;

View 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

View File

@ -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 () {}

View 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

View File

@ -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 {

View 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

View File

@ -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,))
}

View 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

View File

@ -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 }
}

View 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