mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 21:42:44 +00:00
Adds hint if a trait fails to resolve and a newly added one in Edition 2021 is suggested
This commit is contained in:
parent
e91d5ca197
commit
958e645946
@ -66,6 +66,8 @@ crate struct ImportSuggestion {
|
|||||||
pub descr: &'static str,
|
pub descr: &'static str,
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
pub accessible: bool,
|
pub accessible: bool,
|
||||||
|
/// An extra note that should be issued if this item is suggested
|
||||||
|
pub note: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adjust the impl span so that just the `impl` keyword is taken by removing
|
/// Adjust the impl span so that just the `impl` keyword is taken by removing
|
||||||
@ -872,11 +874,38 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
|
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
|
||||||
|
// See if we're recommending TryFrom, TryInto, or FromIterator and add
|
||||||
|
// a note about editions
|
||||||
|
let note = if let Some(did) = did {
|
||||||
|
let requires_note = !did.is_local()
|
||||||
|
&& this.cstore().item_attrs(did, this.session).iter().any(
|
||||||
|
|attr| {
|
||||||
|
if attr.has_name(sym::rustc_diagnostic_item) {
|
||||||
|
[sym::TryInto, sym::TryFrom, sym::FromIterator]
|
||||||
|
.map(|x| Some(x))
|
||||||
|
.contains(&attr.value_str())
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
requires_note.then(|| {
|
||||||
|
format!(
|
||||||
|
"'{}' is included in the prelude starting in Edition 2021",
|
||||||
|
path_names_to_string(&path)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
candidates.push(ImportSuggestion {
|
candidates.push(ImportSuggestion {
|
||||||
did,
|
did,
|
||||||
descr: res.descr(),
|
descr: res.descr(),
|
||||||
path,
|
path,
|
||||||
accessible: child_accessible,
|
accessible: child_accessible,
|
||||||
|
note,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1764,12 +1793,14 @@ crate fn show_candidates(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
|
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
|
||||||
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
|
Vec::new();
|
||||||
|
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
|
||||||
|
Vec::new();
|
||||||
|
|
||||||
candidates.iter().for_each(|c| {
|
candidates.iter().for_each(|c| {
|
||||||
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
|
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
|
||||||
.push((path_names_to_string(&c.path), c.descr, c.did))
|
.push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
|
||||||
});
|
});
|
||||||
|
|
||||||
// we want consistent results across executions, but candidates are produced
|
// we want consistent results across executions, but candidates are produced
|
||||||
@ -1792,6 +1823,11 @@ crate fn show_candidates(
|
|||||||
let instead = if instead { " instead" } else { "" };
|
let instead = if instead { " instead" } else { "" };
|
||||||
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
|
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
|
||||||
|
|
||||||
|
// Issue notes
|
||||||
|
for note in accessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
|
||||||
|
err.note(note);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(span) = use_placement_span {
|
if let Some(span) = use_placement_span {
|
||||||
for candidate in &mut accessible_path_strings {
|
for candidate in &mut accessible_path_strings {
|
||||||
// produce an additional newline to separate the new use statement
|
// produce an additional newline to separate the new use statement
|
||||||
@ -1820,7 +1856,7 @@ crate fn show_candidates(
|
|||||||
assert!(!inaccessible_path_strings.is_empty());
|
assert!(!inaccessible_path_strings.is_empty());
|
||||||
|
|
||||||
if inaccessible_path_strings.len() == 1 {
|
if inaccessible_path_strings.len() == 1 {
|
||||||
let (name, descr, def_id) = &inaccessible_path_strings[0];
|
let (name, descr, def_id, note) = &inaccessible_path_strings[0];
|
||||||
let msg = format!("{} `{}` exists but is inaccessible", descr, name);
|
let msg = format!("{} `{}` exists but is inaccessible", descr, name);
|
||||||
|
|
||||||
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
|
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
|
||||||
@ -1832,12 +1868,15 @@ crate fn show_candidates(
|
|||||||
} else {
|
} else {
|
||||||
err.note(&msg);
|
err.note(&msg);
|
||||||
}
|
}
|
||||||
|
if let Some(note) = (*note).as_deref() {
|
||||||
|
err.note(note);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let (_, descr_first, _) = &inaccessible_path_strings[0];
|
let (_, descr_first, _, _) = &inaccessible_path_strings[0];
|
||||||
let descr = if inaccessible_path_strings
|
let descr = if inaccessible_path_strings
|
||||||
.iter()
|
.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.all(|(_, descr, _)| descr == descr_first)
|
.all(|(_, descr, _, _)| descr == descr_first)
|
||||||
{
|
{
|
||||||
descr_first.to_string()
|
descr_first.to_string()
|
||||||
} else {
|
} else {
|
||||||
@ -1848,7 +1887,7 @@ crate fn show_candidates(
|
|||||||
let mut has_colon = false;
|
let mut has_colon = false;
|
||||||
|
|
||||||
let mut spans = Vec::new();
|
let mut spans = Vec::new();
|
||||||
for (name, _, def_id) in &inaccessible_path_strings {
|
for (name, _, def_id, _) in &inaccessible_path_strings {
|
||||||
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
|
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
|
||||||
let span = definitions.def_span(local_def_id);
|
let span = definitions.def_span(local_def_id);
|
||||||
let span = session.source_map().guess_head_span(span);
|
let span = session.source_map().guess_head_span(span);
|
||||||
@ -1868,6 +1907,10 @@ crate fn show_candidates(
|
|||||||
multi_span.push_span_label(span, format!("`{}`: not accessible", name));
|
multi_span.push_span_label(span, format!("`{}`: not accessible", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for note in inaccessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
|
||||||
|
err.note(note);
|
||||||
|
}
|
||||||
|
|
||||||
err.span_note(multi_span, &msg);
|
err.span_note(multi_span, &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1502,6 +1502,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
|||||||
descr: "module",
|
descr: "module",
|
||||||
path,
|
path,
|
||||||
accessible: true,
|
accessible: true,
|
||||||
|
note: None,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,11 +1,31 @@
|
|||||||
// Make sure that calling `.try_into()` in pre-2021 mentions Edition 2021 change
|
// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions
|
||||||
|
// Edition 2021 change
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
fn test() {
|
fn test() {
|
||||||
let i: i16 = 0_i32.try_into().unwrap();
|
let _i: i16 = 0_i32.try_into().unwrap();
|
||||||
//~^ ERROR no method named `try_into` found for type `i32` in the current scope
|
//~^ ERROR no method named `try_into` found for type `i32` in the current scope
|
||||||
//~| NOTE method not found in `i32`
|
//~| NOTE method not found in `i32`
|
||||||
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
|
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
|
||||||
|
|
||||||
|
let _i: i16 = TryFrom::try_from(0_i32).unwrap();
|
||||||
|
//~^ ERROR failed to resolve: use of undeclared type
|
||||||
|
//~| NOTE not found in this scope
|
||||||
|
//~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
|
||||||
|
//~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
|
||||||
|
|
||||||
|
let _i: i16 = TryInto::try_into(0_i32).unwrap();
|
||||||
|
//~^ ERROR failed to resolve: use of undeclared type
|
||||||
|
//~| NOTE not found in this scope
|
||||||
|
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
|
||||||
|
//~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
|
||||||
|
|
||||||
|
let _v: Vec<_> = FromIterator::from_iter(&[1]);
|
||||||
|
//~^ ERROR failed to resolve: use of undeclared type
|
||||||
|
//~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
|
||||||
|
//~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
@ -1,8 +1,62 @@
|
|||||||
error[E0599]: no method named `try_into` found for type `i32` in the current scope
|
error[E0433]: failed to resolve: use of undeclared type `TryFrom`
|
||||||
--> $DIR/suggest-tryinto-edition-change.rs:5:24
|
--> $DIR/suggest-tryinto-edition-change.rs:11:19
|
||||||
|
|
|
|
||||||
LL | let i: i16 = 0_i32.try_into().unwrap();
|
LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap();
|
||||||
| ^^^^^^^^ method not found in `i32`
|
| ^^^^^^^ not found in this scope
|
||||||
|
|
|
||||||
|
= note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
|
||||||
|
= note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
|
||||||
|
help: consider importing one of these items
|
||||||
|
|
|
||||||
|
LL | use std::convert::TryFrom;
|
||||||
|
|
|
||||||
|
LL | use core::convert::TryFrom;
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0433]: failed to resolve: use of undeclared type `TryInto`
|
||||||
|
--> $DIR/suggest-tryinto-edition-change.rs:17:19
|
||||||
|
|
|
||||||
|
LL | let _i: i16 = TryInto::try_into(0_i32).unwrap();
|
||||||
|
| ^^^^^^^ not found in this scope
|
||||||
|
|
|
||||||
|
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
|
||||||
|
= note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021
|
||||||
|
help: consider importing one of these items
|
||||||
|
|
|
||||||
|
LL | use std::convert::TryInto;
|
||||||
|
|
|
||||||
|
LL | use core::convert::TryInto;
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0433]: failed to resolve: use of undeclared type `FromIterator`
|
||||||
|
--> $DIR/suggest-tryinto-edition-change.rs:23:22
|
||||||
|
|
|
||||||
|
LL | let _v: Vec<_> = FromIterator::from_iter(&[1]);
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub trait IntoIterator {
|
||||||
|
| ---------------------- similarly named trait `IntoIterator` defined here
|
||||||
|
|
|
||||||
|
= note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
|
||||||
|
= note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
|
||||||
|
help: a trait with a similar name exists
|
||||||
|
|
|
||||||
|
LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]);
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
help: consider importing one of these items
|
||||||
|
|
|
||||||
|
LL | use std::iter::FromIterator;
|
||||||
|
|
|
||||||
|
LL | use core::iter::FromIterator;
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0599]: no method named `try_into` found for type `i32` in the current scope
|
||||||
|
--> $DIR/suggest-tryinto-edition-change.rs:6:25
|
||||||
|
|
|
||||||
|
LL | let _i: i16 = 0_i32.try_into().unwrap();
|
||||||
|
| ^^^^^^^^ method not found in `i32`
|
||||||
|
|
|
|
||||||
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
@ -16,6 +70,7 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
|
|||||||
LL | use std::convert::TryInto;
|
LL | use std::convert::TryInto;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0599`.
|
Some errors have detailed explanations: E0433, E0599.
|
||||||
|
For more information about an error, try `rustc --explain E0433`.
|
||||||
|
Loading…
Reference in New Issue
Block a user