Skip to content

Commit 41b00c0

Browse files
authored
Rollup merge of rust-lang#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 (b5a3341 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.
2 parents 7e9608c + db3b40c commit 41b00c0

File tree

3 files changed

+90
-21
lines changed

3 files changed

+90
-21
lines changed

src/librustc/traits/error_reporting/on_unimplemented.rs

+34-20
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
5959
fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
6060
let hir = &self.tcx.hir();
6161
let node = hir.find(hir_id)?;
62-
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
63-
self.describe_generator(*body_id).or_else(|| {
62+
match &node {
63+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
64+
self.describe_generator(*body_id).or_else(|| {
65+
Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
66+
"an async function"
67+
} else {
68+
"a function"
69+
})
70+
})
71+
}
72+
hir::Node::TraitItem(hir::TraitItem {
73+
kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)),
74+
..
75+
}) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
76+
hir::Node::ImplItem(hir::ImplItem {
77+
kind: hir::ImplItemKind::Method(sig, body_id),
78+
..
79+
}) => self.describe_generator(*body_id).or_else(|| {
6480
Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
65-
"an async function"
81+
"an async method"
6682
} else {
67-
"a function"
83+
"a method"
6884
})
69-
})
70-
} else if let hir::Node::Expr(hir::Expr {
71-
kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
72-
..
73-
}) = &node
74-
{
75-
self.describe_generator(*body_id).or_else(|| {
85+
}),
86+
hir::Node::Expr(hir::Expr {
87+
kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
88+
..
89+
}) => self.describe_generator(*body_id).or_else(|| {
7690
Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
77-
})
78-
} else if let hir::Node::Expr(hir::Expr { .. }) = &node {
79-
let parent_hid = hir.get_parent_node(hir_id);
80-
if parent_hid != hir_id {
81-
return self.describe_enclosure(parent_hid);
82-
} else {
83-
None
91+
}),
92+
hir::Node::Expr(hir::Expr { .. }) => {
93+
let parent_hid = hir.get_parent_node(hir_id);
94+
if parent_hid != hir_id {
95+
return self.describe_enclosure(parent_hid);
96+
} else {
97+
None
98+
}
8499
}
85-
} else {
86-
None
100+
_ => None,
87101
}
88102
}
89103

src/test/ui/try-on-option-diagnostics.rs

+29
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,32 @@ fn a_closure() -> u32 {
1616
};
1717
a_closure()
1818
}
19+
20+
fn a_method() -> u32 {
21+
struct S;
22+
23+
impl S {
24+
fn a_method() {
25+
let x: Option<u32> = None;
26+
x?; //~ ERROR the `?` operator
27+
}
28+
}
29+
30+
S::a_method();
31+
22
32+
}
33+
34+
fn a_trait_method() -> u32 {
35+
struct S;
36+
trait T {
37+
fn a_trait_method() {
38+
let x: Option<u32> = None;
39+
x?; //~ ERROR the `?` operator
40+
}
41+
}
42+
43+
impl T for S { }
44+
45+
S::a_trait_method();
46+
22
47+
}

src/test/ui/try-on-option-diagnostics.stderr

+27-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,32 @@ LL | | };
2727
= help: the trait `std::ops::Try` is not implemented for `{integer}`
2828
= note: required by `std::ops::Try::from_error`
2929

30-
error: aborting due to 2 previous errors
30+
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
31+
--> $DIR/try-on-option-diagnostics.rs:26:13
32+
|
33+
LL | / fn a_method() {
34+
LL | | let x: Option<u32> = None;
35+
LL | | x?;
36+
| | ^^ cannot use the `?` operator in a method that returns `()`
37+
LL | | }
38+
| |_________- this function should return `Result` or `Option` to accept `?`
39+
|
40+
= help: the trait `std::ops::Try` is not implemented for `()`
41+
= note: required by `std::ops::Try::from_error`
42+
43+
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`)
44+
--> $DIR/try-on-option-diagnostics.rs:39:13
45+
|
46+
LL | / fn a_trait_method() {
47+
LL | | let x: Option<u32> = None;
48+
LL | | x?;
49+
| | ^^ cannot use the `?` operator in a trait method that returns `()`
50+
LL | | }
51+
| |_________- this function should return `Result` or `Option` to accept `?`
52+
|
53+
= help: the trait `std::ops::Try` is not implemented for `()`
54+
= note: required by `std::ops::Try::from_error`
55+
56+
error: aborting due to 4 previous errors
3157

3258
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)