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

Tracking Issue for non-lifetime binders #108185

Open
1 of 4 tasks
compiler-errors opened this issue Feb 17, 2023 · 8 comments
Open
1 of 4 tasks

Tracking Issue for non-lifetime binders #108185

compiler-errors opened this issue Feb 17, 2023 · 8 comments
Labels
B-experimental Blocker: In-tree experiment; RFC pending, not yet approved or unneeded. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-non_lifetime_binders `#![feature(non_lifetime_binders)]` S-tracking-impl-incomplete Status: The implementation is incomplete. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@compiler-errors
Copy link
Member

This is a tracking issue for "non-lifetime binders" (rust-lang/types-team#81).
The feature gate for the issue is #![feature(non_lifetime_binders)].

About tracking issues

Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

Steps

Unresolved Questions

None yet

Implementation history

@compiler-errors compiler-errors added the C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC label Feb 17, 2023
@estebank estebank added the F-non_lifetime_binders `#![feature(non_lifetime_binders)]` label Feb 18, 2023
github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Mar 21, 2023
=== stdout ===
=== stderr ===
error[E0576]: cannot find associated type `Bt` in `Bt`
  --> /home/runner/work/glacier/glacier/ices/109090.rs:15:34
   |
4  |     type C;
   |     ------- associated type `C` defined here
...
15 |     for<'a, B> <B::C as Bt<'a>>::Bt: Bt, {}
   |                                  ^^
   |                                  |
   |                                  not found in `Bt`
   |                                  help: maybe you meant this associated type: `C`

error[E0404]: expected trait, found type parameter `Bt`
  --> /home/runner/work/glacier/glacier/ices/109090.rs:15:38
   |
3  | pub trait Bt {
   |           -- you might have meant to refer to this trait
...
13 | pub fn oopsie<Bt>()
   |               -- found this type parameter
14 | where
15 |     for<'a, B> <B::C as Bt<'a>>::Bt: Bt, {}
   |                                      ^^ not a trait

warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
 --> /home/runner/work/glacier/glacier/ices/109090.rs:1:12
  |
1 | #![feature(non_lifetime_binders)]
  |            ^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #108185 <rust-lang/rust#108185> for more information
  = note: `#[warn(incomplete_features)]` on by default

error[E0223]: ambiguous associated type
  --> /home/runner/work/glacier/glacier/ices/109090.rs:15:17
   |
15 |     for<'a, B> <B::C as Bt<'a>>::Bt: Bt, {}
   |                 ^^^^
   |
help: if there were a trait named `Example` with associated type `C` implemented for `B`, you could use the fully-qualified path
   |
15 |     for<'a, B> <<B as Example>::C as Bt<'a>>::Bt: Bt, {}
   |                 ~~~~~~~~~~~~~~~~~

error: aborting due to 3 previous errors; 1 warning emitted

Some errors have detailed explanations: E0223, E0404, E0576.
For more information about an error, try `rustc --explain E0223`.
==============
@compiler-errors
Copy link
Member Author

compiler-errors commented Mar 22, 2023

Having recently thoroughly reviewed the guidelines for experimenting with new feature gates (#109010 (comment) 😅), it dawned on me that that the T-types MCP that I did in rust-lang/types-team#81 may have been insufficient to justify landing experimental support for non-lifetime binders in the compiler...

Would anyone from @rust-lang/lang like to chime in here? Not exactly sure if it warrants a T-lang second + kicking off an FCP if we're trying to follow procedure, or if it's not worth it a month after landing the PR adding support. In any case, I'm trying to at least retroactively do my due dilligence here (and will do so for feature gates I add in the future in the future, sorry about that again lol).

Given the MCP from a T-types perspective, it's already confirmed that we on T-types would like to have non-lifetime binders support in the language for experimentation (especially given the pretty gnarly modifications to the trait solver that will be needed to get non-lifetime binders working fully), but if T-lang is not confident about this experimental feature (or would like an RFC), I guess I could un-land it as well. Let me know!

@nikomatsakis
Copy link
Contributor

I'm happy to serve as a lang-team second here. I don't think we need to do the full MCP, but if anyone on @rust-lang/lang has concerns about the idea of supporting things like for<T>, please raise them now.

Just for good measure, I'll nominate for lang team triage meeting.

@rustbot labels +I-lang-nominated

@rustbot rustbot added the I-lang-nominated Nominated for discussion during a lang team meeting. label Mar 22, 2023
@scottmcm
Copy link
Member

To me, accepting GATs was a de-facto "yes, you can experiment with for<T>", since the parallels are so strong.

@nikomatsakis
Copy link
Contributor

@rustbot labels -I-lang-nominated

@rustbot rustbot removed the I-lang-nominated Nominated for discussion during a lang team meeting. label Apr 4, 2023
github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Jul 1, 2023
=== stdout ===
=== stderr ===
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
 --> /home/runner/work/glacier/glacier/ices/113016.rs:1:12
  |
1 | #![feature(non_lifetime_binders)]
  |            ^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #108185 <rust-lang/rust#108185> for more information
  = note: `#[warn(incomplete_features)]` on by default

warning: type parameter `f` should have an upper camel case name
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:21
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                     ^ help: convert the identifier to upper camel case (notice the capitalization): `F`
  |
  = note: `#[warn(non_camel_case_types)]` on by default

error: `impl Trait` can only mention type parameters from an fn or impl
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:53
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                     - type parameter declared here  ^

error[E0658]: anonymous lifetimes in `impl Trait` are unstable
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:58
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                                                          ^^ expected named lifetime parameter
  |
  = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
  |
5 | fn main<'a>(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + 'a>) {}
  |        ++++                                                  ~~

error[E0658]: anonymous lifetimes in `impl Trait` are unstable
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:30
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                              ^^ expected named lifetime parameter
  |
  = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
  |
5 | fn main<'a>(x: impl for<f> Trait<'a, Assoc = impl Trait<f> + '_>) {}
  |        ++++                      ~~

error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:24
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                        ^^^^^-------------------------------- help: remove these generics
  |                        |
  |                        expected 0 lifetime arguments
  |
note: trait defined here, with 0 lifetime parameters
 --> /home/runner/work/glacier/glacier/ices/113016.rs:3:7
  |
3 | trait Trait<Input> {}
  |       ^^^^^

error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:24
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                        ^^^^^ expected 1 generic argument
  |
note: trait defined here, with 1 generic parameter: `Input`
 --> /home/runner/work/glacier/glacier/ices/113016.rs:3:7
  |
3 | trait Trait<Input> {}
  |       ^^^^^ -----
help: add missing generic argument
  |
5 | fn main(x: impl for<f> Trait<'_, Input, Assoc = impl Trait<f> + '_>) {}
  |                                +++++++

error[E0220]: associated type `Assoc` not found for `Trait`
 --> /home/runner/work/glacier/glacier/ices/113016.rs:5:34
  |
5 | fn main(x: impl for<f> Trait<'_, Assoc = impl Trait<f> + '_>) {}
  |                                  ^^^^^ associated type `Assoc` not found

error: aborting due to 6 previous errors; 2 warnings emitted

Some errors have detailed explanations: E0107, E0220, E0658.
For more information about an error, try `rustc --explain E0107`.
==============
github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Sep 26, 2023
=== stdout ===
=== stderr ===
error[E0412]: cannot find type `V` in this scope
 --> /home/runner/work/glacier/glacier/ices/112574.rs:7:4
  |
7 | }> V: IntoIterator
  |    ^ not found in this scope
  |
help: you might be missing a type parameter
  |
3 | pub fn bar<V>()
  |           +++

warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
 --> /home/runner/work/glacier/glacier/ices/112574.rs:1:12
  |
1 | #![feature(non_lifetime_binders)]
  |            ^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #108185 <rust-lang/rust#108185> for more information
  = note: `#[warn(incomplete_features)]` on by default

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0412`.
==============
github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Jan 5, 2024
=== stdout ===
=== stderr ===
error: expected one of `:`, `@`, or `|`, found `)`
 --> /home/runner/work/glacier/glacier/ices/113017.rs:3:22
  |
3 | pub fn String<V>(elem)
  |                      ^ expected one of `:`, `@`, or `|`
  |
  = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a `self` type, give it a parameter name
  |
3 | pub fn String<V>(self: elem)
  |                  +++++
help: if this is a parameter name, give it a type
  |
3 | pub fn String<V>(elem: TypeName)
  |                      ++++++++++
help: if this is a type, explicitly ignore the parameter name
  |
3 | pub fn String<V>(_: elem)
  |                  ++

error[E0261]: use of undeclared lifetime name `'a`
 --> /home/runner/work/glacier/glacier/ices/113017.rs:5:8
  |
