From 197fa5b2ed80eb2a0ac60a6bc2f98b9a9abde424 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 1 Nov 2018 11:56:27 +0100 Subject: [PATCH 1/7] Adding feature specification --- .../feature-specification.md | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 accepted/future-releases/generalized-typedef-2018/feature-specification.md diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md new file mode 100644 index 0000000000..139d7374cf --- /dev/null +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -0,0 +1,135 @@ +# Design Document for Generalized Type Aliases 2018. + +Author: eernst@google.com (@eernst). + +Version: 0.1. + + +## Motivation and Scope + +Parameterized types in Dart can be verbose. An example is here: + +```dart +Map, + SnackBar> +``` + +Such verbose types may be needed repeatedly, and there may also be a need +for several different variants of them, only differing in +specific subterms. For instance, we might also need this one: + +```dart +Map, + SandwichBar> +``` + +This type is unlikely to work as intended if the second type argument of +`Map` is changed to `SnackBar`, but such mistakes could easily happen +during development. It may not even be easy to detect exactly where the +mistake occurred, in cases where the erroneous type is used in some +declaration, and expressions whose types depend on that declaration +unexpectedly get flagged as compile-time errors, or the IDE completions +in such expressions fail to list some of the expected choices. + +This document describes how type aliases are generalized in Dart 2.2 +to make such verbose types more concise and consistent. + + +## Feature Specification + +The precise definition of the changes is given in the language +specification, with a proposed form in +[this CL](https://dart-review.googlesource.com/c/sdk/+/81414). +The following sections summarize the changes. + + +### Syntax + +The grammar is modified as follows in order to support this feature: + +``` +typeAlias ::= + metadata 'typedef' typeAliasBody | + metadata 'typedef' identifier typeParameters? '=' type ';' // CHANGED +``` + +*The modification is that a type alias declaration of the form that uses +`=` can define the type alias to denote any type, not just a function +type.* + + +### Static Analysis + +There is no change in the treatment of existing syntax, so we describe only +the treatment of syntactic forms that can be new when this feature is added. + +The effect of a non-generic type alias declaration of the form that uses +`=` with name `F` is to introduce a type named `F` into the library scope +of the enclosing library, denoting the type on the right hand side of `=` +in that declaration. + +*This is not new, but it applies to a larger set of situations now that the +right hand side can be any type. Let us call that type on the right hand +side `T`. This means that `F` can be used as a type annotation, and the +entity which is given type `F` is considered to have type `T`, with the +same meaning as in the declaration of `F` (even if some declaration in the +current library gives a new meaning to an identifier in `T`).* + +The effect of a generic type alias declaration of the form + +```dart +typedef F = T; +``` + +where metadata is omitted but may be present, is to introduce a mapping +from type argument lists to types into the library scope of the enclosing +library, such that a parameterized type of the form `F` where `F` +resolves to the above declaration denotes the type `[T1/X1 .. Tk/Xk]T`. + +Let _F_ be a generic type alias of the form that uses `=` with type +parameter declarations +_X1 extends B1 .. Xk extends Bk_. +It is a compile-time error unless satisfaction of the declared bounds +_B1 .. Bk_ implies that all all types that occur on +the right hand side of `=` are well-bounded. + +Let `F` be a parameterized type where `F` denotes a declaration of +the form +```dart +typedef F = T; +``` +where metadata is omitted but may be present. It is a compile-time error if +`n != k` and it is a compile-time error if `F` is not well-bounded. + +*These errors are not new, but they apply to a larger set of situations now +that the right hand side can be any type.* + +When a `typeName` (*that is, `identifier` or `identifier.identifier`*) +that resolves to a generic type alias declaration is used as a type or +evaluated as an expression, it is subject to instantiation to bound and +type inference. + +*This treatment of generic type aliases is again the same as it was +previously, but it involves a larger set of types.* + +### Dynamic Semantics + +*The dynamic semantics relies on elaborations on the program performed +during compilation. In particular, instantiation to bound and type +inference has occurred, and hence some `typeName`s in the source code have +been transformed into parameterized types, even when a type is used as an +expression such that it would be a syntax error to actually add the type +arguments explicitly in the source program. This means that every generic +type alias receives actual type arguments at all locations where it is +used. At run time it is also known that the program has no compile-time +errors.* + +For dynamic type checks, type tests, and expression evaluations, an +identifier `F` resolving to a non-generic type alias and a parameterized +type `F` where `F` resolves to a generic type alias are treated +identically to the same type checks, type tests, and expression evaluations +performed with the type denoted by that identifier or parameterized type. + +## Versions + +* Nov 1st, 2018, version 0.1: Initial version of this document. From 3b2755baee2700d0727da15620b00fef37c6fd2c Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 1 Nov 2018 13:49:49 +0100 Subject: [PATCH 2/7] Review response --- .../feature-specification.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md index 139d7374cf..04e65c448c 100644 --- a/accepted/future-releases/generalized-typedef-2018/feature-specification.md +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -64,9 +64,9 @@ There is no change in the treatment of existing syntax, so we describe only the treatment of syntactic forms that can be new when this feature is added. The effect of a non-generic type alias declaration of the form that uses -`=` with name `F` is to introduce a type named `F` into the library scope -of the enclosing library, denoting the type on the right hand side of `=` -in that declaration. +`=` with name `F` is to bind the name `F` in the library scope of the +enclosing library to the type denoted by the right hand side of `=` in that +declaration. *This is not new, but it applies to a larger set of situations now that the right hand side can be any type. Let us call that type on the right hand @@ -81,10 +81,10 @@ The effect of a generic type alias declaration of the form typedef F = T; ``` -where metadata is omitted but may be present, is to introduce a mapping -from type argument lists to types into the library scope of the enclosing -library, such that a parameterized type of the form `F` where `F` -resolves to the above declaration denotes the type `[T1/X1 .. Tk/Xk]T`. +where metadata is omitted but may be present, is to bind the name `F` in +the library scope of the enclosing library to a mapping from type argument +lists to types, such that a parameterized type of the form `F` is +an application of that mapping that denotes the type `[T1/X1 .. Tk/Xk]T`. Let _F_ be a generic type alias of the form that uses `=` with type parameter declarations From ab9671163855c96df80f0ed3b6aaa54de2bbeb34 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 1 Nov 2018 14:51:16 +0100 Subject: [PATCH 3/7] Added a couple of missing words --- .../feature-specification.md | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md index 04e65c448c..51ffbaa5d3 100644 --- a/accepted/future-releases/generalized-typedef-2018/feature-specification.md +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -106,8 +106,7 @@ that the right hand side can be any type.* When a `typeName` (*that is, `identifier` or `identifier.identifier`*) that resolves to a generic type alias declaration is used as a type or -evaluated as an expression, it is subject to instantiation to bound and -type inference. +evaluated as an expression, it is subject to instantiation to bound. *This treatment of generic type aliases is again the same as it was previously, but it involves a larger set of types.* @@ -115,20 +114,22 @@ previously, but it involves a larger set of types.* ### Dynamic Semantics *The dynamic semantics relies on elaborations on the program performed -during compilation. In particular, instantiation to bound and type -inference has occurred, and hence some `typeName`s in the source code have -been transformed into parameterized types, even when a type is used as an -expression such that it would be a syntax error to actually add the type -arguments explicitly in the source program. This means that every generic -type alias receives actual type arguments at all locations where it is -used. At run time it is also known that the program has no compile-time -errors.* +during compilation. In particular, instantiation to bound has occurred, and +hence some `typeName`s in the source code have been transformed into +parameterized types, even when a type is used as an expression such that it +would be a syntax error to actually add the type arguments explicitly in +the source program. This means that every generic type alias receives +actual type arguments at all locations where it is used. At run time it is +also known that the program has no compile-time errors.* For dynamic type checks, type tests, and expression evaluations, an identifier `F` resolving to a non-generic type alias and a parameterized type `F` where `F` resolves to a generic type alias are treated -identically to the same type checks, type tests, and expression evaluations -performed with the type denoted by that identifier or parameterized type. +identically to the same type checks and type tests performed with the type +denoted by that identifier or parameterized type, and the expression +evaluations work as if we had evaluated a fresh type variable bound to the +denoted type as an expression. + ## Versions From 4db313d666a9407f3d7a86e8a343d8773ec1ae53 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 1 Nov 2018 14:59:53 +0100 Subject: [PATCH 4/7] Clarification --- .../generalized-typedef-2018/feature-specification.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md index 51ffbaa5d3..2fa9974a17 100644 --- a/accepted/future-releases/generalized-typedef-2018/feature-specification.md +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -126,9 +126,9 @@ For dynamic type checks, type tests, and expression evaluations, an identifier `F` resolving to a non-generic type alias and a parameterized type `F` where `F` resolves to a generic type alias are treated identically to the same type checks and type tests performed with the type -denoted by that identifier or parameterized type, and the expression -evaluations work as if we had evaluated a fresh type variable bound to the -denoted type as an expression. +denoted by that identifier or parameterized type, and the evaluation of `F` +respectively `F` as an expression works the same as evaluation of a +fresh type variable bound to the denoted type. ## Versions From aa306a5a247d4e210f871232ae0f5410fcb28a38 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 1 Nov 2018 15:05:07 +0100 Subject: [PATCH 5/7] Added extra requirement: When bounds are satisfied the denoted type must be regular-bounded --- .../generalized-typedef-2018/feature-specification.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md index 2fa9974a17..ec38cc3505 100644 --- a/accepted/future-releases/generalized-typedef-2018/feature-specification.md +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -90,8 +90,9 @@ Let _F_ be a generic type alias of the form that uses `=` with type parameter declarations _X1 extends B1 .. Xk extends Bk_. It is a compile-time error unless satisfaction of the declared bounds -_B1 .. Bk_ implies that all all types that occur on -the right hand side of `=` are well-bounded. +_B1 .. Bk_ implies that the right hand side is +regular-bounded, all all types that occur as subterms of the right hand +side are well-bounded. Let `F` be a parameterized type where `F` denotes a declaration of the form From e293c97c13d993bc0ea2385c05025821792c259e Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 1 Nov 2018 15:07:30 +0100 Subject: [PATCH 6/7] Typo --- .../generalized-typedef-2018/feature-specification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md index ec38cc3505..c880633d4a 100644 --- a/accepted/future-releases/generalized-typedef-2018/feature-specification.md +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -91,7 +91,7 @@ parameter declarations _X1 extends B1 .. Xk extends Bk_. It is a compile-time error unless satisfaction of the declared bounds _B1 .. Bk_ implies that the right hand side is -regular-bounded, all all types that occur as subterms of the right hand +regular-bounded, and all types that occur as subterms of the right hand side are well-bounded. Let `F` be a parameterized type where `F` denotes a declaration of From d8ec461151e44ee7778b114253b2ad7abf823de4 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 6 Nov 2018 11:16:57 +0100 Subject: [PATCH 7/7] Review response --- .../feature-specification.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/accepted/future-releases/generalized-typedef-2018/feature-specification.md b/accepted/future-releases/generalized-typedef-2018/feature-specification.md index c880633d4a..d0b15afe42 100644 --- a/accepted/future-releases/generalized-typedef-2018/feature-specification.md +++ b/accepted/future-releases/generalized-typedef-2018/feature-specification.md @@ -93,6 +93,8 @@ It is a compile-time error unless satisfaction of the declared bounds _B1 .. Bk_ implies that the right hand side is regular-bounded, and all types that occur as subterms of the right hand side are well-bounded. +Any self reference in a type alias, either directly or recursively via another +type alias, is a compile-time error. Let `F` be a parameterized type where `F` denotes a declaration of the form @@ -112,6 +114,16 @@ evaluated as an expression, it is subject to instantiation to bound. *This treatment of generic type aliases is again the same as it was previously, but it involves a larger set of types.* +*Note that type aliases introduce types and not classes. Consequently, a +type alias can **not** be used in a position where a class is expected: in the +`extends`, `with`, `implements`, or `on` clause of a class or mixin +declaration; for a static member access; or in an instance creation +expression (`new F()`, `const F()`). On the other hand, it **can** be +used as a type annotation, as a type argument, as part of a function type +or function signature, as a type literal, in an `on` clause of a `try` +statement, in a type test (`e is F`), and in a type cast (`e as F`).* + + ### Dynamic Semantics *The dynamic semantics relies on elaborations on the program performed @@ -134,4 +146,4 @@ fresh type variable bound to the denoted type. ## Versions -* Nov 1st, 2018, version 0.1: Initial version of this document. +* Nov 6th, 2018, version 0.1: Initial version of this document.