diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2017-08-31 21:46:03 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2017-09-03 13:10:54 +0300 |
| commit | efa09ea554575cd0b4ce01ada44fce730c0f7ac4 (patch) | |
| tree | 896816568ac690f302bad2440a353a0f13eb91ad /src | |
| parent | 6dec953c5ad7357a9f2d90626e56bc0dc30127a9 (diff) | |
| download | rust-efa09ea554575cd0b4ce01ada44fce730c0f7ac4.tar.gz rust-efa09ea554575cd0b4ce01ada44fce730c0f7ac4.zip | |
on_unimplemented: add method-name checks and use them in Try
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/ops/try.rs | 4 | ||||
| -rw-r--r-- | src/librustc/traits/error_reporting.rs | 20 | ||||
| -rw-r--r-- | src/librustc/traits/on_unimplemented.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/suggestions/try-operator-on-main.rs | 14 | ||||
| -rw-r--r-- | src/test/ui/suggestions/try-operator-on-main.stderr | 32 |
5 files changed, 69 insertions, 12 deletions
diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index 6e330f538a8..28e84d2fba6 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -21,7 +21,9 @@ (or another type that implements `{Try}`)")] #[cfg_attr(not(stage0), rustc_on_unimplemented( - on(all(direct, from_desugaring="?"), + on(all( + any(from_method="from_error", from_method="from_ok"), + from_desugaring="?"), message="the `?` operator can only be used in a \ function that returns `Result` \ (or another type that implements `{Try}`)", diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 509f3420628..ce6da55fec3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -327,7 +327,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .unwrap_or(trait_ref.def_id()); let trait_ref = *trait_ref.skip_binder(); - let s; + let desugaring; + let method; let mut flags = vec![]; let direct = match obligation.cause.code { ObligationCauseCode::BuiltinDerivedObligation(..) | @@ -340,10 +341,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { flags.push(("direct", None)); } + if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code { + // FIXME: maybe also have some way of handling methods + // from other traits? That would require name resolution, + // which we might want to be some sort of hygienic. + // + // Currently I'm leaving it for what I need for `try`. + if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { + method = self.tcx.item_name(item).as_str(); + flags.push(("from_method", None)); + flags.push(("from_method", Some(&*method))); + } + } + if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { - s = k.as_symbol().as_str(); + desugaring = k.as_symbol().as_str(); flags.push(("from_desugaring", None)); - flags.push(("from_desugaring", Some(&*s))); + flags.push(("from_desugaring", Some(&*desugaring))); } if let Ok(Some(command)) = OnUnimplementedDirective::of_item( diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 2cfee21936c..7dd3fc70b1e 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -176,6 +176,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { { let mut message = None; let mut label = None; + info!("evaluate({:?}, trait_ref={:?}, options={:?})", + self, trait_ref, options); for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition { @@ -191,8 +193,13 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { } } debug!("evaluate: {:?} succeeded", command); - message = command.message.clone(); - label = command.label.clone(); + if let Some(ref message_) = command.message { + message = Some(message_.clone()); + } + + if let Some(ref label_) = command.label { + label = Some(label_.clone()); + } } OnUnimplementedNote { diff --git a/src/test/ui/suggestions/try-operator-on-main.rs b/src/test/ui/suggestions/try-operator-on-main.rs index d81f773442c..473efea54de 100644 --- a/src/test/ui/suggestions/try-operator-on-main.rs +++ b/src/test/ui/suggestions/try-operator-on-main.rs @@ -13,9 +13,21 @@ use std::ops::Try; fn main() { + // error for a `Try` type on a non-`Try` fn std::fs::File::open("foo")?; + // a non-`Try` type on a `Try` fn + ()?; + + // an unrelated use of `Try` try_trait_generic::<()>(); } -fn try_trait_generic<T: Try>() {} + + +fn try_trait_generic<T: Try>() -> T { + // and a non-`Try` object on a `Try` fn. + ()?; + + loop {} +} diff --git a/src/test/ui/suggestions/try-operator-on-main.stderr b/src/test/ui/suggestions/try-operator-on-main.stderr index 0d3e67e99a8..5fc24e46fa7 100644 --- a/src/test/ui/suggestions/try-operator-on-main.stderr +++ b/src/test/ui/suggestions/try-operator-on-main.stderr @@ -1,7 +1,7 @@ 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:16:5 + --> $DIR/try-operator-on-main.rs:17:5 | -16 | std::fs::File::open("foo")?; +17 | std::fs::File::open("foo")?; | --------------------------- | | | cannot use the `?` operator in a function that returns `()` @@ -11,12 +11,34 @@ error[E0277]: the `?` operator can only be used in a function that returns `Resu = note: required by `std::ops::Try::from_error` error[E0277]: the trait bound `(): std::ops::Try` is not satisfied - --> $DIR/try-operator-on-main.rs:18:5 + --> $DIR/try-operator-on-main.rs:20:5 | -18 | try_trait_generic::<()>(); +20 | ()?; + | --- + | | + | the trait `std::ops::Try` is not implemented for `()` + | in this macro invocation + | + = note: required by `std::ops::Try::into_result` + +error[E0277]: the trait bound `(): std::ops::Try` is not satisfied + --> $DIR/try-operator-on-main.rs:23:5 + | +23 | try_trait_generic::<()>(); | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Try` is not implemented for `()` | = note: required by `try_trait_generic` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `(): std::ops::Try` is not satisfied + --> $DIR/try-operator-on-main.rs:30:5 + | +30 | ()?; + | --- + | | + | the trait `std::ops::Try` is not implemented for `()` + | in this macro invocation + | + = note: required by `std::ops::Try::into_result` + +error: aborting due to 4 previous errors |
