Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't force the user to specify effects for projections #3

Closed
fee1-dead opened this issue Aug 9, 2024 · 2 comments
Closed

Don't force the user to specify effects for projections #3

fee1-dead opened this issue Aug 9, 2024 · 2 comments

Comments

@fee1-dead
Copy link
Member

fee1-dead commented Aug 9, 2024

This is a problem exclusively for when there is a const RUNTIME: bool param added to all const traits.

Suppose we have the following function:

const fn foo<T: ~const Add>(a: T, b: T) -> T::Output { a + b }

We'd expect this to pass compilation, but if Add has a runtime parameter, T::Output needs to exclusively refer to the not-const version of the trait for backwards compatibility, which means this code would not compile. In fact, it is required to write the function like so, if traits had booleans attached to them:

const fn foo<T: ~const Add>(a: T, b: T) -> <T as ~const Add>::Output { a + b }

This can add a lot of surface syntax noise as people, expectedly, use projections a lot. And constifying functions would lead to these projections all having to specify which context they are in:

  • T::Output for non-const
  • <T as ~const Add>::Output for binding constness to context (in const fns)
  • <T as const Add>::Output for always-const (in consts and etc.)

But we shouldn't need to do this! We can always be sure that the same type T implementing a trait Foo will always have <T as Foo>::X == <T as const Foo>::X if they do implement both the non-const and always-const version of the trait. This is due to the fact that we always store the "which context this type is in" in types themselves, leading to them being locked to a specific context.

For example, let's say in the future const closures are implemented. We always know which context this closure is in based on its type. (Note that closures will never implement both non-const and always-const, only exactly one context, see rust-lang/rust#119718.) That means the same closure (suppose we bind its constness to a generic param, such that it will eventually figure out what constness it is) used in a const context and in a non-const context will be two different types (imagine one with <true> attached to it and the other with <false>, therefore we never have to worry about different kinds of projections giving us different types.

@fee1-dead
Copy link
Member Author

fee1-dead commented Aug 9, 2024

On second thought, my last two paragraphs could be wrong. There are types that are not locked to specific contexts like u32 and trait impls for them could easily project to different types should we start allowing things like function pointers to be specified as always const or not:

#[const_trait]
trait Foo {
    type Bar: ~const FnOnce();
}

impl const Foo for u32 {
    type Bar = ~const fn();
}

@compiler-errors
Copy link
Member

I believe this is also finished? Since fee1-dead's rewrite to use associated consts, effects are fully "late-bound", so this problem doesn't matter anymore.

I do think we should open a follow-up issue about WTF to do with ~const fn(), b/c that comes with its own set of really weird problems (also because it would be a distinct type from fn(), and that has tons of ecosystem implications).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants