Skip to content

Commit 9a59be4

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Store the interface target of a forwarding stub.
This is a temporary measure to allow the analyzer team to make progress until #31519 is fixed. Change-Id: I056505ed0308c5b2ea3e3664a8943549c3c8548c Reviewed-on: https://dart-review.googlesource.com/27460 Reviewed-by: Kevin Millikin <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 7e2645c commit 9a59be4

File tree

2 files changed

+102
-5
lines changed

2 files changed

+102
-5
lines changed

pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart

+33-3
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,15 @@ class ForwardingNode extends Procedure {
425425
typeParameters: typeParameters,
426426
requiredParameterCount: target.function.requiredParameterCount,
427427
returnType: substitution.substituteType(target.function.returnType));
428-
return new Procedure(name, kind, function,
429-
isAbstract: true,
430-
isForwardingStub: true,
428+
Member finalTarget;
429+
if (target is ForwardingStub) {
430+
finalTarget = ForwardingStub.getInterfaceTarget(target);
431+
} else if (target is SyntheticAccessor) {
432+
finalTarget = target._field;
433+
} else {
434+
finalTarget = target;
435+
}
436+
return new ForwardingStub(finalTarget, name, kind, function,
431437
fileUri: enclosingClass.fileUri)
432438
..fileOffset = enclosingClass.fileOffset
433439
..parent = enclosingClass
@@ -597,6 +603,30 @@ class ForwardingNode extends Procedure {
597603
}
598604
}
599605

606+
/// Represents a [Procedure] generated by the front end to serve as a forwarding
607+
/// stub.
608+
///
609+
/// This class exists to work around dartbug.com/31519.
610+
/// TODO(paulberry): remove when dartbug.com/31519 is fixed.
611+
class ForwardingStub extends Procedure {
612+
/// The interface target that this forwarding stub replaces.
613+
final Member _interfaceTarget;
614+
615+
ForwardingStub(this._interfaceTarget, Name name, ProcedureKind kind,
616+
FunctionNode function, {Uri fileUri})
617+
: super(name, kind, function,
618+
isAbstract: true, isForwardingStub: true, fileUri: fileUri);
619+
620+
/// Retrieves the [_interfaceTarget] from a forwarding stub.
621+
///
622+
/// This method exists so that we don't have to expose [_interfaceTarget] as
623+
/// a public getter (which might confuse clients of the front end that aren't
624+
/// expecting it).
625+
static Member getInterfaceTarget(ForwardingStub stub) {
626+
return stub._interfaceTarget;
627+
}
628+
}
629+
600630
/// An [InterfaceResolver] keeps track of the information necessary to resolve
601631
/// method calls, gets, and sets within a chunk of code being compiled, to
602632
/// infer covariance annotations, and to create forwarwding stubs when necessary

pkg/front_end/test/fasta/type_inference/interface_resolver_test.dart

+69-2
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,11 @@ class InterfaceResolverTest {
161161
isAbstract: isAbstract);
162162
}
163163

