address comments

This commit is contained in:
Michael Goulet 2022-05-30 14:18:03 -07:00
parent aeb765b299
commit 2a61f0cc45
4 changed files with 109 additions and 55 deletions

View File

@ -1375,22 +1375,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let matching_variants: Vec<_> = kind let matching_variants: Vec<_> = kind
.variants() .variants()
.iter() .iter()
.filter_map(|variant| { .flat_map(|variant| {
let [field] = &variant.fields[..] else { return None; }; let [field] = &variant.fields[..] else { return None; };
let field_ty = field.ty(tcx, substs); let field_ty = field.ty(tcx, substs);
// Skip `_`, since that'll just lead to ambiguity. // Skip `_`, since that'll just lead to ambiguity.
if matches!(self.resolve_vars_if_possible(field_ty).kind(), ty::Infer(_)) { if self.resolve_vars_if_possible(field_ty).is_ty_var() {
return None; return None;
} }
if let Ok(pick) =
self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits) self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
{ .ok()
Some((variant, field, pick)) .map(|pick| (variant, field, pick))
} else {
None
}
}) })
.collect(); .collect();
@ -1409,45 +1405,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
match &matching_variants[..] { match &matching_variants[..] {
[(_, field, pick)] if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) => { [(_, field, pick)] => {
let self_ty = field.ty(tcx, substs); let self_ty = field.ty(tcx, substs);
err.span_note( err.span_note(
tcx.def_span(pick.item.def_id), tcx.def_span(pick.item.def_id),
&format!("the method `{item_name}` exists on the type `{self_ty}`"), &format!("the method `{item_name}` exists on the type `{self_ty}`"),
); );
if ret_ty_matches(sym::Result) { let (article, kind, variant, question) =
if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
("a", "Result", "Err", ret_ty_matches(sym::Result))
} else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
("an", "Option", "None", ret_ty_matches(sym::Option))
} else {
return;
};
if question {
err.span_suggestion_verbose( err.span_suggestion_verbose(
expr.span.shrink_to_hi(), expr.span.shrink_to_hi(),
format!("use the `?` operator to extract the `{self_ty}` value, propagating a `Result::Err` value to the caller"), format!(
"use the `?` operator to extract the `{self_ty}` value, propagating \
{article} `{kind}::{variant}` value to the caller"
),
"?".to_owned(), "?".to_owned(),
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} else { } else {
err.span_suggestion_verbose( err.span_suggestion_verbose(
expr.span.shrink_to_hi(), expr.span.shrink_to_hi(),
format!("consider using `Result::expect` to unwrap the `{self_ty}` value, panicking if the value is an `Err`"), format!(
".expect(\"REASON\")".to_owned(), "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
Applicability::HasPlaceholders, panicking if the value is {article} `{kind}::{variant}`"
); ),
}
}
[(_, field, pick)] if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) => {
let self_ty = field.ty(tcx, substs);
err.span_note(
tcx.def_span(pick.item.def_id),
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
);
if ret_ty_matches(sym::Option) {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!("use the `?` operator to extract the `{self_ty}` value, propagating a `None` to the caller"),
"?".to_owned(),
Applicability::MachineApplicable,
);
} else {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!("consider using `Option::expect` to unwrap the `{self_ty}` value, panicking if the value is `None`"),
".expect(\"REASON\")".to_owned(), ".expect(\"REASON\")".to_owned(),
Applicability::HasPlaceholders, Applicability::HasPlaceholders,
); );

View File

@ -1,4 +1,6 @@
// compile-flags: --edition=2021
// run-rustfix // run-rustfix
#![allow(unused)] #![allow(unused)]
struct Foo; struct Foo;
@ -17,11 +19,26 @@ fn test_result_in_result() -> Result<(), ()> {
Ok(()) Ok(())
} }
fn test_result_in_plain() { async fn async_test_result_in_result() -> Result<(), ()> {
let res: Result<_, ()> = Ok(Foo);
res?.get();
//~^ ERROR no method named `get` found for enum `Result` in the current scope
//~| HELP use the `?` operator
Ok(())
}
fn test_result_in_unit_return() {
let res: Result<_, ()> = Ok(Foo); let res: Result<_, ()> = Ok(Foo);
res.expect("REASON").get(); res.expect("REASON").get();
//~^ ERROR no method named `get` found for enum `Result` in the current scope //~^ ERROR no method named `get` found for enum `Result` in the current scope
//~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is an `Err` //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
}
async fn async_test_result_in_unit_return() {
let res: Result<_, ()> = Ok(Foo);
res.expect("REASON").get();
//~^ ERROR no method named `get` found for enum `Result` in the current scope
//~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
} }
fn test_option_in_option() -> Option<()> { fn test_option_in_option() -> Option<()> {
@ -32,11 +49,11 @@ fn test_option_in_option() -> Option<()> {
Some(()) Some(())
} }
fn test_option_in_plain() { fn test_option_in_unit_return() {
let res: Option<_> = Some(Foo); let res: Option<_> = Some(Foo);
res.expect("REASON").get(); res.expect("REASON").get();
//~^ ERROR no method named `get` found for enum `Option` in the current scope //~^ ERROR no method named `get` found for enum `Option` in the current scope
//~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is `None` //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
} }
fn main() {} fn main() {}

View File

@ -1,4 +1,6 @@
// compile-flags: --edition=2021
// run-rustfix // run-rustfix
#![allow(unused)] #![allow(unused)]
struct Foo; struct Foo;
@ -17,11 +19,26 @@ fn test_result_in_result() -> Result<(), ()> {
Ok(()) Ok(())
} }
fn test_result_in_plain() { async fn async_test_result_in_result() -> Result<(), ()> {
let res: Result<_, ()> = Ok(Foo); let res: Result<_, ()> = Ok(Foo);
res.get(); res.get();
//~^ ERROR no method named `get` found for enum `Result` in the current scope //~^ ERROR no method named `get` found for enum `Result` in the current scope
//~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is an `Err` //~| HELP use the `?` operator
Ok(())
}
fn test_result_in_unit_return() {
let res: Result<_, ()> = Ok(Foo);
res.get();
//~^ ERROR no method named `get` found for enum `Result` in the current scope
//~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
}
async fn async_test_result_in_unit_return() {
let res: Result<_, ()> = Ok(Foo);
res.get();
//~^ ERROR no method named `get` found for enum `Result` in the current scope
//~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
} }
fn test_option_in_option() -> Option<()> { fn test_option_in_option() -> Option<()> {
@ -32,11 +49,11 @@ fn test_option_in_option() -> Option<()> {
Some(()) Some(())
} }
fn test_option_in_plain() { fn test_option_in_unit_return() {
let res: Option<_> = Some(Foo); let res: Option<_> = Some(Foo);
res.get(); res.get();
//~^ ERROR no method named `get` found for enum `Option` in the current scope //~^ ERROR no method named `get` found for enum `Option` in the current scope
//~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is `None` //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
} }
fn main() {} fn main() {}

View File

@ -1,11 +1,11 @@
error[E0599]: no method named `get` found for enum `Result` in the current scope error[E0599]: no method named `get` found for enum `Result` in the current scope
--> $DIR/enum-method-probe.rs:14:9 --> $DIR/enum-method-probe.rs:24:9
| |
LL | res.get(); LL | res.get();
| ^^^ method not found in `Result<Foo, ()>` | ^^^ method not found in `Result<Foo, ()>`
| |
note: the method `get` exists on the type `Foo` note: the method `get` exists on the type `Foo`
--> $DIR/enum-method-probe.rs:7:5 --> $DIR/enum-method-probe.rs:9:5
| |
LL | fn get(&self) -> u8 { LL | fn get(&self) -> u8 {
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
@ -15,53 +15,85 @@ LL | res?.get();
| + | +
error[E0599]: no method named `get` found for enum `Result` in the current scope error[E0599]: no method named `get` found for enum `Result` in the current scope
--> $DIR/enum-method-probe.rs:22:9 --> $DIR/enum-method-probe.rs:39:9
| |
LL | res.get(); LL | res.get();
| ^^^ method not found in `Result<Foo, ()>` | ^^^ method not found in `Result<Foo, ()>`
| |
note: the method `get` exists on the type `Foo` note: the method `get` exists on the type `Foo`
--> $DIR/enum-method-probe.rs:7:5 --> $DIR/enum-method-probe.rs:9:5
| |
LL | fn get(&self) -> u8 { LL | fn get(&self) -> u8 {
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is an `Err` help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
|
LL | res.expect("REASON").get();
| +++++++++++++++++
error[E0599]: no method named `get` found for enum `Result` in the current scope
--> $DIR/enum-method-probe.rs:16:9
|
LL | res.get();
| ^^^ method not found in `Result<Foo, ()>`
|
note: the method `get` exists on the type `Foo`
--> $DIR/enum-method-probe.rs:9:5
|
LL | fn get(&self) -> u8 {
| ^^^^^^^^^^^^^^^^^^^
help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller
|
LL | res?.get();
| +
error[E0599]: no method named `get` found for enum `Result` in the current scope
--> $DIR/enum-method-probe.rs:32:9
|
LL | res.get();
| ^^^ method not found in `Result<Foo, ()>`
|
note: the method `get` exists on the type `Foo`
--> $DIR/enum-method-probe.rs:9:5
|
LL | fn get(&self) -> u8 {
| ^^^^^^^^^^^^^^^^^^^
help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
| |
LL | res.expect("REASON").get(); LL | res.expect("REASON").get();
| +++++++++++++++++ | +++++++++++++++++
error[E0599]: no method named `get` found for enum `Option` in the current scope error[E0599]: no method named `get` found for enum `Option` in the current scope
--> $DIR/enum-method-probe.rs:29:9 --> $DIR/enum-method-probe.rs:46:9
| |
LL | res.get(); LL | res.get();
| ^^^ method not found in `Option<Foo>` | ^^^ method not found in `Option<Foo>`
| |
note: the method `get` exists on the type `Foo` note: the method `get` exists on the type `Foo`
--> $DIR/enum-method-probe.rs:7:5 --> $DIR/enum-method-probe.rs:9:5
| |
LL | fn get(&self) -> u8 { LL | fn get(&self) -> u8 {
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: use the `?` operator to extract the `Foo` value, propagating a `None` to the caller help: use the `?` operator to extract the `Foo` value, propagating an `Option::None` value to the caller
| |
LL | res?.get(); LL | res?.get();
| + | +
error[E0599]: no method named `get` found for enum `Option` in the current scope error[E0599]: no method named `get` found for enum `Option` in the current scope
--> $DIR/enum-method-probe.rs:37:9 --> $DIR/enum-method-probe.rs:54:9
| |
LL | res.get(); LL | res.get();
| ^^^ method not found in `Option<Foo>` | ^^^ method not found in `Option<Foo>`
| |
note: the method `get` exists on the type `Foo` note: the method `get` exists on the type `Foo`
--> $DIR/enum-method-probe.rs:7:5 --> $DIR/enum-method-probe.rs:9:5
| |
LL | fn get(&self) -> u8 { LL | fn get(&self) -> u8 {
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is `None` help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
| |
LL | res.expect("REASON").get(); LL | res.expect("REASON").get();
| +++++++++++++++++ | +++++++++++++++++
error: aborting due to 4 previous errors error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0599`. For more information about this error, try `rustc --explain E0599`.