Before: mixin application classes could not have methods of their
own.
After: type inference will sometimes insert forwarding stubs in mixin
application classes. In the mixin elimination transformation, these
forwarding stubs are replaced with the methods of the mixin class if
they have the same name, but the parameter flags from the forwarding
stub are retained. The other forwarding stubs are left as methods of
the class.
Change-Id: I5ee89d6b1fc83194df82009c2800b54ce856e8c5
Reviewed-on: https://dart-review.googlesource.com/15887
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
This has no effect on the generated kernel output; it just affects tests.
Also fix an incorrect type in field_forwarding_stub_explicit_covariant.dart.
Change-Id: Ic89d59a52648dc37a43cb12c4289611daaf422c6
Reviewed-on: https://dart-review.googlesource.com/15647
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Also add a test to verify that contravariance is properly handled for
method calls using "if-null" syntax (since this is handled by a
slightly different code path in the front end).
Change-Id: I93ee8b38ff39d78e25cac23ff048fcf69f15b5db
Reviewed-on: https://dart-review.googlesource.com/15000
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
The outer loops are now through the arguments of the method to be
fixed, and the inner loops are through the inherited methods. This
allows us to handle the situation where a forwarding stub is needed
because isGenericCovariantInterface changes from true to false, but
the forwarding stub doesn't need to be concrete, since
isGenericCovariantImpl is inherited from the base class. (Previously
that situation didn't work because by the time we processed the
inheritance of isGenericCovariantImpl, we had already created a
concrete forwarding stub).
Additional fixes in this CL (necessary to get tests to pass in
meaningful ways):
- Updated InstrumentationValueForForwardingStub to print covariance
annotations on type parameters.
- Updated _createForwardingStub to copy covariance annotations from
the target procedure to the procedure being created.
- Moved call_through_this.dart from runtime_checks/ to
runtime_checks_new/ because the analyzer implementation doesn't
handle this case correctly.
Change-Id: I984a46826a3a4d8ad1a1ce840269498df049fef0
Reviewed-on: https://dart-review.googlesource.com/13963
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This allows covariance information to propagate properly between
classes and avoids creation of unnecessary forwarding stubs.
Change-Id: Ib55c62adb74d16f94282e752e387634086001946
Reviewed-on: https://dart-review.googlesource.com/12600
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Instead of using enums, we use booleans, and we change the terminology
as follows:
FormalSafety.semiSafe -> isGenericCovariantImpl
InterfaceSafety.semiTyped -> isGenericCovariantInterface
(The enum value FormalSafety.unsafe turned out to be redundant with
isCovariant, so it is no longer needed).
Similarly, the annotations in the front end tests are updated as follows:
@checkFormal=unsafe -> @covariance=explicit
@checkFormal=semiSafe -> @covariance=genericImpl
@checkInterface=semiTyped -> @covariance=genericInterface
Change-Id: Iafc0c5d3fc4e7608a2b8c52d8c29f293d9219995
Reviewed-on: https://dart-review.googlesource.com/5540
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
A few corner cases weren't being handled correctly by the analyzer
code; some other corner cases weren't being handled correctly by the
front end.
Change-Id: I2b7153a411036541f48019757349b197f9b3bba7
Reviewed-on: https://dart-review.googlesource.com/5328
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Rather than track precisely which types can be passed to each method
parameter through all of the interfaces it implements, and mark them
as semiSafe when they don't match the declared parameter type, it is
simpler to simply make semiSafe an "inherited" version of semiTyped.
The simpler analysis is slightly conservative--it will unnecessarily
mark parameters as semiSafe in a few circumstances, but those
circumstances seem like they will be rare enough that they don't
justify doing extra work.
This allows us to get rid of the extra field additionalIncomingTypes
(which we would otherwise have had to store in the kernel
representation).
In the process, reworked the logic for deciding whether to mark a
parameter as semiSafe or semiTyped so that it uses a type visitor
rather than by substituting and then doing a subtype check; this
should be significantly faster.
Note that in order for semiSafe to be "inherited" in all the right
circumstances, we need to mark it on abstract methods as well as
concrete ones; this is a departure from analyzer behavior, so I've
added a hack to front_end_runtime_check_test to ensure that it
generates the expected annotations.
Change-Id: I53d3718d8fb1979ac8551fe02734ddaf3d6708b8
Reviewed-on: https://dart-review.googlesource.com/5044
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This CL extends the computation of unsafe/semiSafe/safe and
semiTyped/typed annotations so that they apply to type parameters of
generic methods as well as ordinary method parameters (previously they
only applied to method parameters).
Change-Id: I5302e1bfe404df5c73656069557b80ca6787b2b4
Reviewed-on: https://dart-review.googlesource.com/4900
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
The old technique had the right effect in a few simple corner cases,
but wasn't correct on theoretical grounds. The new technique is to
keep track, for every method parameter in every interface, the set of
types which might be passed to that method parameter through base
classes, and then compare those types to the declared method parameter
types.
So for instance, in the code:
class A<T> {
foo(List<T> argument) {}
}
class B extends A<num> {
foo(List<num> argument) {}
}
The set of types that might be passed to B.foo's argument is all
subtypes of List<Object> (since a caller might be invoking foo through
the interface A<Object>). Since List<Object> is not a subtype of
List<num>, B needs a runtime check.
Change-Id: Iae819e9f8c97ec1cf910fbfacf9bc635fccd9706
Reviewed-on: https://dart-review.googlesource.com/4610
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
It turns out that it is easier to calculate whether or not checks are
needed at the site of the declaration of the interface target, not at
the call site. Accordingly, it makes sense to put the annotations on
the interface target declarations as well. This lets us get rid of a
clumsy annotation format that referred to arguments by number, in
favor of simply annotating the formal parameters themselves.
R=scheglov@google.com
Review-Url: https://codereview.chromium.org/3010613003 .
We haven't quite figured out how we want to store the need for these
type checks in the kernel representation, and I'm hoping that my
coding work can help inform that decision. So for the moment the
annotation is simply stored in the front_end wrapper
(KernelVariableDeclaration). This is enough to get simple tests to
pass.
R=ahe@google.com
Review-Url: https://codereview.chromium.org/3000353002 .
The tests in this CL illustrate the major use cases where runtime
checks are required. They are not exhaustive. In a later CL I will
copy over some of analyzer's internal unit tests, which are much more
thorough.
So far these tests only pass when tested via analyzer, since analyzer
currently is the only platform that does the necessary analysis to
figure out which checks are needed. In follow up CLs I will begin
introducing code into front_end to determine which checks are needed,
and to record this information in the kernel representation.
R=danrubel@google.com, sigmund@google.com
Review-Url: https://codereview.chromium.org/3002893002 .