diff --git a/src/librustc/traits/error_reporting/on_unimplemented.rs b/src/librustc/traits/error_reporting/on_unimplemented.rs index 9f3fc91548b21..2ba12baaf6d6e 100644 --- a/src/librustc/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc/traits/error_reporting/on_unimplemented.rs @@ -59,31 +59,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> { let hir = &self.tcx.hir(); let node = hir.find(hir_id)?; - if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node { - self.describe_generator(*body_id).or_else(|| { + match &node { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => { + self.describe_generator(*body_id).or_else(|| { + Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header { + "an async function" + } else { + "a function" + }) + }) + } + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)), + .. + }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")), + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Method(sig, body_id), + .. + }) => self.describe_generator(*body_id).or_else(|| { Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header { - "an async function" + "an async method" } else { - "a function" + "a method" }) - }) - } else if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability), - .. - }) = &node - { - self.describe_generator(*body_id).or_else(|| { + }), + hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability), + .. + }) => self.describe_generator(*body_id).or_else(|| { Some(if gen_movability.is_some() { "an async closure" } else { "a closure" }) - }) - } else if let hir::Node::Expr(hir::Expr { .. }) = &node { - let parent_hid = hir.get_parent_node(hir_id); - if parent_hid != hir_id { - return self.describe_enclosure(parent_hid); - } else { - None + }), + hir::Node::Expr(hir::Expr { .. }) => { + let parent_hid = hir.get_parent_node(hir_id); + if parent_hid != hir_id { + return self.describe_enclosure(parent_hid); + } else { + None + } } - } else { - None + _ => None, } } diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-on-option-diagnostics.rs index 65d5e29ec2f13..63d17414c313b 100644 --- a/src/test/ui/try-on-option-diagnostics.rs +++ b/src/test/ui/try-on-option-diagnostics.rs @@ -16,3 +16,32 @@ fn a_closure() -> u32 { }; a_closure() } + +fn a_method() -> u32 { + struct S; + + impl S { + fn a_method() { + let x: Option = None; + x?; //~ ERROR the `?` operator + } + } + + S::a_method(); + 22 +} + +fn a_trait_method() -> u32 { + struct S; + trait T { + fn a_trait_method() { + let x: Option = None; + x?; //~ ERROR the `?` operator + } + } + + impl T for S { } + + S::a_trait_method(); + 22 +} diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr index ce3aca39fb8fb..c9dc3f1b87969 100644 --- a/src/test/ui/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-on-option-diagnostics.stderr @@ -27,6 +27,32 @@ LL | | }; = help: the trait `std::ops::Try` is not implemented for `{integer}` = note: required by `std::ops::Try::from_error` -error: aborting due to 2 previous errors +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-diagnostics.rs:26:13 + | +LL | / fn a_method() { +LL | | let x: Option = None; +LL | | x?; + | | ^^ cannot use the `?` operator in a method that returns `()` +LL | | } + | |_________- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `std::ops::Try` is not implemented for `()` + = note: required by `std::ops::Try::from_error` + +error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `std::ops::Try`) + --> $DIR/try-on-option-diagnostics.rs:39:13 + | +LL | / fn a_trait_method() { +LL | | let x: Option = None; +LL | | x?; + | | ^^ cannot use the `?` operator in a trait method that returns `()` +LL | | } + | |_________- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `std::ops::Try` is not implemented for `()` + = note: required by `std::ops::Try::from_error` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`.