Files
sdk/pkg/kernel/lib/transformations
Johnni Winther f8e7e64fd6 [cfe] Handle constant constructor invocations in Widget factory constructors
The widget transformer would try to pass on the location injected
parameter in the factory constructor when calling constructors of its
own kind in constructor body. For instance

  class Foo extends Widget {
    factory Foo() => new Foo.internal();
    Foo.internal();
  }

would be transformed into

  class Foo extends Widget {
    factory Foo({Location loc}) => new Foo.internal(loc: loc);
    Foo.internal({Location loc}) : super(loc);
  }

This doesn't work if the constructor invocation is constant. For
instance:

  class Foo extends Widget {
    factory Foo() => const Foo.internal();
    const Foo.internal();
  }

which would be transformed into

  class Foo extends Widget {
    factory Foo({Location loc}) => const Foo.internal(loc: loc);
    const Foo.internal({Location loc}) : super(loc);
  }

Here the reading of the injected factory parameter [loc] is not a
valid constant, leading to a compile-time error during constant
evaluation.

To handle this, const constructor invocations within factories do
not pass on the location from the surrounding constructor but
uses their own. For instance:

  class Foo extends Widget {
    factory Foo() => const Foo.internal();
    Foo.internal();
  }

will be transformed into

  class Foo extends Widget {
    factory Foo({Location loc})
      => const Foo.internal(loc: const Location());
    Foo.internal({Location loc}) : super(loc);
  }

This does mean that these constant widgets will all have a
location based on the factory constructor declaration and _not_
one per invocation of the factory constructor.

Related to https://github.com/flutter/flutter/issues/63335

Change-Id: Ie3300d3ba81324d5fbd7fb6ab72b9d83d7afcf22
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158395
Reviewed-by: Jens Johansen <jensj@google.com>
2020-08-14 10:15:12 +00:00
..