@@ -627,6 +627,18 @@ evaluation at compile time _if the underlying compiler supports it_.
627627const 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+
630642Applying ` @konst ` to normal variables and fields simply requests compiler to
631643compute 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 -
855867compiler 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
859879I have intentionally avoided saying that ` @konst ` has to be a language feature
860880and 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
864883For example, a native JIT or DDC (development mode JS compiler) could simply
865884implement ` 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