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:
parent
6866aea5af
commit
02b3ae63e2
|
@ -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")]
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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]`).
|
||||
|
|
|
@ -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>() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue