Skip to content

Commit 02b3ae6

Browse files
committed
enable desugaring-sensitive error messages and use them in Try
Maybe I should allow error messages to check the *specific* desugaring? Thanks @huntiep for the idea!
1 parent 6866aea commit 02b3ae6

File tree

5 files changed

+74
-9
lines changed

5 files changed

+74
-9
lines changed

src/libcore/ops/try.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@
1515
/// extracting those success or failure values from an existing instance and
1616
/// creating a new instance from a success or failure value.
1717
#[unstable(feature = "try_trait", issue = "42327")]
18-
#[rustc_on_unimplemented = "the `?` operator can only be used in a function that returns `Result` \
19-
(or another type that implements `{Try}`)"]
18+
#[cfg_attr(stage0,
19+
rustc_on_unimplemented = "the `?` operator can only be used in a \
20+
function that returns `Result` \
21+
(or another type that implements `{Try}`)")]
22+
#[cfg_attr(not(stage0),
23+
rustc_on_unimplemented(
24+
on(all(direct, from_desugaring),
25+
message="the `?` operator can only be used in a \
26+
function that returns `Result` \
27+
(or another type that implements `{Try}`)")))]
2028
pub trait Try {
2129
/// The type of this value when viewed as successful.
2230
#[unstable(feature = "try_trait", issue = "42327")]

src/librustc/traits/error_reporting.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
327327
.unwrap_or(trait_ref.def_id());
328328
let trait_ref = *trait_ref.skip_binder();
329329

330+
let mut flags = vec![];
331+
let direct = match obligation.cause.code {
332+
ObligationCauseCode::BuiltinDerivedObligation(..) |
333+
ObligationCauseCode::ImplDerivedObligation(..) => false,
334+
_ => true
335+
};
336+
if direct {
337+
// this is a "direct", user-specified, rather than derived,
338+
// obligation.
339+
flags.push("direct");
340+
}
341+
342+
if let Some(_) = obligation.cause.span.compiler_desugaring_kind() {
343+
flags.push("from_desugaring");
344+
}
345+
330346
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
331347
self.tcx, trait_ref.def_id, def_id
332348
) {
333-
command.evaluate(self.tcx, trait_ref, &[])
349+
command.evaluate(self.tcx, trait_ref, &flags)
334350
} else {
335351
OnUnimplementedNote::empty()
336352
}

src/libsyntax_pos/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,18 @@ impl Span {
205205
}
206206
}
207207

208+
/// Return the compiler desugaring that created this span, or None
209+
/// if this span is not from a desugaring.
210+
pub fn compiler_desugaring_kind(&self) -> Option<CompilerDesugaringKind> {
211+
match self.ctxt().outer().expn_info() {
212+
Some(info) => match info.callee.format {
213+
ExpnFormat::CompilerDesugaring(k) => Some(k),
214+
_ => None
215+
},
216+
None => None
217+
}
218+
}
219+
208220
/// Check if a span is "internal" to a macro in which `unsafe`
209221
/// can be used without triggering the `unsafe_code` lint
210222
// (that is, a macro marked with `#[allow_internal_unsafe]`).

src/test/ui/suggestions/try-operator-on-main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::ops::Try;
12+
1113
fn main() {
1214
std::fs::File::open("foo")?;
15+
16+
try_trait_generic::<()>();
1317
}
18+
19+
fn try_trait_generic<T: Try>() {}
Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
1-
error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
2-
--> $DIR/try-operator-on-main.rs:12:5
1+
error: use of unstable library feature 'try_trait' (see issue #42327)
2+
--> $DIR/try-operator-on-main.rs:11:5
3+
|
4+
11 | use std::ops::Try;
5+
| ^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(try_trait)] to the crate attributes to enable
8+
9+
error: use of unstable library feature 'try_trait' (see issue #42327)
10+
--> $DIR/try-operator-on-main.rs:19:25
11+
|
12+
19 | fn try_trait_generic<T: Try>() {}
13+
| ^^^
314
|
4-
12 | std::fs::File::open("foo")?;
15+
= help: add #![feature(try_trait)] to the crate attributes to enable
16+
17+
error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
18+
--> $DIR/try-operator-on-main.rs:14:5
19+
|
20+
14 | std::fs::File::open("foo")?;
521
| ---------------------------
622
| |
7-
| the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
23+
| the trait `std::ops::Try` is not implemented for `()`
824
| in this macro invocation
925
|
10-
= help: the trait `std::ops::Try` is not implemented for `()`
1126
= note: required by `std::ops::Try::from_error`
1227

13-
error: aborting due to previous error
28+
error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
29+
--> $DIR/try-operator-on-main.rs:16:5
30+
|
31+
16 | try_trait_generic::<()>();
32+
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()`
33+
|
34+
= note: required by `try_trait_generic`
35+
36+
error: aborting due to 4 previous errors
1437

0 commit comments

Comments
 (0)