diff options
| author | bors <bors@rust-lang.org> | 2017-06-04 20:16:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-06-04 20:16:09 +0000 |
| commit | 0418fa9d382a47d782cc1e195c14573be9c32095 (patch) | |
| tree | 20337e568c7a68a788142cf3653ea1894c1de5ed | |
| parent | 9a4e13f5c43a6eaf97ab3b62c5f1d2d9ab4f3d6e (diff) | |
| parent | e324919ec57954adaa49884e5894bc7d615d413e (diff) | |
| download | rust-0418fa9d382a47d782cc1e195c14573be9c32095.tar.gz rust-0418fa9d382a47d782cc1e195c14573be9c32095.zip | |
Auto merge of #42362 - estebank:type, r=arielb1
Show trait method signature when impl differs
When the trait's span is available, it is already being used, add a
`note` for the cases where the span isn't available:
<pre>
error[E0053]: <b>method `fmt` has an incompatible type for trait</b>
--> $DIR/trait_type.rs:17:4
|
17 | fn fmt(&self, x: &str) -> () { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
|
= note: expected type `<b>fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error></b>`
found type `<b>fn(&MyType, &str)</b>`
error[E0050]: <b>method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2</b>
--> $DIR/trait_type.rs:21:11
|
21 | fn fmt(&self) -> () { }
| ^^^^^ expected 2 parameters, found 1
|
= note: `fmt` from trait: `<b>fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error></b>`
error[E0186]: <b>method `fmt` has a `&self` declaration in the trait, but not in the impl</b>
--> $DIR/trait_type.rs:25:4
|
25 | fn fmt() -> () { }
| ^^^^^^^^^^^^^^^^^^ expected `&self` in impl
|
= note: `fmt` from trait: `<b>fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error></b>`
error[E0046]: <b>not all trait items implemented, missing: `fmt`</b>
--> $DIR/trait_type.rs:28:1
|
28 | impl std::fmt::Display for MyType4 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation
|
= note: `fmt` from trait: `<b>fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error></b>`
</code></pre>
Fix #28011.
| -rw-r--r-- | src/librustc/ty/mod.rs | 16 | ||||
| -rw-r--r-- | src/librustc_errors/diagnostic.rs | 8 | ||||
| -rw-r--r-- | src/librustc_typeck/check/compare_method.rs | 6 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/impl-trait/trait_type.rs | 30 | ||||
| -rw-r--r-- | src/test/ui/impl-trait/trait_type.stderr | 35 |
6 files changed, 97 insertions, 15 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e4e1ebe1882..653021119aa 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -198,6 +198,22 @@ impl AssociatedItem { AssociatedKind::Method => !self.method_has_self_argument, } } + + pub fn signature<'a, 'tcx>(&self, tcx: &TyCtxt<'a, 'tcx, 'tcx>) -> String { + match self.kind { + ty::AssociatedKind::Method => { + // We skip the binder here because the binder would deanonymize all + // late-bound regions, and we don't want method signatures to show up + // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound + // regions just fine, showing `fn(&MyType)`. + format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder()) + } + ty::AssociatedKind::Type => format!("type {};", self.name.to_string()), + ty::AssociatedKind::Const => { + format!("const {}: {:?};", self.name.to_string(), tcx.type_of(self.def_id)) + } + } + } } #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 861880aa265..7a64cdeee65 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -157,6 +157,14 @@ impl Diagnostic { self } + pub fn note_trait_signature(&mut self, name: String, signature: String) -> &mut Self { + self.highlighted_note(vec![ + (format!("`{}` from trait: `", name), Style::NoStyle), + (signature, Style::Highlight), + ("`".to_string(), Style::NoStyle)]); + self + } + pub fn note(&mut self, msg: &str) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new(), None); self diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 7633be24477..8b76431fd2e 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -550,6 +550,9 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, format!("expected `{}` in impl", self_descr)); if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) { err.span_label(span, format!("`{}` used in trait", self_descr)); + } else { + err.note_trait_signature(trait_m.name.to_string(), + trait_m.signature(&tcx)); } err.emit(); return Err(ErrorReported); @@ -697,6 +700,9 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { format!("{} parameter", trait_number_args) })); + } else { + err.note_trait_signature(trait_m.name.to_string(), + trait_m.signature(&tcx)); } err.span_label(impl_span, format!("expected {}, found {}", diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ccaf9b84a45..c3bce804879 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1348,18 +1348,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - let signature = |item: &ty::AssociatedItem| { - match item.kind { - ty::AssociatedKind::Method => { - format!("{}", tcx.type_of(item.def_id).fn_sig().0) - } - ty::AssociatedKind::Type => format!("type {};", item.name.to_string()), - ty::AssociatedKind::Const => { - format!("const {}: {:?};", item.name.to_string(), tcx.type_of(item.def_id)) - } - } - }; - if !missing_items.is_empty() { let mut err = struct_span_err!(tcx.sess, impl_span, E0046, "not all trait items implemented, missing: `{}`", @@ -1374,9 +1362,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(span) = tcx.hir.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.note_trait_signature(trait_item.name.to_string(), + trait_item.signature(&tcx)); } } err.emit(); diff --git a/src/test/ui/impl-trait/trait_type.rs b/src/test/ui/impl-trait/trait_type.rs new file mode 100644 index 00000000000..3507dcfbe17 --- /dev/null +++ b/src/test/ui/impl-trait/trait_type.rs @@ -0,0 +1,30 @@ +// Copyright 2017 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. + +struct MyType; +struct MyType2; +struct MyType3; +struct MyType4; + +impl std::fmt::Display for MyType { + fn fmt(&self, x: &str) -> () { } +} + +impl std::fmt::Display for MyType2 { + fn fmt(&self) -> () { } +} + +impl std::fmt::Display for MyType3 { + fn fmt() -> () { } +} + +impl std::fmt::Display for MyType4 {} + +fn main() {} diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr new file mode 100644 index 00000000000..cc7a7153a38 --- /dev/null +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -0,0 +1,35 @@ +error[E0053]: method `fmt` has an incompatible type for trait + --> $DIR/trait_type.rs:17:4 + | +17 | fn fmt(&self, x: &str) -> () { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` + found type `fn(&MyType, &str)` + +error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2 + --> $DIR/trait_type.rs:21:11 + | +21 | fn fmt(&self) -> () { } + | ^^^^^ expected 2 parameters, found 1 + | + = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` + +error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in the impl + --> $DIR/trait_type.rs:25:4 + | +25 | fn fmt() -> () { } + | ^^^^^^^^^^^^^^^^^^ expected `&self` in impl + | + = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` + +error[E0046]: not all trait items implemented, missing: `fmt` + --> $DIR/trait_type.rs:28:1 + | +28 | impl std::fmt::Display for MyType4 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation + | + = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>` + +error: aborting due to previous error(s) + |
