Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use multiline note for trait suggestion
  • Loading branch information
estebank committed Jun 2, 2017
1 parent 4ed2eda commit e935acf
Show file tree
Hide file tree
Showing 10 changed files with 401 additions and 167 deletions.
57 changes: 28 additions & 29 deletions src/librustc_typeck/check/method/suggest.rs
Expand Up @@ -228,7 +228,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
macro_rules! report_function {
($span:expr, $name:expr) => {
err.note(&format!("{} is a function, perhaps you wish to call it",
$name));
$name));
}
}

Expand Down Expand Up @@ -315,9 +315,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut candidates = valid_out_of_scope_traits;
candidates.sort();
candidates.dedup();
let msg = format!("items from traits can only be used if the trait is in scope; the \
following {traits_are} implemented but not in scope, perhaps add \
a `use` for {one_of_them}:",
let mut msg = format!("items from traits can only be used if the trait is in scope; \
the following {traits_are} implemented but not in scope, \
perhaps add a `use` for {one_of_them}:",
traits_are = if candidates.len() == 1 {
"trait is"
} else {
Expand All @@ -329,17 +329,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
"one of them"
});

err.help(&msg[..]);

let limit = if candidates.len() == 5 { 5 } else { 4 };
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
err.help(&format!("candidate #{}: `use {};`",
i + 1,
self.tcx.item_path_str(*trait_did)));
msg.push_str(&format!("\ncandidate #{}: `use {};`",
i + 1,
self.tcx.item_path_str(*trait_did)));
}
if candidates.len() > limit {
err.note(&format!("and {} others", candidates.len() - limit));
msg.push_str(&format!("\nand {} others", candidates.len() - limit));
}
err.help(&msg[..]);

return;
}

Expand Down Expand Up @@ -369,28 +369,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// FIXME #21673 this help message could be tuned to the case
// of a type parameter: suggest adding a trait bound rather
// than implementing.
let msg = format!("items from traits can only be used if the trait is implemented \
and in scope; the following {traits_define} an item `{name}`, \
perhaps you need to implement {one_of_them}:",
traits_define = if candidates.len() == 1 {
"trait defines"
} else {
"traits define"
},
one_of_them = if candidates.len() == 1 {
"it"
} else {
"one of them"
},
name = item_name);

err.help(&msg[..]);
let mut msg = format!("items from traits can only be used if the trait is implemented \
and in scope; the following {traits_define} an item `{name}`, \
perhaps you need to implement {one_of_them}:",
traits_define = if candidates.len() == 1 {
"trait defines"
} else {
"traits define"
},
one_of_them = if candidates.len() == 1 {
"it"
} else {
"one of them"
},
name = item_name);

for (i, trait_info) in candidates.iter().enumerate() {
err.help(&format!("candidate #{}: `{}`",
i + 1,
self.tcx.item_path_str(trait_info.def_id)));
msg.push_str(&format!("\ncandidate #{}: `{}`",
i + 1,
self.tcx.item_path_str(trait_info.def_id)));
}
err.help(&msg[..]);
}
}

Expand Down
134 changes: 0 additions & 134 deletions src/test/compile-fail/no-method-suggested-traits.rs

This file was deleted.

@@ -0,0 +1,11 @@
error[E0599]: no method named `foo` found for type `Bar` in the current scope
--> $DIR/issue-21659-show-relevant-trait-impls-3.rs:30:8
|
30 | f1.foo(1usize);
| ^^^
|
= help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `foo`, perhaps you need to implement it:
candidate #1: `Foo`

error: aborting due to previous error(s)

13 changes: 13 additions & 0 deletions src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -0,0 +1,13 @@
error[E0599]: no method named `is_empty` found for type `Foo` in the current scope
--> $DIR/method-suggestion-no-duplication.rs:19:15
|
19 | foo(|s| s.is_empty());
| ^^^^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope; the following traits define an item `is_empty`, perhaps you need to implement one of them:
candidate #1: `std::iter::ExactSizeIterator`
candidate #2: `core::slice::SliceExt`
candidate #3: `core::str::StrExt`

error: aborting due to previous error(s)

133 changes: 133 additions & 0 deletions src/test/ui/impl-trait/no-method-suggested-traits.rs
@@ -0,0 +1,133 @@
// Copyright 2015 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.

// aux-build:no_method_suggested_traits.rs
extern crate no_method_suggested_traits;

struct Foo;
enum Bar { X }

mod foo {
pub trait Bar {
fn method(&self) {}

fn method2(&self) {}
}

impl Bar for u32 {}

impl Bar for char {}
}

fn main() {
// test the values themselves, and autoderef.


1u32.method();
//~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
//~| ERROR no method named
//~| HELP `use foo::Bar;`
//~| HELP `use no_method_suggested_traits::foo::PubPub;`
std::rc::Rc::new(&mut Box::new(&1u32)).method();
//~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
//~| ERROR no method named
//~| HELP `use foo::Bar;`
//~| HELP `use no_method_suggested_traits::foo::PubPub;`

'a'.method();
//~^ ERROR no method named
//~| HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
//~| HELP `use foo::Bar;`
std::rc::Rc::new(&mut Box::new(&'a')).method();
//~^ ERROR no method named
//~| HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
//~| HELP `use foo::Bar;`

1i32.method();
//~^ ERROR no method named
//~| HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
//~| HELP `use no_method_suggested_traits::foo::PubPub;`
std::rc::Rc::new(&mut Box::new(&1i32)).method();
//~^ ERROR no method named
//~| HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
//~| HELP `use no_method_suggested_traits::foo::PubPub;`

Foo.method();
//~^ ERROR no method named
//~| HELP following traits define an item `method`, perhaps you need to implement one of them
//~| HELP `foo::Bar`
//~| HELP `no_method_suggested_traits::foo::PubPub`
//~| HELP `no_method_suggested_traits::Reexported`
//~| HELP `no_method_suggested_traits::bar::PubPriv`
//~| HELP `no_method_suggested_traits::qux::PrivPub`
//~| HELP `no_method_suggested_traits::quz::PrivPriv`
std::rc::Rc::new(&mut Box::new(&Foo)).method();
//~^ ERROR no method named
//~| HELP following traits define an item `method`, perhaps you need to implement one of them
//~| HELP `foo::Bar`
//~| HELP `no_method_suggested_traits::foo::PubPub`
//~| HELP `no_method_suggested_traits::Reexported`
//~| HELP `no_method_suggested_traits::bar::PubPriv`
//~| HELP `no_method_suggested_traits::qux::PrivPub`
//~| HELP `no_method_suggested_traits::quz::PrivPriv`

1u64.method2();
//~^ ERROR no method named
//~| HELP the following trait defines an item `method2`, perhaps you need to implement it
//~| HELP `foo::Bar`
std::rc::Rc::new(&mut Box::new(&1u64)).method2();
//~^ ERROR no method named
//~| HELP the following trait defines an item `method2`, perhaps you need to implement it
//~| HELP `foo::Bar`

no_method_suggested_traits::Foo.method2();
//~^ ERROR no method named
//~| HELP following trait defines an item `method2`, perhaps you need to implement it
//~| HELP `foo::Bar`
std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
//~^ ERROR no method named
//~| HELP following trait defines an item `method2`, perhaps you need to implement it
//~| HELP `foo::Bar`
no_method_suggested_traits::Bar::X.method2();
//~^ ERROR no method named
//~| HELP following trait defines an item `method2`, perhaps you need to implement it
//~| HELP `foo::Bar`
std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
//~^ ERROR no method named
//~| HELP following trait defines an item `method2`, perhaps you need to implement it
//~| HELP `foo::Bar`

Foo.method3();
//~^ ERROR no method named
//~| HELP following trait defines an item `method3`, perhaps you need to implement it
//~| HELP `no_method_suggested_traits::foo::PubPub`
std::rc::Rc::new(&mut Box::new(&Foo)).method3();
//~^ ERROR no method named
//~| HELP following trait defines an item `method3`, perhaps you need to implement it
//~| HELP `no_method_suggested_traits::foo::PubPub`
Bar::X.method3();
//~^ ERROR no method named
//~| HELP following trait defines an item `method3`, perhaps you need to implement it
//~| HELP `no_method_suggested_traits::foo::PubPub`
std::rc::Rc::new(&mut Box::new(&Bar::X)).method3();
//~^ ERROR no method named
//~| HELP following trait defines an item `method3`, perhaps you need to implement it
//~| HELP `no_method_suggested_traits::foo::PubPub`

// should have no help:
1_usize.method3(); //~ ERROR no method named
std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); //~ ERROR no method named
no_method_suggested_traits::Foo.method3(); //~ ERROR no method named
std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
//~^ ERROR no method named
no_method_suggested_traits::Bar::X.method3(); //~ ERROR no method named
std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
//~^ ERROR no method named
}

0 comments on commit e935acf

Please sign in to comment.