Skip to content

once_cell::Lazy fails to infer type parameter #10058

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
jonas-schievink opened this issue Aug 27, 2021 · 1 comment · Fixed by #11550
Closed

once_cell::Lazy fails to infer type parameter #10058

jonas-schievink opened this issue Aug 27, 2021 · 1 comment · Fixed by #11550
Assignees
Labels
A-ty type system / type inference / traits / method resolution S-actionable Someone could pick this issue up and work on it right now

Comments

@jonas-schievink
Copy link
Contributor

This code fails infer the type of lazy (rust-analyzer gives it the type Lazy<{unknown}, || -> ()>, but the program compiles fine with rustc):

use std::ops::Deref;

struct Lazy<T, F> {
    _t: T,
    _f: F,
}

impl<T, F> Lazy<T, F> {
    fn new(_f: F) -> Self {
        loop {}
    }
}

impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        loop {}
    }
}

fn main() {
    let lazy = Lazy::new(|| ());

    let () = *lazy;
}

I believe this is caused by the autoderef logic not applying the F: FnOnce() -> T bound back to the inference table, as mentioned in this comment:

https://github.com/rust-analyzer/rust-analyzer/blob/3acbf94d29fb57f83666cf6538435b12d4a431b6/crates/hir_ty/src/autoderef.rs#L192-L196

@jonas-schievink jonas-schievink added A-ty type system / type inference / traits / method resolution S-actionable Someone could pick this issue up and work on it right now labels Aug 27, 2021
@flodiebold
Copy link
Member

Oh, interesting. Yeah, one way to approach this would be to change autoderef and method resolution to happen inside the inference context; the other might be to just record the non-builtin derefs (which we want to do anyway) and add obligations for them (which we probably have to do anyway, given that we perform the deref even when the answer is still ambiguous)... 🤔

@flodiebold flodiebold self-assigned this Sep 12, 2021
flodiebold added a commit to flodiebold/rust-analyzer that referenced this issue Sep 12, 2021
Should fix rust-lang#10090, rust-lang#10046, rust-lang#10179.
This is only a workaround, but the proper fix requires some bigger
refactoring (also related to fixing rust-lang#10058), and this at least prevents
the crash.
bors bot added a commit that referenced this issue Sep 12, 2021
10212: fix: Avoid type inference panic on bitslice methods r=flodiebold a=flodiebold

Should fix #10090, fix #10046, and fix #10179.
This is only a workaround, but the proper fix requires some bigger
refactoring (also related to fixing #10058), and this at least prevents
the crash.

Co-authored-by: Florian Diebold <[email protected]>
bors bot added a commit that referenced this issue Feb 25, 2022
11550: Refactor autoderef/method resolution r=flodiebold a=flodiebold

- don't return the receiver type from method resolution; instead just
 return the autorefs/autoderefs that happened and repeat them. This
 ensures all the effects like trait obligations and whatever we learned
 about type variables from derefing them are actually applied. Also, it
 allows us to get rid of `decanonicalize_ty`, which was just wrong in
 principle.

 - Autoderef itself now directly works with an inference table. Sadly
 this has the effect of making it harder to use as an iterator, often
 requiring manual `while let` loops. (rustc works around this by using
 inner mutability in the inference context, so that things like unifying
 types don't require a unique reference.)

 - We now record the adjustments (autoref/deref) for method receivers
 and index expressions, which we didn't before.

 - Removed the redundant crate parameter from method resolution, since
 the trait_env contains the crate as well.

 - in the HIR API, the methods now take a scope to determine the trait env.
 `Type` carries a trait env, but I think that's probably a bad decision
 because it's easy to create it with the wrong env, e.g. by using
 `Adt::ty`. This mostly didn't matter so far because
 `iterate_method_candidates` took a crate parameter and ignored
 `self.krate`, but the trait env would still have been wrong in those
 cases, which I think would give some wrong results in some edge cases.

Fixes #10058.

Co-authored-by: Florian Diebold <[email protected]>
@bors bors bot closed this as completed in 6fb5abb Feb 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ty type system / type inference / traits / method resolution S-actionable Someone could pick this issue up and work on it right now
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants