Change:
RFC 1859 laid out for the operator, but currently they are not implemented (and instead the compiler's internal desugaring is revealed). UPDATE: Many parts of this are done, but not all. UPDATE 2: to close this ticket we need to . Original text: in main has long been an issue, to the point of trying to adjust the language to support it: I was trying out today, and hit this error: That's the only line, inside of a function. Even though I know about this pitfall, and have been using Rust for a long time, I asked a question about it on IRC. Can we print a better diagnostic here that points out it's the return type of the function that's looking for ?
Now that it's part of the language, we can even print .
Yeah, that's exactly what I was hoping.
Carrier trait.
can you elaborate? Do we have to wait on this kind of diagnostic until the Carrier stuff shakes out?
I mean that such diagnostic will make no sense once we implement and accept the carrier trait. First, because then you’ll be able to use in function that returns anything implementing Carrier trait (not just ), but also because it would be possible to implement carrier trait for something like in case anybody wanted to do so in their standard library. Implementing such special cased diagnostic now would 100% result in it being forgotten until somebody comes along and complains that diagnostic about makes no sense (like it is already a case with a bunch of such help messages).
Maybe we can just put a on ? It would be neat if that worked, but that attribute has been sorely neglected of late. Regardless I hope that good diagnostics will be taken into account while designing the trait.
As of , the error in this case has gotten less understandable, imo: This error message seems to be guiding me towards implementing on , but what would be better is what and suggested: something that mentions the return type is , and that mentions you can only use in a function that returns a .
This is what you can get with rustconunimplemented: Bikeshed on wording.
I am not sure if this is good enough. I've long been unsatisfied with for a couple of reasons -- one of them is that the "better" message is not the main thing people see. The other is that the ability to decide when to give the better message is pretty limited: often people write a "better" message for one particular scenario, but the same error (i.e., an unsatisfied trait bound) can appear in other scenarios where that better message sounds wrong. i.e., here, we talk about return types, but if I wrote some code like: that error message would make any sense to me. These two things are of course related, since giving a "maybe wrong" message high prominence feels bad. That said, in this particular case, since is unstable, we can probably hard-code more -- but it feels like we could do better still. We know that the desugars into some particular code. We can probably tag that code and give the resulting trait obligations a more specific "cause", so that we can produce a good error in exactly this situation. Note that this is valuable even once gets stabilized.
Here's what I have so far: Need to inhibit that second note. Next step is to actually figure out whether the error came from or .
seems good so far!
Hi what do you have so far where? I don't see a PR linked to this issue at all :-/ Is there anyone I could bother to get you the help you need to finish this? I'd really love for this to get fixed before the new version of the book comes out, and for all the new rustaceans who are hitting this in the meantime <3 <3 <3
Hey I don't really have anything working unfortunately. I'd like to pick it up again, I'll need some help though. I think that will change things anyway ( why was that closed? is the design work that came out of ongoing somewhere?).
It may look like I did something significant but I didn't think so. This rust-lang/rfcs/issues/1718 is the main thread, and niko proposed another variant of the formulation (which I confirmed compiles and works in rustc). It does change slightly for the better, it doesn't have a carrier trait anymore. Edited, without the semicolon is maybe better:
thanks! That definitely looks better :) I assume if you use in (the most common thing new rustaceans do) that the error message looks like: With this implementation, would it still be possible to add this note?
I just wanted to mentio one more option, as a beginner rust user. I would find it helpful if the error message mentioned something like , rather than just -- to make clear why we are expecting a .
As a further data point about something going awry: produces together with the type mismatch errors already shown in this issue. There's no visible match arm. tried to solve this, but wasn't merged due to concerns about save-analysis.
I'm currently doing: There is a lot more code and the company owns it. Also it wasn't throw this error yesterday --' I refactored something related to logging and BOOM I started seeing this. Also entire other methods within this class_ are no longer resolving.
Current output on nightly after :
In order to really implement the , I think we will need to do something better than . In , we discussed that before we really start adding impls of for , we need to get the error messages under control, so this issue is quite a high priority in that sense. Right now, the way that is implemented is as follows: The AST includes direct support for the operator (). During HIR lowering, gets . This means that HIR doesn't directly see the operator -- it just sees a call to . This explains the kind of poor error messages at present. However, we do keep a bit of extra info -- in particular, the span of that function call . At the moment, this annotation is only used to allow access to unstable APIs (notably ) even within stable code. But we can leverage it to give better errors too. At this point, a slight diversion is in order. Each in the compiler includes "expansion info" that indicates, if this code arose from macro expansion, precisely what that expansion was. This includes a full backtrace. That backtrace may include "compiler desugarings", in which case we allow access to unstable APIs. For example, checks whether code in that span should have access to unstable APIs. We would need a similar function like that checks whether the top-most expn-info has equal to where == the currently includes an interned string to indicate which one it is. This is kind of hokey. Probably an enum would be better. If we had such a helper on spans, then we could use it when reporting trait failures. In particular, let's start with the simplest error case: imagine that we have applied to a value of some type (e.g., ) that does not implement . The RFC states then that the error should be: " cannot be applied to a value of type ". To implement this, we can modify , which is invoked when a trait selection fails. In this case, the trait selection would be . We can then check whether the trait in question is the trait It seems like we have to make into a lang-item first, by adding it to [this file] and then adding to the declaration of the trait Then we can get its def-id by doing and compare that against the def-id of the trait we are selecting Presuming they are the same, we can check whether the span comes from desugaring using our helper we earlier () If (a) this is from the and (b) this is a match of the trait, then we could print the error message proscribed by the RFC. I think this is roughly the idea. Happy to provide more details where needed. But ping on IRC or gitter if you don't get a response though, as it's easy to lose track of GH notifications. I think that to start it would be good to target this precise case I outlined, and I would probably do it in a few steps PRs (each of which could be a separate PR): the string in with an enum and add a helper on that will check if it arises from a compile desugaring of a particular kind. a lang item. the error handling in error-selection as described above. Once we get that working, we can cover the other cases described in the RFC.
expressed interest in working on this in
regarding your question from : I think the thing you need to do is to create a second desugaring code, maybe something like , and then use that span for , basically the parts that correspond to the . Then we can detect errors that arose due to the (or ) part of the desugaring and give them the custom error message of "try cannot be used in a function that returns". We might even make a distinct code for so that we can tailor the error message to the case of versus just .
feel free to ping me on IRC.
So, between and we now have a lot of progress on this topic. See for example the test case (). Notably, we now say one of the following: the operator can only be used in a function that returns (or another type that implements ) the operator can only be applied to values that implement I think we can close this issue, right?
Well, looking through the RFC, there are a few things not covered. These are the heading: Suggesting a new return type: The RFC writes, 'At this point, we could likely make a suggestion such as "consider changing the return type to Result<(), Box<Error".' It's not clear to me that this is a good idea, but it might be, subject to the caveats in the RFC. Errors cannot be interconverted -- probably a good idea. Consider suggesting the use of catch -- I'm not sure how I feel about this, perhaps the extended error description is the right place to talk about it though. In any case, as is not stable, we likely won't want to do this (yet).
that he was planning on trying to cover the "Errors cannot be interconverted" case. -- as an alternative, if you feel like writing mentoring instructions, this is the place.
I already opened for the mentoring instructions
:
what are the "errors cannot be interconverted case"? ()
: The case where is slightly verbose but suggests setting a return type only when returning, not when the used on its own (and the suggestion doesn't take the return path into consideration for the suggested return type): , we don't get suggestions:
OK, I updated the head comment to link to your post.
We now point only at the when we can't cover the error type, but otherwise no changes from my last comment.
Of the three cases, the first one is now: and the third one is
The first case is unchanged. Only improvement I can think of would be to point at in the return type . The current output for the second case is: And for the third: Note the suggestion to use . Overall I feel quite happy with the current state and feel we can close this after pointing at the return type when having the implicit conversion failure.

Discussion:
.starts_with("std::convert::From<std::option::NoneError"); let should_convert_result_to_option = format!("{}", trait_ref) .starts_with("<std::option::NoneError as std::convert::From<"); <del> if is_try && is_from && should_convert_option_to_result { err.span_suggestion_verbose( span.shrink_to_lo(), "consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`", ".ok_or_else(|| /* error value */)".to_string(), Applicability::HasPlaceholders, ); } else if is_try && is_from && should_convert_result_to_option { err.span_suggestion_verbose( span.shrink_to_lo(), "consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`", ".ok()".to_string(), Applicability::MachineApplicable, ); </del> <ins> if is_try && is_from { if should_convert_option_to_result { err.span_suggestion_verbose( span.shrink_to_lo(), "consider converting the `Option<T>` into a `Result<T, _>`  using `Option::ok_or` or `Option::ok_or_else`", ".ok_or_else(|| /* error value */)".to_string(), Applicability::HasPlaceholders, ); } else if should_convert_result_to_option { err.span_suggestion_verbose( span.shrink_to_lo(), "consider converting the `Result<T, _>` into an `Option<T>`  using `Result::ok`", ".ok()".to_string(), Applicability::MachineApplicable, ); } if let Some(ret_span) = self.return_type_span(obligation) { err.span_label( ret_span, &format!("expected `{}` because of this", trait_ref.self_ty()), ); } </ins> } let explanation =

trait_ref: &ty::Binder<ty::TraitRef<'tcx>>, ); <ins> fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>; </ins> fn suggest_impl_trait( &self, err: &mut DiagnosticBuilder<'tcx>,

} } <ins> fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> { let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); let sig = match hir.find(parent_node) { Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) => sig, _ => return None, }; if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None } } </ins> /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if /// applicable and signal that the error has been expanded appropriately and needs to be /// emitted.

error[E0277]: `?` couldn't convert the error to `()` --> $DIR/issue-32709.rs:4:11 | <ins> LL | fn a() -> Result<i32, ()> { |           --------------- expected `()` because of this </ins> LL |     Err(5)?; |           ^ the trait `std::convert::From<{integer}>` is not implemented for `()` |

error[E0277]: `?` couldn't convert the error to `()` --> $DIR/option-to-result.rs:5:6 | <ins> LL | fn test_result() -> Result<(),()> { |                     ------------- expected `()` because of this LL |     let a:Option<()> = Some(()); </ins> LL |     a?; |      ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()` |

error[E0277]: `?` couldn't convert the error to `std::option::NoneError` --> $DIR/option-to-result.rs:11:6 | <ins> LL | fn test_option() -> Option<i32>{ |                     ----------- expected `std::option::NoneError` because of this LL |     let a:Result<i32, i32> = Ok(5); </ins> LL |     a?; |      ^ the trait `std::convert::From<i32>` is not implemented for `std::option::NoneError` |

error[E0277]: `?` couldn't convert the error to `()` --> $DIR/try-on-option.rs:7:6 | <ins> LL | fn foo() -> Result<u32, ()> { |             --------------- expected `()` because of this LL |     let x: Option<u32> = None; </ins> LL |     x?; |      ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()` |