5 |     V: 'a,
  |        ^^ undeclared lifetime
  |
  = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
  |
5 |     for<'a> V: 'a,
  |     +++++++
help: consider introducing lifetime `'a` here
  |
3 | pub fn String<'a, V>(elem)
  |               +++

error[E0261]: use of undeclared lifetime name `'a`
 --> /home/runner/work/glacier/glacier/ices/113017.rs:6:39
  |
6 |     for<const N: usize = { || {}}> V: 'a, 
  |                                       ^^ undeclared lifetime
  |
help: consider making the bound lifetime-generic with a new `'a` lifetime
  |
6 |     for<'a, const N: usize = { || {}}> V: 'a, 
  |         +++
help: consider introducing lifetime `'a` here
  |
3 | pub fn String<'a, V>(elem)
  |               +++

error[E0637]: `&` without an explicit lifetime name cannot be used here
 --> /home/runner/work/glacier/glacier/ices/113017.rs:7:26
  |
7 |     for<C2: , R2, R3: > <&str as IntoIterator>::Item: 'static,
  |                          ^ explicit lifetime name needed here
  |
help: consider introducing a higher-ranked lifetime here
  |
7 |     for<'a> for<C2: , R2, R3: > <&'a str as IntoIterator>::Item: 'static,
  |     +++++++                       ++

