Skip to content

Type inference fails with adt_const_params and const_generic_exprs for associated types #112248

Open
@Tehforsch

Description

@Tehforsch

Sorry for the long example, but it is the shortest that I could come up with that reproduces the bug:

#![allow(incomplete_features)]
#![feature(generic_const_exprs, adt_const_params)]

use std::{marker::ConstParamTy, ops::Add};

#[derive(ConstParamTy, PartialEq, Eq)]
pub struct Value(i32);

#[derive(Clone, Copy)]
pub struct MyType<const D: Value>;

impl Value {
    pub const fn add(self, other: Self) -> Self {
        Self(self.0 + other.0)
    }
}

impl<const DL: Value, const DR: Value> std::ops::Add<MyType<DR>> for MyType<DL>
where
    MyType<{ DL.add(DR) }>:,
{
    type Output = MyType<{ DL.add(DR) }>;

    fn add(self, _: MyType<DR>) -> Self::Output {
        MyType
    }
}

pub type One = MyType<{ Value(1) }>;
pub type Two = MyType<{ Value(2) }>;

fn foo(one: One) -> <One as Add<Two>>::Output {
    let two = one + one;
    one + two
}

fn foo_annotated(one: One) -> <One as Add<Two>>::Output {
    let two: Two = one + one;
    one + two
}

I expected both foo and foo_annotated to compile, but only foo_annotated compiles. foo fails to compile with:

error[E0308]: mismatched types
  --> src/main.rs:36:5
   |
36 |     one + two
   |     ^^^^^^^^^ expected `Value(2)`, found `{const expr}`
   |
   = note: expected constant `Value(2)`
              found constant `{const expr}`

foo compiles correctly if any of the following changes are made:

  1. Value is replaced by an i32 everywhere (which removes the dependency on adt_const_params)
  2. The return type of foo is specified directly as MyType { Value(3) }
  3. A different, simpler expression is used:
fn foo(one: One) -> <One as Add<One>>::Output {
    one + one
}

I didn't find anything in my search through the issues, so I hope this isn't a duplicate.
Totally not a critical bug but it would be nice if the compiler could infer the type of the expression correctly. Currently, any expression involving more than a few inferred types seems to require an annotation.

Meta

rustc --version --verbose:

rustc 1.72.0-nightly (dd5d7c729 2023-06-02)
binary: rustc
commit-hash: dd5d7c729d4e8a59708df64002e09dbcbc4005ba
commit-date: 2023-06-02
host: x86_64-unknown-linux-gnu
release: 1.72.0-nightly
LLVM version: 16.0.4
Backtrace

Compiling comptest v0.1.0 (/home/toni/projects/comptest)
error[E0308]: mismatched types
  --> src/main.rs:36:5
   |
36 |     one + two
   |     ^^^^^^^^^ expected `Value(2)`, found `{const expr}`
   |
   = note: expected constant `Value(2)`
              found constant `{const expr}`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `comptest` (bin "main") due to previous error

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-genericsArea: const generics (parameters and arguments)C-bugCategory: This is a bug.F-adt_const_params`#![feature(adt_const_params)]`F-generic_const_exprs`#![feature(generic_const_exprs)]`P-lowLow priorityT-compilerRelevant to the compiler 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