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

Disambiguate between () as type and as value in const generic arguments #66615

Open
varkor opened this issue Nov 21, 2019 · 15 comments
Open

Disambiguate between () as type and as value in const generic arguments #66615

varkor opened this issue Nov 21, 2019 · 15 comments
Labels
A-const-generics Area: const generics (parameters and arguments) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@varkor
Copy link
Member

varkor commented Nov 21, 2019

#![feature(const_generics)]

trait Trait<const U: ()> {}

impl Trait<()> for () {} // error (expected const argument, found type argument)

I wonder if we can resolve the unit value correctly here (though maybe it'll require a small hack), because this is quite unfortunate.

@varkor varkor added A-const-generics Area: const generics (parameters and arguments) F-const_generics `#![feature(const_generics)]` labels Nov 21, 2019
@cramertj
Copy link
Member

Note that impl Trait<{()}> for () {} works and that impl Trait<(5, 5, 5)> for () {} results in

error: expected type, found `5`
 --> src/lib.rs:5:13
  |
5 | impl Trait<(5, 5, 5)> for () {}
  |             ^ expected type

@jplatte
Copy link
Contributor

jplatte commented Jan 2, 2020

Would this require going back to the initial idea of trying to parse generic arguments as either types or values, disambiguating at a later stage where we know whether the parameter is a const or a type?

@varkor
Copy link
Member Author

varkor commented Jan 2, 2020

@jplatte: this isn't going to be very convenient to fix. The problem is that we aren't going to be able to disambiguate until type-checking itself. (This is the same problem as the snippet below, which currently also fails, because it can't tell what X is by name resolution alone.) We're going to need to pass more information into type-checking to disambiguate later, yes, but I suspect it won't be straightforward. If you want to investigate, though, this (and the related examples) would be a really nice papercut to fix :)

#![feature(const_generics)]

struct X;

struct S<const X: u8>;

impl<const X: u8> S<X> {} // error: wrong number of const arguments: expected 1, found 0

@jplatte
Copy link
Contributor

jplatte commented Jan 2, 2020

Okay so in cases we can't tell whether we've got a type or a value during parsing, we need to try resolving both, correct? Is that already done or is value resolution only done if type resolution fails?

@varkor
Copy link
Member Author

varkor commented Jan 3, 2020

The problem is that () (and X in the above example) will resolve correctly in both the type and value namespace (as the two namespaces don't collide). We can't tell at resolution which is intended: we need type information for that. Currently for names (e.g. X), value resolution is only attempted if type resolution fails, so types take precedence.

@jplatte
Copy link
Contributor

jplatte commented Jan 3, 2020

Yeah, that's what I was thinking. So we'll need to keep around both a resolved type and a resolved value in cases like the one you showed above.

And in cases where something can't be resolved (at all or in the right namespace) but the number of arguments given is still correct, I guess we will need yet more information to produce a reasonable error message.

@lcnr
Copy link
Contributor

lcnr commented Mar 26, 2020

@rustbot claim

@rustbot rustbot self-assigned this Mar 26, 2020
@petrochenkov
Copy link
Contributor

Is it useful to disambiguate between () type and () value in generic argument?

The disambiguation is done for IDENT type vs IDENT value only because it's a super common case, so we can afford paying for it with more complexity and special cases. I'm not sure this is the case for ().

@varkor
Copy link
Member Author

varkor commented Mar 26, 2020

It makes the language more consistent, though it's definitely a less useful case than with identifiers. Let's see how much additional complexity it adds to support this case, and if it seems disproportionate, then we can re-evaluate.

@lcnr
Copy link
Contributor

lcnr commented Mar 29, 2020

@rustbot release-assignment

@rustbot rustbot removed their assignment Mar 29, 2020
@varkor
Copy link
Member Author

varkor commented Sep 13, 2020

I think at the very least we need to improve diagnostics here for min_const_generics, though I would prefer a complete solution.
(Alternatively, maybe unit type will/should be disallowed for min_const_generics.)

@lcnr
Copy link
Contributor

lcnr commented Sep 13, 2020

I think we disallow unit rn, so that's the easier solution 😆

@varkor
Copy link
Member Author

varkor commented Sep 13, 2020

Yes, if we don't have compound data types at all, it doesn't make sense to have unit anyway.

@varkor
Copy link
Member Author

varkor commented Oct 9, 2020

This is essentially the same problem as getting multi-segment paths working with const generics (#66104 (comment) and Zulip conversation), which really would be useful to allow.

@lcnr
Copy link
Contributor

lcnr commented Jun 28, 2022

visited during project-const-generics triage, added to rust-lang/project-const-generics#42 but don't expect us to make much progress here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants