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!
This commit is contained in:
Ariel Ben-Yehuda 2017-08-31 00:12:34 +03:00
parent 6866aea5af
commit 02b3ae63e2
5 changed files with 74 additions and 9 deletions

View File

@ -15,8 +15,16 @@
/// extracting those success or failure values from an existing instance and
/// creating a new instance from a success or failure value.
#[unstable(feature = "try_trait", issue = "42327")]
#[rustc_on_unimplemented = "the `?` operator can only be used in a function that returns `Result` \
(or another type that implements `{Try}`)"]
#[cfg_attr(stage0,
rustc_on_unimplemented = "the `?` operator can only be used in a \
function that returns `Result` \
(or another type that implements `{Try}`)")]
#[cfg_attr(not(stage0),
rustc_on_unimplemented(
on(all(direct, from_desugaring),
message="the `?` operator can only be used in a \
function that returns `Result` \
(or another type that implements `{Try}`)")))]
pub trait Try {
/// The type of this value when viewed as successful.
#[unstable(feature = "try_trait", issue = "42327")]

View File

@ -327,10 +327,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.unwrap_or(trait_ref.def_id());
let trait_ref = *trait_ref.skip_binder();
let mut flags = vec![];
let direct = match obligation.cause.code {
ObligationCauseCode::BuiltinDerivedObligation(..) |
ObligationCauseCode::ImplDerivedObligation(..) => false,
_ => true
};
if direct {
// this is a "direct", user-specified, rather than derived,
// obligation.
flags.push("direct");
}
if let Some(_) = obligation.cause.span.compiler_desugaring_kind() {
flags.push("from_desugaring");
}
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
self.tcx, trait_ref.def_id, def_id
) {
command.evaluate(self.tcx, trait_ref, &[])
command.evaluate(self.tcx, trait_ref, &flags)
} else {
OnUnimplementedNote::empty()
}

View File

@ -205,6 +205,18 @@ impl Span {
}
}
/// Return the compiler desugaring that created this span, or None
/// if this span is not from a desugaring.
pub fn compiler_desugaring_kind(&self) -> Option<CompilerDesugaringKind> {
match self.ctxt().outer().expn_info() {
Some(info) => match info.callee.format {
ExpnFormat::CompilerDesugaring(k) => Some(k),
_ => None
},
None => None
}
}
/// Check if a span is "internal" to a macro in which `unsafe`
/// can be used without triggering the `unsafe_code` lint
// (that is, a macro marked with `#[allow_internal_unsafe]`).

View File

@ -8,6 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ops::Try;
fn main() {
std::fs::File::open("foo")?;
try_trait_generic::<()>();
}
fn try_trait_generic<T: Try>() {}

View File

@ -1,14 +1,37 @@
error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
--> $DIR/try-operator-on-main.rs:12:5
error: use of unstable library feature 'try_trait' (see issue #42327)
--> $DIR/try-operator-on-main.rs:11:5
|
12 | std::fs::File::open("foo")?;
11 | use std::ops::Try;
| ^^^^^^^^^^^^^
|
= help: add #![feature(try_trait)] to the crate attributes to enable
error: use of unstable library feature 'try_trait' (see issue #42327)
--> $DIR/try-operator-on-main.rs:19:25
|
19 | fn try_trait_generic<T: Try>() {}
| ^^^
|
= help: add #![feature(try_trait)] to the crate attributes to enable
error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
--> $DIR/try-operator-on-main.rs:14:5
|
14 | std::fs::File::open("foo")?;
| ---------------------------
| |
| the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
| the trait `std::ops::Try` is not implemented for `()`
| in this macro invocation
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
error: aborting due to previous error
error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
--> $DIR/try-operator-on-main.rs:16:5
|
16 | try_trait_generic::<()>();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()`
|
= note: required by `try_trait_generic`
error: aborting due to 4 previous errors