Skip to content

Remove type literals from the language. #2393

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

Open
lrhn opened this issue Aug 8, 2022 · 2 comments
Open

Remove type literals from the language. #2393

lrhn opened this issue Aug 8, 2022 · 2 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@lrhn
Copy link
Member

lrhn commented Aug 8, 2022

I know this is a long shot.

Dart allows expressions like int and List<int> to evaluate to Type instances representing those types.
That's very convenient when you want to have a type literal, but with dart:mirrors being deprecated, and Type objects being useless for most things (all they support is equality), there shouldn't be that many Type instances. In most cases, a type parameter is a better solution to the problem people are trying to solve using Type objects. If anything, the syntactic ease of creating Type objects is encouraging too many uses.

The syntax of type literals has already gotten in the way of using the same syntax for something else. The ClassName.new tear-off syntax for tearing off the unnamed constructor was only introduced because ClassName was already taken by the type literal.

With the constuctor tear-off language feature, Dart started allowing List<int> as a type literal too. That also allows us to define a type alias like typedef typeof<T> = T;, so that typeof<any type> can create a Type object for any type, even those not allowed as type literals.

So, I suggest we introduce a canonical typedef typeof<T> = T; in the platform libraries, and disallowed any type literal other than typeof<some type>.

All existing uses of type literals need to be migrated. That can be entirely automatized, but it does require running dart-fix on all the code.
We will be using language versioning, because the typeof syntax is backwards compatible, and we can start warning and hinting that you should fix the code a few versions earlier than when we actually remove the feature.
All you have to do to migrate will be running dart fix. (And existing code will keep working at the prior language versions as long as we support those).

This will allow us to:

  • Use ClassName as the constructor tear-off.
  • Not have a semi-arbitrary difference between types we allow literals for, and types we don't (functions, records).
  • Maybe encourage people to use something else than Type objects. If you have your own class Type<T> to represent types, it's shorter to write than typeof<T>, and can have more features.
  • Give better error messages when people use a type name incorrectly (classical example: if (T is int) to check if a type variable is some type, it instead gives no error and is always false).
@lrhn lrhn added the feature Proposed language feature that solves one or more problems label Aug 8, 2022
@marcotas
Copy link

marcotas commented Aug 10, 2022

@lrhn, I'm building a server framework in pure dart to serve all front-end flavours (flutter, tailwindcss, vue, react, svelt etc). So the framework trust on mirrors to inject depencies based on types.

For example if you define a controller like below, you will have the request and repository objects injected into your controller method automatically based on mirrors that recursively tries to resolve all the dependencies if you didn't register them in the service container.

class UserController extends Controller {
  updateAmount(int id, Request request, UserRepository repository) {
    ...
    await repository.updateBillingAmount(request.get('amount'));
    ...
  }
}

I don't want to change this behavior but I'd like to know/understand how I should be able to do this without mirrors. What would be the best or official way to use reflections without mirrors?

(Sorry If this question was massively asked dart team and if I'm missing something here. I'm new to dart language but I love it)

I appreciate any help or suggestions on this. Thank you

@Levi-Lesches
Copy link

dart:mirrors allows you to introspect the code running, meaning its reflection is all done at runtime. The alternative is code generation, in which you use the Analyzer to inspect code before it's compiled and add your own classes/functions/etc. to it. I'm not sure how your project works, but you might be able to convert it to code generation instead of reflection. With this approach, you would do the same type of analysis as you are now but with variables known at compile-time, and then generate code to do what you want.

In this case, you may be interested in the up-and-coming macros feature, which makes code generation much easier to work with and officially supported by the language.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants