rust-lang / rust-lang/rust

`generic_const_exprs` doesn't evaluate `size_of::<T>()` if `T` has a generic

Open
#144,021 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-const-generics C-bug F-generic_const_exprs T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code

I tried this code:

#![feature(generic_const_exprs)]

#[repr(transparent)]
struct FixedI8<const FRAC: i32>(i8);

impl<const FRAC: i32> FixedI8<FRAC> {
    fn from_be_bytes(bytes: [u8; 1]) -> Self {
        todo!()
    }
}

trait Fixed
where
    Self: Sized,
{
    fn from_be_bytes(bytes: [u8; size_of::<Self>()]) -> Self;
}

impl<const FRAC: i32> Fixed for FixedI8<FRAC> {
    fn from_be_bytes(bits: [u8; size_of::<Self>()]) -> Self {
        Self::from_be_bytes(bits)
    }
}

And this code:

#![feature(generic_const_exprs)]

use std::marker::PhantomData;

#[repr(transparent)]
struct FixedI8<T> {
    field: i8,
    _a: PhantomData<T>,
}

impl<T> FixedI8<T> {
    fn from_be_bytes(bytes: [u8; 1]) -> Self {
        todo!()
    }
}

trait Fixed
where
    Self: Sized,
{
    fn from_be_bytes(bytes: [u8; size_of::<Self>()]) -> Self;
}

impl<T> Fixed for FixedI8<T> {
    fn from_be_bytes(bits: [u8; size_of::<Self>()]) -> Self {
        Self::from_be_bytes(bits)
    }
}

I expected to see this happen: the code compiles, just like before the regression, or how it still compiles if the type has no generic:

#![feature(generic_const_exprs)]

#[repr(transparent)]
struct FixedI8(i8);

impl FixedI8 {
    fn from_be_bytes(bytes: [u8; 1]) -> Self {
        todo!()
    }
}

trait Fixed
where
    Self: Sized,
{
    fn from_be_bytes(bytes: [u8; size_of::<Self>()]) -> Self;
}

impl Fixed for FixedI8 {
    fn from_be_bytes(bits: [u8; size_of::<Self>()]) -> Self {
        Self::from_be_bytes(bits)
    }
}

Instead, this happened:

error[E0308]: mismatched types
  --> src/lib.rs:26:29
   |
26 |         Self::from_be_bytes(bits)
   |                             ^^^^ expected `1`, found `size_of::<Self>()`
   |
   = note: expected constant `1`
              found constant `size_of::<Self>()`
Version with regression

The PR that caused the regression is #140553.

A real crate affected by the regression is the alpha version of fixed (issue on that repo).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by compiling the two reproductions using the generic_const_exprs feature and confirm the mismatch between size_of::() and the expected constant. Then compare the behavior with the no-generic example and inspect PR #140553, which is identified as the regression source. Done means the generic implementations compile without the reported E0308 error.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.