Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use multiline note for trait suggestion #42383

Merged
merged 2 commits into from
Jun 5, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 28 additions & 29 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
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.

Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should rephrase this to something more like this:

   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following traits define an item `is_empty`, perhaps you need to implement one?
           `std::iter::ExactSizeIterator`
           `core::slice::SliceExt`
           `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
Original file line number Diff line number Diff line change
@@ -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
}
Loading