From aeb765b299640ee0674d2c01df600c296af7d691 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 26 Apr 2022 19:59:50 -0700 Subject: [PATCH 1/2] better enum suggestions --- .../rustc_typeck/src/check/method/suggest.rs | 215 +++++++++++++----- .../ui/suggestions/enum-method-probe.fixed | 42 ++++ src/test/ui/suggestions/enum-method-probe.rs | 42 ++++ .../ui/suggestions/enum-method-probe.stderr | 67 ++++++ 4 files changed, 314 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/suggestions/enum-method-probe.fixed create mode 100644 src/test/ui/suggestions/enum-method-probe.rs create mode 100644 src/test/ui/suggestions/enum-method-probe.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 4e54d554c6ec2..b5fd3eb44628c 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -978,45 +978,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { label_span_not_found(&mut err); } - if let SelfSource::MethodCall(expr) = source - && let Some((fields, substs)) = self.get_field_candidates(span, actual) - { - let call_expr = - self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); - for candidate_field in fields.iter() { - if let Some(field_path) = self.check_for_nested_field_satisfying( - span, - &|_, field_ty| { - self.lookup_probe( - span, - item_name, - field_ty, - call_expr, - ProbeScope::AllTraits, - ) - .is_ok() - }, - candidate_field, - substs, - vec![], - self.tcx.parent_module(expr.hir_id).to_def_id(), - ) { - let field_path_str = field_path - .iter() - .map(|id| id.name.to_ident_string()) - .collect::>() - .join("."); - debug!("field_path_str: {:?}", field_path_str); + self.check_for_field_method(&mut err, source, span, actual, item_name); - err.span_suggestion_verbose( - item_name.span.shrink_to_lo(), - "one of the expressions' fields has a method of the same name", - format!("{field_path_str}."), - Applicability::MaybeIncorrect, - ); - } - } - } + self.check_for_unwrap_self(&mut err, source, span, actual, item_name); bound_spans.sort(); bound_spans.dedup(); @@ -1343,6 +1307,157 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + fn check_for_field_method( + &self, + err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + source: SelfSource<'tcx>, + span: Span, + actual: Ty<'tcx>, + item_name: Ident, + ) { + if let SelfSource::MethodCall(expr) = source + && let Some((fields, substs)) = self.get_field_candidates(span, actual) + { + let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); + for candidate_field in fields.iter() { + if let Some(field_path) = self.check_for_nested_field_satisfying( + span, + &|_, field_ty| { + self.lookup_probe( + span, + item_name, + field_ty, + call_expr, + ProbeScope::AllTraits, + ) + .is_ok() + }, + candidate_field, + substs, + vec![], + self.tcx.parent_module(expr.hir_id).to_def_id(), + ) { + let field_path_str = field_path + .iter() + .map(|id| id.name.to_ident_string()) + .collect::>() + .join("."); + debug!("field_path_str: {:?}", field_path_str); + + err.span_suggestion_verbose( + item_name.span.shrink_to_lo(), + "one of the expressions' fields has a method of the same name", + format!("{field_path_str}."), + Applicability::MaybeIncorrect, + ); + } + } + } + } + + fn check_for_unwrap_self( + &self, + err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, + source: SelfSource<'tcx>, + span: Span, + actual: Ty<'tcx>, + item_name: Ident, + ) { + let tcx = self.tcx; + let SelfSource::MethodCall(expr) = source else { return; }; + let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id)); + + let ty::Adt(kind, substs) = actual.kind() else { return; }; + if !kind.is_enum() { + return; + } + + let matching_variants: Vec<_> = kind + .variants() + .iter() + .filter_map(|variant| { + let [field] = &variant.fields[..] else { return None; }; + let field_ty = field.ty(tcx, substs); + + // Skip `_`, since that'll just lead to ambiguity. + if matches!(self.resolve_vars_if_possible(field_ty).kind(), ty::Infer(_)) { + return None; + } + + if let Ok(pick) = + self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits) + { + Some((variant, field, pick)) + } else { + None + } + }) + .collect(); + + let ret_ty_matches = |diagnostic_item| { + if let Some(ret_ty) = self + .ret_coercion + .as_ref() + .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) + && let ty::Adt(kind, _) = ret_ty.kind() + && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) + { + true + } else { + false + } + }; + + match &matching_variants[..] { + [(_, field, pick)] if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) => { + 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::Result) { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!("use the `?` operator to extract the `{self_ty}` value, propagating a `Result::Err` value to the caller"), + "?".to_owned(), + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!("consider using `Result::expect` to unwrap the `{self_ty}` value, panicking if the value is an `Err`"), + ".expect(\"REASON\")".to_owned(), + Applicability::HasPlaceholders, + ); + } + } + [(_, 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(), + Applicability::HasPlaceholders, + ); + } + } + // FIXME(compiler-errors): Support suggestions for other matching enum variants + _ => {} + } + } + pub(crate) fn note_unmet_impls_on_type( &self, err: &mut Diagnostic, @@ -1662,13 +1777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "), (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"), ] { - match self.lookup_probe( - span, - item_name, - *rcvr_ty, - rcvr, - crate::check::method::probe::ProbeScope::AllTraits, - ) { + match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) { Ok(pick) => { // If the method is defined for the receiver we have, it likely wasn't `use`d. // We point at the method, but we just skip the rest of the check for arbitrary @@ -1700,13 +1809,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"), (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"), ] { - if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe( - span, - item_name, - new_rcvr_t, - rcvr, - crate::check::method::probe::ProbeScope::AllTraits, - ) { + if let Some(new_rcvr_t) = *rcvr_ty + && let Ok(pick) = self.lookup_probe( + span, + item_name, + new_rcvr_t, + rcvr, + ProbeScope::AllTraits, + ) + { debug!("try_alt_rcvr: pick candidate {:?}", pick); let did = Some(pick.item.container.id()); // We don't want to suggest a container type when the missing diff --git a/src/test/ui/suggestions/enum-method-probe.fixed b/src/test/ui/suggestions/enum-method-probe.fixed new file mode 100644 index 0000000000000..990f7900f2232 --- /dev/null +++ b/src/test/ui/suggestions/enum-method-probe.fixed @@ -0,0 +1,42 @@ +// run-rustfix +#![allow(unused)] + +struct Foo; + +impl Foo { + fn get(&self) -> u8 { + 42 + } +} + +fn 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_plain() { + 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 an `Err` +} + +fn test_option_in_option() -> Option<()> { + let res: Option<_> = Some(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP use the `?` operator + Some(()) +} + +fn test_option_in_plain() { + let res: Option<_> = Some(Foo); + res.expect("REASON").get(); + //~^ 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` +} + +fn main() {} diff --git a/src/test/ui/suggestions/enum-method-probe.rs b/src/test/ui/suggestions/enum-method-probe.rs new file mode 100644 index 0000000000000..6270fa9fea598 --- /dev/null +++ b/src/test/ui/suggestions/enum-method-probe.rs @@ -0,0 +1,42 @@ +// run-rustfix +#![allow(unused)] + +struct Foo; + +impl Foo { + fn get(&self) -> u8 { + 42 + } +} + +fn 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_plain() { + 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 an `Err` +} + +fn test_option_in_option() -> Option<()> { + let res: Option<_> = Some(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP use the `?` operator + Some(()) +} + +fn test_option_in_plain() { + let res: Option<_> = Some(Foo); + res.get(); + //~^ 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` +} + +fn main() {} diff --git a/src/test/ui/suggestions/enum-method-probe.stderr b/src/test/ui/suggestions/enum-method-probe.stderr new file mode 100644 index 0000000000000..4af1775f66bf9 --- /dev/null +++ b/src/test/ui/suggestions/enum-method-probe.stderr @@ -0,0 +1,67 @@ +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:14:9 + | +LL | res.get(); + | ^^^ method not found in `Result` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:7: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:22:9 + | +LL | res.get(); + | ^^^ method not found in `Result` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:7:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is an `Err` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error[E0599]: no method named `get` found for enum `Option` in the current scope + --> $DIR/enum-method-probe.rs:29:9 + | +LL | res.get(); + | ^^^ method not found in `Option` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:7:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating a `None` to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Option` in the current scope + --> $DIR/enum-method-probe.rs:37:9 + | +LL | res.get(); + | ^^^ method not found in `Option` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:7:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is `None` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. From 2a61f0cc45c809c62dd149477cb2672c2022c3a4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 May 2022 14:18:03 -0700 Subject: [PATCH 2/2] address comments --- .../rustc_typeck/src/check/method/suggest.rs | 58 ++++++++----------- .../ui/suggestions/enum-method-probe.fixed | 25 ++++++-- src/test/ui/suggestions/enum-method-probe.rs | 25 ++++++-- .../ui/suggestions/enum-method-probe.stderr | 56 ++++++++++++++---- 4 files changed, 109 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b5fd3eb44628c..0e198907c8d50 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1375,22 +1375,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let matching_variants: Vec<_> = kind .variants() .iter() - .filter_map(|variant| { + .flat_map(|variant| { let [field] = &variant.fields[..] else { return None; }; let field_ty = field.ty(tcx, substs); // 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; } - if let Ok(pick) = - self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits) - { - Some((variant, field, pick)) - } else { - None - } + self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits) + .ok() + .map(|pick| (variant, field, pick)) }) .collect(); @@ -1409,45 +1405,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match &matching_variants[..] { - [(_, field, pick)] if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) => { + [(_, field, pick)] => { 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::Result) { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!("use the `?` operator to extract the `{self_ty}` value, propagating a `Result::Err` value to the caller"), - "?".to_owned(), - Applicability::MachineApplicable, - ); - } else { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - format!("consider using `Result::expect` to unwrap the `{self_ty}` value, panicking if the value is an `Err`"), - ".expect(\"REASON\")".to_owned(), - Applicability::HasPlaceholders, - ); - } - } - [(_, 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) { + 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( expr.span.shrink_to_hi(), - format!("use the `?` operator to extract the `{self_ty}` value, propagating a `None` to the caller"), + format!( + "use the `?` operator to extract the `{self_ty}` value, propagating \ + {article} `{kind}::{variant}` value 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`"), + format!( + "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \ + panicking if the value is {article} `{kind}::{variant}`" + ), ".expect(\"REASON\")".to_owned(), Applicability::HasPlaceholders, ); diff --git a/src/test/ui/suggestions/enum-method-probe.fixed b/src/test/ui/suggestions/enum-method-probe.fixed index 990f7900f2232..6499c92bc6f15 100644 --- a/src/test/ui/suggestions/enum-method-probe.fixed +++ b/src/test/ui/suggestions/enum-method-probe.fixed @@ -1,4 +1,6 @@ +// compile-flags: --edition=2021 // run-rustfix + #![allow(unused)] struct Foo; @@ -17,11 +19,26 @@ fn test_result_in_result() -> Result<(), ()> { 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); + 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` +} + +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 an `Err` + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` } fn test_option_in_option() -> Option<()> { @@ -32,11 +49,11 @@ fn test_option_in_option() -> Option<()> { Some(()) } -fn test_option_in_plain() { +fn test_option_in_unit_return() { let res: Option<_> = Some(Foo); res.expect("REASON").get(); //~^ 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() {} diff --git a/src/test/ui/suggestions/enum-method-probe.rs b/src/test/ui/suggestions/enum-method-probe.rs index 6270fa9fea598..18ea8ed8a58ff 100644 --- a/src/test/ui/suggestions/enum-method-probe.rs +++ b/src/test/ui/suggestions/enum-method-probe.rs @@ -1,4 +1,6 @@ +// compile-flags: --edition=2021 // run-rustfix + #![allow(unused)] struct Foo; @@ -17,11 +19,26 @@ fn test_result_in_result() -> Result<(), ()> { 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); + 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 an `Err` + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` } fn test_option_in_option() -> Option<()> { @@ -32,11 +49,11 @@ fn test_option_in_option() -> Option<()> { Some(()) } -fn test_option_in_plain() { +fn test_option_in_unit_return() { let res: Option<_> = Some(Foo); res.get(); //~^ 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() {} diff --git a/src/test/ui/suggestions/enum-method-probe.stderr b/src/test/ui/suggestions/enum-method-probe.stderr index 4af1775f66bf9..6ed14984f4747 100644 --- a/src/test/ui/suggestions/enum-method-probe.stderr +++ b/src/test/ui/suggestions/enum-method-probe.stderr @@ -1,11 +1,11 @@ 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(); | ^^^ method not found in `Result` | 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 { | ^^^^^^^^^^^^^^^^^^^ @@ -15,53 +15,85 @@ LL | res?.get(); | + 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(); | ^^^ method not found in `Result` | 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 { | ^^^^^^^^^^^^^^^^^^^ -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` + | +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` + | +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(); | +++++++++++++++++ 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(); | ^^^ method not found in `Option` | 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 { | ^^^^^^^^^^^^^^^^^^^ -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(); | + 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(); | ^^^ method not found in `Option` | 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 { | ^^^^^^^^^^^^^^^^^^^ -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(); | +++++++++++++++++ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0599`.