Skip to content

Commit 43f4ec2

Browse files
committed
Tweak wording a bit
1 parent 72d111b commit 43f4ec2

1 file changed

Lines changed: 108 additions & 9 deletions

File tree

  • working/4271 - static enough metaprogramming

working/4271 - static enough metaprogramming/proposal.md

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,18 @@ evaluation at compile time _if the underlying compiler supports it_.
627627
const konst = pragma('konst');
628628
```
629629

630+
> [!NOTE]
631+
>
632+
> The actual name `konst` is a subject to discussion and change. It can be
633+
> `comptime`, `constexpr` or anything else. Concrete name is irrelevant and
634+
> choosing a different name does not change the core of this proposal.
635+
>
636+
> I have chosen metadata instead of introducing a new keyword for pragmatic
637+
> reasons - it does not require syntax changes.
638+
>
639+
> It is important to understand that concrete syntax is secondary, the
640+
> capability is more important.
641+
630642
Applying `@konst` to normal variables and fields simply requests compiler to
631643
compute their value at compile time:
632644

@@ -854,12 +866,19 @@ Note that all methods are annotated with `@konst` so if compiler supports
854866
`@konst` these must be invoked on constant objects and will be folded away -
855867
compiler does not need to store any information itself.
856868

869+
> [!NOTE]
870+
>
871+
> `dart:mirrors` allows developer to ignore privacy, enumerate and access
872+
> private fields and methods. However Dart VM does mark `dart:*` classes
873+
> as non-reflectable. Similar approach should be probably taken with compile
874+
> time reflection: `FieldInfo.getFrom` should ignore privacy unless target
875+
> is marked as non-reflectable.
876+
857877
### It's a spectrum of choice
858878

859879
I have intentionally avoided saying that `@konst` has to be a language feature
860880
and that any Dart implementation needs to support compile time constant
861-
evaluation of `@konst`. I think we should consider doing this as a toolchain
862-
feature, similar to how `platform-const` is implemented.
881+
evaluation of `@konst`. I think we should implement this as a toolchain feature, similar to how `platform-const` is implemented.
863882

864883
For example, a native JIT or DDC (development mode JS compiler) could simply
865884
implement `TypeInfo` on top of runtime reflection. This way developer can debug
@@ -876,14 +895,94 @@ operations.
876895
> runtime performance. This reduces the size of deployed applications but
877896
> decreases peak performance.
878897
879-
In this model, developer _might_ encounter compile time errors when building
880-
release application which they did not observe while developing - as development
881-
and deployment toolchains implement different semantics.
898+
There are multiple reasons for going this route. First of all, I believe that
899+
this allows to considerably simplify the design and implementation of this
900+
feature. But there is another reason for this: _you can't actually perform
901+
compile time evaluation without knowing compile time environment_. Consider for
902+
example the following code:
903+
904+
```dart
905+
void foo(@konst String id) {
906+
if (id.length != 10) {
907+
throw 'Incorect value for $id';
908+
}
909+
910+
// Do various things with id.
911+
}
912+
913+
void bar() {
914+
foo(const String.fromEnvironment('some.define'));
915+
}
916+
```
917+
918+
Dart Analyzer can't really say what happens here because it does not know
919+
a specific value of `id` - the value is only known when compiling. The example
920+
can be made even more complicated by adding dependency on various platform
921+
specific defines (e.g. to distinguish between target platforms and specialize
922+
for them).
882923

883-
I think that's an acceptable price to pay for the convenience&power of this
884-
feature. We can later choose to implement additional checks in development
885-
toolchains or analyzer to minimize amount of errors which are only surfaced by
886-
release builds. But I don't see this as a requirement for shipping this feature.
924+
Fundamentally this means that _compiling_ an application can reveal compile
925+
time error which are not revealed by running Dart analyzer on the same code.
926+
Furthermore compiling for different platforms can reveal different errors.
927+
928+
The fact that these errors surface in compile time is an intrinsic property
929+
of this proposal - and is a direct consequence of its powerful ability to
930+
specialize code based on the compile time computation. It can't be fully
931+
avoided for the reasons which are explained above - though we could eventually
932+
_choose_ to implement subset of this proposal in analyzer as well and surface
933+
some of the errors earlier. However I currently don't see direct analyzer
934+
support as a necessary requirement to shipping this feature.
935+
936+
> [!NOTE]
937+
>
938+
> If we decide that `@konst` is a no-op in debug (development) mode and
939+
> `@konst` reflection falls back to actual reflection then it is reasonable
940+
> to expect that developer could still opt-in into full `@konst` evaluation
941+
> for debug (development) mode. This is important to enable testing this code
942+
> without forcing developers to build their code in release mode.
943+
944+
> [!NOTE]
945+
>
946+
> Some of our tools (most notably analyzer and DDC) are capable of
947+
> analyzing/compiling libraries only given the _outlines_ of their dependencies.
948+
> This was one of the showstoppers for enhanced constant proposal, which did not
949+
> introduce a syntactic marker to delineate code potentially needed for
950+
> `const`-evaluation from the rest of the program, which would mean that
951+
> outlines had to contain bodies for most methods - making them impractically
952+
> large and erasing their benefits.
953+
>
954+
> This proposal does not suffer the same issue, even if we decide to support
955+
> `@konst` evaluation in these tools: as `@konst` actually provides a syntactic
956+
> marker which partitions the program. Only bodies of methods with `@konst`
957+
> parameters need to be included into the outline.
958+
959+
### Non-Goals
960+
961+
This proposal does _not_ intend to cover all cases which are supportable via
962+
Dart source code generation or which are supported by macro systems in other
963+
programming languages. For example the following capabilities are out of scope:
964+
965+
- injecting new declarations into the program;
966+
- changing or expanding Dart syntax.
967+
968+
This means that certain things are not possible with this proposal which are
969+
possible with code generation. Most notably it is not possible to declare
970+
fields, methods or parameters. This means for example that it is impossible
971+
to use `@konst` to inject a `copyWith` method based on the list of fields.
972+
973+
> [!NOTE]
974+
>
975+
> It is however possible to define method like this:
976+
>
977+
> ```dart
978+
> // Universal function to apply updates specified by the record.
979+
> T copyWith<@konst T, @konst R extends Record>(T obj, R updates) {
980+
> // ...
981+
> }
982+
> ```
983+
>
984+
> Though usability of this method will be questionable as there will be good
985+
> autocomplete available for `updates` parameter.
887986
888987
### Prototype implementation
889988

0 commit comments

Comments
 (0)