Failure to deduce bound when using const_generics and generic associated types

I have the following snippet of code:

#![no_std]

#![feature(generic_associated_types)]
#![feature(const_generics)]
#![feature(const_evaluatable_checked)]
#![feature(const_fn)]

#![allow(dead_code)]
#![allow(incomplete_features)]

use core::marker::PhantomData;
use core::mem::{size_of, align_of};

trait BoolConst {
    const VALUE : bool;
}

struct AlwaysTrueAsserter {}

impl BoolConst for AlwaysTrueAsserter {
    const VALUE : bool = true;
}

struct SizeAsserter<L,R>(PhantomData<(L,R)>);

impl<S,T> BoolConst for SizeAsserter<S, T> {
    const VALUE : bool = size_of::<S>() >= size_of::<T>() && 
                         align_of::<S>() % align_of::<T>() == 0;
}

trait Storage {
    type Asserter<T> : BoolConst;
}

struct HeapStorage {}

impl Storage for HeapStorage {
    type Asserter<T> = AlwaysTrueAsserter;
}

struct RawBox<T, S: Storage>(PhantomData<(T,S)>);

const fn size_assertion<S : Storage, T>() -> usize {
    S::Asserter::<T>::VALUE as usize - 1
}

impl<T, S : Storage> RawBox<T, S> {

    fn create(_val : T) -> Self where
        [u8 ; size_assertion::<S, T>()] : Sized
    {
        Self(PhantomData)
    }

}

fn create<T>(val : T) -> RawBox::<T, HeapStorage> 
    // this here is my issue
    where  [u8 ; size_assertion::<HeapStorage, T>()] : Sized
{
    RawBox::<T, HeapStorage>::create(val)
}

Ideally I would like the final create function to not need a bound because it's strictly unneeded. I expected the compiler to perform the following simplifications:

[u8 ; size_assert::<HeapStorage, T>()] : Sized =>
[u8 ; HeapStorage::Asserter<T>::VALUE as usize - 1] : Sized =>
[u8 ; AlwaysTrueAsserter::VALUE as usize - 1] : Sized =>
[u8 ; true as usize - 1] : Sized =>
[u8 ; 0] : Sized

Now, I know this is a lot of experimental features and that I shouldn't expect much but I am wondering if this is intended behavior or if it's an implementation issue. Should I expect this in the future? The RFC currently says this:

  • Unification of abstract const expressions: This RFC performs the most minimal unification of abstract const expressions possible - it essentially doesn't unify them. Possibly this will be an unacceptable UX for stabilization and we will want to perform some more advanced unification before we stabilize this feature.

I am assuming this may be a consequence of this paragraph ?

Without that bound the error message is pretty weird. It complains about an unconstrained generic constant and suggests to add a bound that's already there.

Also, adding the bound you have an issue with makes the playground's compiler ICE, both on stable and nightly.

the ICE was due to using deduction in the create function. Making it explicit makes the ICE go away. Edited with fix.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.