error[E0658]: only lifetime parameters can be used in this context
 --> /home/runner/work/glacier/glacier/ices/113017.rs:6:15
  |
6 |     for<const N: usize = { || {}}> V: 'a, 
  |               ^
  |
  = note: see issue #108185 <rust-lang/rust#108185> for more information
  = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable

error[E0658]: only lifetime parameters can be used in this context
 --> /home/runner/work/glacier/glacier/ices/113017.rs:7:9
  |
7 |     for<C2: , R2, R3: > <&str as IntoIterator>::Item: 'static,
  |         ^^    ^^  ^^
  |
  = note: see issue #108185 <rust-lang/rust#108185> for more information
  = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable

warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
 --> /home/runner/work/glacier/glacier/ices/113017.rs:1:12
  |
1 | #![feature(generic_const_exprs)]
  |            ^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #76560 <rust-lang/rust#76560> for more information
  = note: `#[warn(incomplete_features)]` on by default

error: defaults for generic parameters are not allowed in `for<...>` binders
 --> /home/runner/work/glacier/glacier/ices/113017.rs:6:9
  |
6 |     for<const N: usize = { || {}}> V: 'a, 
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0601]: `main` function not found in crate `113017`
 --> /home/runner/work/glacier/glacier/ices/113017.rs:8:3
  |
8 | {}
  |   ^ consider adding a `main` function to `/home/runner/work/glacier/glacier/ices/113017.rs`

error[E0277]: `&str` is not an iterator
 --> /home/runner/work/glacier/glacier/ices/113017.rs:3:1
  |
3 | / pub fn String<V>(elem)
4 | | where
5 | |     V: 'a,
6 | |     for<const N: usize = { || {}}> V: 'a, 
7 | |     for<C2: , R2, R3: > <&str as IntoIterator>::Item: 'static,
  | |______________________________________________________________^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
  |
  = help: the trait `Iterator` is not implemented for `&str`
  = note: required for `&str` to implement `IntoIterator`

error[E0277]: `&str` is not an iterator
 --> /home/runner/work/glacier/glacier/ices/113017.rs:3:8
  |
3 | pub fn String<V>(elem)
  |        ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
  |
  = help: the trait `Iterator` is not implemented for `&str`
  = note: required for `&str` to implement `IntoIterator`