164-
Field makeField({String name: 'foo', DartType type: const DynamicType()}) {
165-
return new Field(new Name(name), type: type);
164+
Field makeField(
165+
{String name: 'foo',
166+
DartType type: const DynamicType(),
167+
bool isFinal: false}) {
168+
return new Field(new Name(name), type: type, isFinal: isFinal);
166169
}
167170

168171
Procedure makeForwardingStub(Procedure method, bool setter,
@@ -718,6 +721,7 @@ class InterfaceResolverTest {
718721
expect(y.isGenericCovariantImpl, isFalse);
719722
expect(y.isGenericCovariantInterface, isFalse);
720723
expect(y.isCovariant, isTrue);
724+
expect(ForwardingStub.getInterfaceTarget(stub), same(methodA));
721725
expect(getStubTarget(stub), same(methodA));
722726
}
723727

@@ -765,9 +769,68 @@ class InterfaceResolverTest {
765769
expect(y.isGenericCovariantImpl, isTrue);
766770
expect(y.isGenericCovariantInterface, isFalse);
767771
expect(y.isCovariant, isFalse);
772+
expect(ForwardingStub.getInterfaceTarget(stub), same(methodA));
768773
expect(getStubTarget(stub), same(methodA));
769774
}
770775

776+
void test_interfaceTarget_cascaded() {
777+
var methodC = makeEmptyMethod(positionalParameters: [
778+
new VariableDeclaration('x', type: intType),
779+
new VariableDeclaration('y', type: intType)
780+
]);
781+
var c = makeClass(name: 'C', procedures: [methodC]);
782+
var t = new TypeParameter('T', objectType);
783+
var methodI1 = makeEmptyMethod(positionalParameters: [
784+
new VariableDeclaration('x', type: new TypeParameterType(t))
785+
..isGenericCovariantImpl = true,
786+
new VariableDeclaration('y', type: intType)
787+
]);
788+
var i1 = makeClass(name: 'I1', typeParameters: [t], procedures: [methodI1]);
789+
// Let's say D was previously compiled, so it already has a forwarding stub
790+
var methodD = new ForwardingStub(
791+
methodC,
792+
methodC.name,
793+
methodC.kind,
794+
new FunctionNode(null, positionalParameters: [
795+
new VariableDeclaration('x', type: intType),
796+
new VariableDeclaration('y', type: intType)
797+
]));
798+
var d =
799+
makeClass(name: 'D', supertype: c.asThisSupertype, implementedTypes: [
800+
new Supertype(i1, [intType])
801+
], procedures: [
802+
methodD
803+
]);
804+
var u = new TypeParameter('U', objectType);
805+
var methodI2 = makeEmptyMethod(positionalParameters: [
806+
new VariableDeclaration('x', type: intType),
807+
new VariableDeclaration('y', type: new TypeParameterType(u))
808+
..isGenericCovariantImpl = true
809+
]);
810+
var i2 = makeClass(name: 'I2', typeParameters: [u], procedures: [methodI2]);
811+
var e =
812+
makeClass(name: 'E', supertype: d.asThisSupertype, implementedTypes: [
813+
new Supertype(i2, [intType])
814+
]);
815+
var node = getForwardingNode(e, false);
816+
var stub = node.finalize();
817+
expect(ForwardingStub.getInterfaceTarget(stub), same(methodC));
818+
}
819+
820+
void test_interfaceTarget_field() {
821+
var fieldA = makeField(type: numType, isFinal: true);
822+
var fieldB = makeField(type: intType, isFinal: true);
823+
var a = makeClass(name: 'A', fields: [fieldA]);
824+
var b = makeClass(name: 'B', fields: [fieldB]);
825+
var c = makeClass(
826+
name: 'C',
827+
supertype: a.asThisSupertype,
828+
implementedTypes: [b.asThisSupertype]);
829+
var node = getForwardingNode(c, false);
830+
var stub = node.finalize();
831+
expect(ForwardingStub.getInterfaceTarget(stub), same(fieldB));
832+
}
833+
771834
void test_merge_candidates_including_mixin() {
772835
var methodA = makeEmptyMethod();
773836
var methodB = makeEmptyMethod();
@@ -860,6 +923,7 @@ class InterfaceResolverTest {
860923
name: 'C', implementedTypes: [a.asThisSupertype, b.asThisSupertype]);
861924
var node = getForwardingNode(c, false);
862925
var stub = node.finalize();
926+
expect(ForwardingStub.getInterfaceTarget(stub), same(methodB));
863927
expect(getStubTarget(stub), isNull);
864928
expect(stub.function.returnType, intType);
865929
}
@@ -878,6 +942,7 @@ class InterfaceResolverTest {
878942
]);
879943
var node = getForwardingNode(d, true);
880944
var stub = node.finalize();
945+
expect(ForwardingStub.getInterfaceTarget(stub), same(setterB));
881946
expect(getStubTarget(stub), isNull);
882947
expect(stub.function.positionalParameters[0].type, objectType);
883948
}
@@ -910,6 +975,7 @@ class InterfaceResolverTest {
910975
var resolvedMethod = node.finalize();
911976
expect(resolvedMethod, same(methodC));
912977
expect(methodC.function.body, isNotNull);
978+
expect(methodC, isNot(new isInstanceOf<ForwardingStub>()));
913979
expect(getStubTarget(methodC), same(methodA));
914980
}
915981

@@ -938,6 +1004,7 @@ class InterfaceResolverTest {
9381004
]);
9391005
var node = getForwardingNode(d, false);
9401006
var stub = node.finalize();
1007+
expect(ForwardingStub.getInterfaceTarget(stub), same(methodB));
9411008
expect(getStubTarget(stub), isNull);
9421009
expect(stub.function.returnType, intType);
9431010
}

0 commit comments

Comments
 (0)