Skip to content

Commit

Permalink
Rollup merge of rust-lang#37370 - estebank:signature-2-empire-strikes…
Browse files Browse the repository at this point in the history
…-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.
  • Loading branch information
eddyb committed Nov 9, 2016
2 parents 6c7b433 + 40c2c0f commit 7f2853f
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 11 deletions.
33 changes: 25 additions & 8 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1131,24 +1131,33 @@ 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());
}
}
}

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() {
Expand All @@ -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,
Expand Down
10 changes: 10 additions & 0 deletions src/test/run-make/missing-items/Makefile
Original file line number Diff line number Diff line change
@@ -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 changes: 17 additions & 0 deletions src/test/run-make/missing-items/m1.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions src/test/run-make/missing-items/m2.rs
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

trait Foo {
fn foo();
//~^ NOTE `foo` from trait
}

struct Bar;
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/span/E0046.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -50,4 +50,7 @@ impl Foo for FooTypeForMethod {
const MY_CONST: u32 = 1;
}

impl Debug for FooTypeForMethod {
}

fn main () {}
64 changes: 64 additions & 0 deletions src/test/ui/span/impl-wrong-item-for-trait.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/span/issue-23729.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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,))
}
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/span/issue-23827.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}

Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/span/issue-24356.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 7f2853f

Please sign in to comment.