error: aborting due to 10 previous errors; 1 warning emitted

Some errors have detailed explanations: E0261, E0277, E0601, E0637, E0658.
For more information about an error, try `rustc --explain E0261`.
==============
@rebenkoy

This comment has been minimized.

@compiler-errors
Copy link
Member Author

@rebenkoy: Thanks, but no need to comment on this tracking issue -- opening a bug report is sufficient. The feature is marked as incomplete because non-lifetime binders still has bugs. That issue will be fixed in due time.

warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
 --> src/lib.rs:1:12
  |
1 | #![feature(non_lifetime_binders)]
  |            ^^^^^^^^^^^^^^^^^^^^

@zvolin
Copy link

zvolin commented Jan 17, 2024

I'm curious if that could work with const generics. I'm currently working with Multihash and MultihashDigest and it's often a pain to propagate the parameter all the time. Consider this example:

trait ToArray<const N: usize> {
    fn to_array(&self) -> [u8; N];
}

struct Array<const N: usize>([u8; N]);

impl<const N: usize> ToArray<N> for Array<N> {
    fn to_array(&self) -> [u8; N] {
        self.0
    }
}

struct Vec2(Vec<u8>);

impl Vec2 {
    fn from_arr<const N: usize, A>(other: A) -> Self
    where
        A: ToArray<N>,
    {
        Self(other.to_array().to_vec())
    }
}

fn main() {
    let other = Array([0; 20]);
    Vec2::from_arr::<20, _>(other);
}

Specifying this 20 doesn't read nice. I'd love to be able to write it like so

impl Vec2 {
    fn from_arr<A>(other: A) -> Self
    where
        A: for<const N: usize> ToArray<N>,
    {
        Self(other.to_array().to_vec())
    }
}

fn main() {
    let other = Array([0; 20]);
    Vec2::from_arr(other);
}

@c3potheds
Copy link

impl Vec2 {
    fn from_arr<A>(other: A) -> Self
    where
        A: for<const N: usize> ToArray<N>,
    {
        Self(other.to_array().to_vec())
    }
}

fn main() {
    let other = Array([0; 20]);
    Vec2::from_arr(other);
}

I don't think that would do what you think. The bounds you put on A say "A can be turned into an array of any size", not "A can be turned into an array of some size".

You'd want to use:

impl Vec2 {
    fn from_arr<A, const N: usize>(other: A) -> Self
    where
        A: ToArray<N>,
    {
        Self(other.to_array().to_vec())
    }
}

I could imagine a FromArray<const N: usize> trait where a universal type would be useful, though:

trait FromArray<T, const N: usize> {
    fn from_array(a: [T; N]) -> Self:
}

// Implement the trait for one specific size.
impl<T> FromArray<T, 2> for (T, T) {
    fn from_array(a: [T; 2]) -> Self {
        (a[0], a[1])
    }
}

// Implement the trait for all sizes.
impl<T, const N: usize> FromArray<T, N> for Vec<T> {
    fn from_array(a: [T; N]) -> Self {
        a.into_iter().collect()
    }
}

// Require something that implements the trait for all sizes.
fn create_test_data<A>() -> [A; 3]
where
    for <const N: usize> A: FromArray<i32, N>,
{
    [
        A::from_array([0]),
        A::from_array([0, 1]),
        A::from_array([0, 1, 2]),
    ]
}

@fmease fmease added T-types Relevant to the types team, which will review and decide on the PR/issue. B-experimental Blocker: In-tree experiment; RFC pending, not yet approved or unneeded. S-tracking-impl-incomplete Status: The implementation is incomplete. B-unstable Blocker: Implemented in the nightly compiler and unstable. labels Feb 28, 2024
@fmease fmease changed the title Tracking Issue for Non-lifetime Binders Tracking Issue for non-lifetime binders May 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-experimental Blocker: In-tree experiment; RFC pending, not yet approved or unneeded. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-non_lifetime_binders `#![feature(non_lifetime_binders)]` S-tracking-impl-incomplete Status: The implementation is incomplete. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

9 participants