Rollup merge of #68425 - phi-gamma:try-method, r=varkor
Fix try-op diagnostic in E0277 for methods
For methods the try-op diagnostic displays the empty string where
it has more descriptive strings like “a function” otherwise:
error[E0277]: the `?` operator can only be used in that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
^^
| | ^^ cannot use the `?` operator in that returns `()`
^^
I’m seeing this on nightly (rustc 1.42.0-nightly (b5a3341f1
2020-01-20)) and [on the playpen](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0e7ce7792c2aceb8056941710d539124).
The changeset add strings for impl methods and trait provided
methods and test cases for the option type.
This commit is contained in:
commit
1077adae12
@ -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(|| {
|
||||
Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
|
||||
"an async function"
|
||||
} else {
|
||||
"a function"
|
||||
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"
|
||||
})
|
||||
})
|
||||
})
|
||||
} 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(|| {
|
||||
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
|
||||
}
|
||||
} else {
|
||||
None
|
||||
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 method"
|
||||
} else {
|
||||
"a method"
|
||||
})
|
||||
}),
|
||||
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" })
|
||||
}),
|
||||
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
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,3 +16,32 @@ fn a_closure() -> u32 {
|
||||
};
|
||||
a_closure()
|
||||
}
|
||||
|
||||
fn a_method() -> u32 {
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
fn a_method() {
|
||||
let x: Option<u32> = 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<u32> = None;
|
||||
x?; //~ ERROR the `?` operator
|
||||
}
|
||||
}
|
||||
|
||||
impl T for S { }
|
||||
|
||||
S::a_trait_method();
|
||||
22
|
||||
}
|
||||
|
@ -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<u32> = 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<u32> = 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`.
|
||||
|
Loading…
Reference in New Issue
Block a user