Fix handling of forwarding semi-stubs in the front end.

See #31649 for more details about forwarding semi-stubs.

Change-Id: I2af7fb0c5de01d7732279a6ca8254985f396683a
Reviewed-on: https://dart-review.googlesource.com/35003
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samir Jindel <sjindel@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry 2018-01-17 17:47:58 +00:00 committed by commit-bot@chromium.org
parent d29f574518
commit 7339e1ffe7
5 changed files with 26 additions and 8 deletions

View file

@ -114,8 +114,17 @@ abstract class KernelFunctionBuilder
}
actualBody = newBody;
if (function != null) {
function.body = newBody;
newBody?.parent = function;
// A forwarding semi-stub is a method that is abstract in the source code,
// but which needs to have a forwarding stub body in order to ensure that
// covariance checks occur. We don't want to replace the forwarding stub
// body with null.
var parent = function.parent;
if (!(newBody == null &&
parent is Procedure &&
parent.isForwardingSemiStub)) {
function.body = newBody;
newBody?.parent = function;
}
}
}

View file

@ -366,11 +366,16 @@ class ForwardingNode extends Procedure {
}
procedure.isAbstract = false;
if (!procedure.isForwardingStub) {
// This procedure exists abstractly in the source code; we need to make it
// concrete and give it a body that is a forwarding stub. This situation
// is called a "forwarding semi-stub".
procedure.isForwardingStub = true;
procedure.isForwardingSemiStub = true;
_interfaceResolver._instrumentation?.record(
procedure.fileUri,
procedure.fileOffset,
'forwardingStub',
new InstrumentationValueLiteral('implementation'));
new InstrumentationValueLiteral('semi-stub'));
}
var positionalArguments = function.positionalParameters
.map<Expression>((parameter) => new VariableGet(parameter))
@ -799,6 +804,7 @@ class InterfaceResolver {
}
if (resolution is Procedure &&
resolution.isForwardingStub &&
!resolution.isForwardingSemiStub &&
identical(resolution.enclosingClass, class_)) {
if (strongMode) class_.addMember(resolution);
_instrumentation?.record(
@ -971,7 +977,9 @@ class InterfaceResolver {
for (var procedure in class_.procedures) {
if (procedure.isStatic) continue;
// Forwarding stubs are annotated separately
if (procedure.isForwardingStub) continue;
if (procedure.isForwardingStub && !procedure.isForwardingSemiStub) {
continue;
}
void recordFormalAnnotations(VariableDeclaration formal) {
recordCovariance(formal.fileOffset, formal.isCovariant,
formal.isGenericCovariantInterface, formal.isGenericCovariantImpl);

View file

@ -14,7 +14,7 @@ abstract class I<T> {
}
class C extends B implements I<num> {
void /*@forwardingStub=implementation*/ f(num /*@covariance=genericImpl*/ x);
void /*@forwardingStub=semi-stub*/ f(num /*@covariance=genericImpl*/ x);
}
main() {}

View file

@ -18,6 +18,7 @@ class C extends self::B implements self::I<core::num> {
default constructor •() → void
: super self::B::•()
;
method f(generic-covariant-impl core::num x) → void;
forwarding-stub forwarding-semi-stub method f(generic-covariant-impl core::num x) → void
return super.{self::B::f}(x);
}
static method main() → dynamic {}

View file

@ -393,9 +393,7 @@ generic_method_types_test/02: RuntimeError, OK # No support for covariant tear-o
generic_methods_bounds_test/01: MissingCompileTimeError
generic_methods_bounds_test/02: MissingRuntimeError
generic_methods_dynamic_test/01: MissingCompileTimeError
generic_methods_dynamic_test/02: MissingRuntimeError
generic_methods_dynamic_test/03: MissingCompileTimeError
generic_methods_dynamic_test/04: MissingRuntimeError
generic_methods_generic_class_tearoff_test: RuntimeError
generic_methods_named_parameters_test: RuntimeError
generic_methods_optional_parameters_test: RuntimeError
@ -1058,6 +1056,8 @@ forwarding_stub_tearoff_test: RuntimeError
function_type_call_getter2_test/none: RuntimeError
function_type_test: RuntimeError
generic_field_mixin6_test/none: RuntimeError
generic_methods_dynamic_test/02: MissingRuntimeError
generic_methods_dynamic_test/04: MissingRuntimeError
implicit_downcast_during_assignment_test: RuntimeError
implicit_downcast_during_combiner_test: RuntimeError
implicit_downcast_during_compound_assignment_test: RuntimeError