Skip to content

Problem with type inference and impl Trait #73239

Closed

Description

@joe-hauns

Hi!
I recently experienced a bug in that probably comes from problems of the interference of type inference, impl Trait in return type position, and associated types.

This is a very strongly simplified version of what was going on in my codebase. In fact my codebase included Arc instead of SmartPointer and AsRef instead of MyAsRef, but I wanted to simplify to reproduce the problem without std.

struct SmartPointer<A>(A);

trait MyAsRef<A> {
    fn my_ref(&self) -> &A;
}

impl<A> MyAsRef<A> for SmartPointer<A> {
    fn my_ref(&self) -> &A {
        &self.0
    }
}

struct Type0Container<P>(SmartPointer<P::Type0>)
where
    P: TypeSet;

impl<P> Type0Container<P>
where
    P: TypeSet,
{
    // fn item(&self) -> &SmartPointer<P::Type0> { // << compiles
    fn item(&self) -> &impl MyAsRef<P::Type0> {    // << does not compile
        &self.0
    }
}

trait TypeSet {
    type Type0;
}

struct TypeSetImpl;
struct Type0Impl;

impl TypeSet for TypeSetImpl {
    type Type0 = Type0Impl;
}

fn main() {
    let proc: Type0Container<TypeSetImpl> = Type0Container(SmartPointer(Type0Impl)); 
    let _: &Type0Impl = proc.item().my_ref();
}

I expected to see this happen:
The compiler should be able to infer that <TypeSetImpl as TypeSet>::Type0 = Type0Impl and compile the program.

Instead, this happened:
The compiler failed with this error message:

   Compiling lala v0.1.0 (/path/to/lala)
error[E0308]: mismatched types
  --> src/main.rs:41:25
   |
41 |     let _: &Type0Impl = proc.item().my_ref();
   |            ----------   ^^^^^^^^^^^^^^^^^^^^ expected struct `Type0Impl`, found associated type
   |            |
   |            expected due to this
   |
   = note: expected reference `&Type0Impl`
              found reference `&<TypeSetImpl as TypeSet>::Type0`
   = help: consider constraining the associated type `<TypeSetImpl as TypeSet>::Type0` to `Type0Impl`
   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

As noted in the comments in the code snipped changing the one line using impl Trait in return type position enables the compiler to build the program.
I'm not entirely sure if this is a bug or if I expecting type inference to be stronger as it is or if the code I wrote is indeed not correct, so sorry if that is the case.

Meta

rustc --version --verbose:

rustc 1.46.0-nightly (449e8eaa2 2020-06-10)
binary: rustc
commit-hash: 449e8eaa286e407c9cd8cac655b77998fd53db6b
commit-date: 2020-06-10
host: x86_64-apple-darwin
release: 1.46.0-nightly
LLVM version: 10.0
None

<backtrace>

Activity

  1. added
    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
    T-typesRelevant to the types team, which will review and decide on the PR/issue.
    on Dec 21, 2024
  2. fmease commented on Dec 22, 2024

    @fmease
    Member

    The provided snippet compiles just fine in the current version of Rust. I'm pretty sure that we have a test for this somewhere already, so we don't need to add a regression test and can close this issue directly. However, I actually still need to look for it ^^

  3. fmease commented on Dec 28, 2024

    @fmease
    Member

    Smaller:

    trait Id { type Out; }
    impl<T> Id for T { type Out = T; }
    
    fn main() {
        fn make<P: Id>(x: P::Out) -> impl Into<P::Out> { x }
        let _: () = make::<()>(()).into(); // error: mismatched types
                                           //  note:    expected unit type `()`
                                           //        found associated type `<() as Id>::Out`
    }

    searched toolchains nightly-2020-06-11 through nightly-2024-12-28
    
    ********************************************************************************
    Regression in nightly-2020-10-07
    ********************************************************************************
    
    looking for regression commit between 2020-10-06 and 2020-10-07
    fetching (via remote github) commits from max(a1dfd2490a6cb456b92e469fa550dc217e20ad6d, 2020-10-04) to 98edd1fbf8a68977a2a7c1312eb1ebff80515a92
    ending github query because we found starting sha: a1dfd2490a6cb456b92e469fa550dc217e20ad6d
    get_commits_between returning commits, len: 6
      commit[0] 2020-10-05: Auto merge of #77080 - richkadel:llvm-coverage-counters-2, r=tmandry
      commit[1] 2020-10-06: Auto merge of #77606 - JohnTitor:rollup-7rgahdt, r=JohnTitor
      commit[2] 2020-10-06: Auto merge of #77594 - timvermeulen:chain_advance_by, r=scottmcm
      commit[3] 2020-10-06: Auto merge of #73905 - matthewjasper:projection-bounds-2, r=nikomatsakis
      commit[4] 2020-10-06: Auto merge of #76356 - caass:hooks, r=jyn514
      commit[5] 2020-10-06: Auto merge of #77386 - joshtriplett:static-glibc, r=petrochenkov
    ERROR: no CI builds available between a1dfd2490a6cb456b92e469fa550dc217e20ad6d and 98edd1fbf8a68977a2a7c1312eb1ebff80515a92 within last 167 days
    

    Fixed by PR: #73905. A lot of tests were modified and added, none look quite like this test but I'm more than certain that this is covered by a bunch of tests. Closing as fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-associated-itemsArea: Associated items (types, constants & functions)A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.A-lazy-normalizationArea: Lazy normalization (tracking issue: #60471)A-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions