Skip to content

Suggest changing -> T<U> to a -> T<&U> when trying to return a T<&U> #100699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DropDemBits opened this issue Aug 17, 2022 · 2 comments · Fixed by #101367
Closed

Suggest changing -> T<U> to a -> T<&U> when trying to return a T<&U> #100699

DropDemBits opened this issue Aug 17, 2022 · 2 comments · Fixed by #101367
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@DropDemBits
Copy link
Contributor

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a33eca3ff60c0fa5b2f73dc3e34c362f

fn bing<'a>() -> Option<&'a ()> {
    None
}

struct Thing;

impl Thing {
    fn bang(&self) -> Option<()> {
        bing()
    }
}

The current output is:

error[E0308]: mismatched types
 --> src/lib.rs:9:9
  |
8 |     fn bang(&self) -> Option<()> {
  |                       ---------- expected `Option<()>` because of return type
9 |         bing()
  |         ^^^^^^ expected `()`, found `&()`
  |
  = note: expected enum `Option<()>`
             found enum `Option<&()>`

Ideally, there should be a suggestion to add a & to the inner type

  = help: try adding a `&` to the inner type:
  |
8 |     fn bang(&self) -> Option<&()> {
  |                              +
@DropDemBits DropDemBits added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 17, 2022
@compiler-errors
Copy link
Member

Hm, this suggestion in particular is very specific to T itself, and also the signature of the function (i.e. it's only meaningful to suggest a reference with an elided lifetime in the return type -- like &T -- if there's a lifetime that matches in the inputs...).

This also changes the meaning of the function. It's equally likely, I think, that the user could've forgotten an Option::copied method call in the case of the example you provided.

@DropDemBits
Copy link
Contributor Author

Yeah, I probably reduced the example too much when making the issue.
This snippet is a closer approximation of the original code:

use std::collections::HashMap;

struct Def;

struct DefThings {
    things: HashMap<u32, Vec<Def>>
}

impl DefThings {
    fn get_thing(&self, id: u32) -> Option<Vec<Def>> {
        self.things.get(&id)
    }
}

Though this also falls under the same reasoning as the previous example (an Option::cloned could've been forgotten).


I was definitely confused initially because I'd first seen the error text in vscode (and thus from r-a), and the presentation of the error there is less than ideal:

mismatched types
expected enum `std::option::Option<std::vec::Vec<Def>>`
   found enum `std::option::Option<&std::vec::Vec<Def>>` rustc(E0308)
lib.rs(11, 37): expected `std::option::Option<std::vec::Vec<Def>>` because of return type

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants