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

Enum shorthands using a type alias and invoking a constructor #4183

Open
eernstg opened this issue Nov 28, 2024 · 2 comments
Open

Enum shorthands using a type alias and invoking a constructor #4183

eernstg opened this issue Nov 28, 2024 · 2 comments
Labels
brevity A feature whose purpose is to enable concise syntax, typically expressible already in a longer form enum-shorthands Issues related to the enum shorthands feature. question Further information is requested

Comments

@eernstg
Copy link
Member

eernstg commented Nov 28, 2024

Consider the following program, which assumes https://github.com/dart-lang/language/blob/main/working/3616%20-%20enum%20value%20shorthand/proposal-simple-lrhn.md:

class A<X> {
  final X x;
  A(this.x);
  AIntAlias get aInt => A(25);
}

typedef AIntAlias = A<int>;

void main() {
  AIntAlias _ = .new('Hello!').aInt;
}

The meaning of .new('Hello!').aInt is AIntAlias.new('Hello!').aInt, which is a compile-time error.

I think we would want to add a few words to the spec saying that the context type is subjected to a full alias expansion before we attempt to strip off the actual type arguments and re-compute them by inference.

@dart-lang/language-team, do you see any reason not to do this?

@eernstg eernstg added question Further information is requested enum-shorthands Issues related to the enum shorthands feature. brevity A feature whose purpose is to enable concise syntax, typically expressible already in a longer form labels Nov 28, 2024
@lrhn
Copy link
Member

lrhn commented Nov 28, 2024

The meaning of .new('Hello!').aInt should be A.new('Hello!').aInt (or equivalent to, in a way that avoids A being shadowed) .

The context type scheme is A<int>, which is the declared type of _.
The static namespace denoted by that context type scheme is the static namespace of the A declaration.

The context type scheme is a type scheme, which means it's a type-extended-with-_, so type aliases have necessarily already been expanded. Type aliases do not introduce types, just a way to denote a type, so there is no entity in the static type system that represents a type alias or instantiated type alias. That's entirely a syntactic concept, the syntactic type clause AIntAlias denotes the type A<int>, just like the type clause A<int>.

If the static type system can actually represent a type alias, I'll need to redefine "namespace denoted by context type scheme" to go through the alias, maybe the same way we do for accessing statics through an alias, but likely not exaclty, since I don't want to get the type arguments from the context type.

A type alias denotes the static namespace S if its RHS denotes the static namespace S.
(A type variable denotes no static namespace.)

But I don't think TypeAliasName<Type> is a type, so it's a category error to even ask whether a type scheme, can be a type alias.

We can add a note in the specification that context types introduced by types denoted using type aliases will not refer to the type alias, only to the denoted type, so that a type alias was involved has no effect on static shorthands.

@eernstg
Copy link
Member Author

eernstg commented Nov 29, 2024

It's a good point that the context entity is a context type schema (which is a context type in the special case where _ doesn't occur), and hence it isn't syntax. In particular, there is no source code that directly denotes a context type schema.

Nevertheless, several specification documents do take care to call out type aliases explicitly (e.g., inference.md, normalization.md, upper-lower-bounds.md, and the language specification), indicating that type aliases have been fully expanded before the rules in subsequent sections of those documents are applied. So it probably wouldn't hurt to mention it.

In any case, we do agree that the original example should work as follows:

void main() {
  AIntAlias _ = A.new('Hello!').aInt;
}

which is what I wanted to clarify in the first place. I created #4186 to add a sentence to this effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
brevity A feature whose purpose is to enable concise syntax, typically expressible already in a longer form enum-shorthands Issues related to the enum shorthands feature. question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants