Skip to content

Interaction between min_generic_const_args/associated_const_equality/ambig_generic_arg_kinds #58

Open
@BoxyUwU

Description

@BoxyUwU

What is this

This is a design document for const generics. Any discussions about its content should be on zulip. The conclusions of these discussions should then be edited back into this issue. Please do not post any comments directly in this issue.

Content

If we start supporting unbraced const path arguments, e.g. Foo<T::ASSOC> this could pose issues with associated const equality where we cannot tell from context if the T::ASSOC argument is for a const or type associated item. For example something like this:

#![feature(associated_const_equality, min_generic_const_args)]

trait Trait {
    type ASSOC;
    #[mgca_const]
    const ASSOC: usize;
}


trait HasConst {
    #[mgca_const]
    const ASSOC: usize;
}

trait HasType {
    type ASSOC;
}

fn foo<T: Trait<ASSOC = U::ASSOC>, U: HasConst + HasType>() {}

In the T: Trait<ASSOC binding it's not clear whether ASSOC refers to the assoc const or the assoc type. This means that we cannot use the position of the argument U::ASSOC to disambiguate whether it is a type or a const argument.

There is already some ambiguity when resolving associated type bindings as supertraits can introduce same-named associated types, currently we just prefer to resolve to associated items in the subtrait (though this does nothing to help with trait objects which wind up requiring unwriteable associated type bounds).

In order for ambig gen args + assoc const equality to not make matters worse when it comes to the lack of expressiveness when resolving assoc bindings, I think we should forbid having a mgca_const on a trait that also defines a same-named associated type. This would be fully backwards compatible as no mgca_const assoc items exist today. There is no need to introduce any restrictions for non-mgca_const associated consts as I do not expect us to want to support T: Trait<ASSOC for arbitrary non-type-system associated constants.

When resolving assoc item bindings we should also attempt to find either a type or a const so that we do not arbitrarily prefer a supertraits associated type over a subtraits associated const when either would have been valid:

#![feature(associated_const_equality, min_generic_const_args)]

trait SuperTrait {
    type ASSOC;
}

trait Trait: SuperTrait {
    #[mgca_const]
    const ASSOC: usize;
}


trait HasConst {
    #[mgca_const]
    const ASSOC: usize;
}

trait HasType {
    type ASSOC;
}

fn foo<T: Trait<ASSOC = U::ASSOC>, U: HasConst + HasType>() {}

T: Trait<ASSOC here should resolve to the associated constant on Trait not the associated type on SuperTrait as we already prefer subtrait assoc items over super trait assoc items see this example.

It is also worth noting that most of this is likely to not matter whatsoever in practice as the naming scheme for associated types and consts are different. Typically we would write type Assoc and const ASSOC: usize which does not result in equally named associated items. This is likely to only ever crop up in the case of single-letter associated items where type N and const N: usize are both written according to the expected naming guidelines

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-design-docsCategory: This is part of our design documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions