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

Can't use type arguments with statics and constants #25572

Open
Hixie opened this issue Jan 25, 2016 · 7 comments
Open

Can't use type arguments with statics and constants #25572

Hixie opened this issue Jan 25, 2016 · 7 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). type-enhancement A request for a change that isn't a bug

Comments

@Hixie
Copy link
Contributor

Hixie commented Jan 25, 2016

This code doesn't compile:

class Foo<T> { const Foo(); static Foo<T> bar() => const Foo<T>(); }

This prevents us from having statics that walk a tree looking for an instance of a specific instance (e.g. walking a tree looking for a Foo<int>).

@kevmoo kevmoo added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label Feb 1, 2016
@munificent
Copy link
Member

munificent commented Dec 13, 2016

Right. There are a couple of limitations in play here:

  1. Dart considers static members to be part of the underlying class, independent of its generic type arguments. In Dart's world, there is no such concept as Foo<int>.bar(), only Foo.bar().

  2. Generic type parameters are not in scope inside const expressions. Even if you were to make bar() an instance method, you still can't put const Foo<T>(); in the body because T is not even in scope.

    Strangely, the VM does silently allow you to refer to T inside the body of the method in your example. That seems like a bug to me. The analyzer correctly flags it as an error.

If you don't need to use const here, you could address this with a generic method:

class Foo<T> {
  const Foo();
  static Foo<S> bar<S>() => const Foo<S>();
}

Foo.bar<int>(); // Note the <int> is after the method, not the class.

However, the VM does not currently reify type arguments for generic methods, so this won't actually let you use T at runtime.

@Hixie
Copy link
Contributor Author

Hixie commented Dec 13, 2016

I believe this issue is basically asking for #1 and #2 above to be changed. :-)

@munificent
Copy link
Member

Yup! I just wanted to note down some context.

For what it's worth, I agree with you, though putting type annotations in scope inside const expressions adds a surprising amount of complexity.

@Hixie
Copy link
Contributor Author

Hixie commented Dec 14, 2016

I bet.

@munificent
Copy link
Member

See also: #26291.

I'll leave this one open too since that one is restricted to const which this issue also talks about static members.

@lrhn lrhn added the type-enhancement A request for a change that isn't a bug label Jun 25, 2018
@lrhn
Copy link
Member

lrhn commented Jun 25, 2018

The const usage is unlikely to happen. The static usage is tricky - it would mean that you can write Foo<int>.staticMember() and the static member has access to the int. I'll keep it open as a request for that part.

These days you can just write Foo.staticMember<int>(), so the feature is probably not as needed any more.
Can we close this issue?

@werediver
Copy link

The fact that type parameters are non-const (while I'd expect the compiler to type-check / infer every parametrization statically) makes it more difficult to refer to type parameters in annotations (and thus in code generators).

For instance, I'm working on a sum-types [-alike classes] generator, sum_types_generator, which would benefit from annotations being able to refer to type parameters of an annotated declaration to generate generic sum-types:

@SumType([
  @Case<T>(name: "some"), // Not possible, because `T` is not a const-expression
  @Case<void>(name: "none")
])
mixin _Optional<T> implements _OptionalBase {}

(one can think of generating Either<Left, Right> instead)

This still can be worked around with a much less nice @CaseT(0, name: "some"), but that has a much less nice UX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

5 participants