[cfe] Handle simple use of extension instance members

Change-Id: Ic1a949c0dca9327763e01458211e477de13c222f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/114504
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Johnni Winther
2019-08-28 22:16:21 +00:00
committed by commit-bot@chromium.org
parent e9fdeb2db8
commit a147d4e8d2
32 changed files with 1224 additions and 129 deletions
@@ -4,12 +4,6 @@
library fasta.procedure_builder;
// Note: we're deliberately using AsyncMarker and ProcedureKind from kernel
// outside the kernel-specific builders. This is simpler than creating
// additional enums.
import 'package:kernel/ast.dart'
show AsyncMarker, ProcedureKind, VariableDeclaration;
import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
import 'package:kernel/type_algebra.dart';
@@ -30,6 +24,7 @@ import 'package:kernel/ast.dart'
show
Arguments,
AsyncMarker,
Block,
Class,
Constructor,
ConstructorInvocation,
@@ -45,6 +40,7 @@ import 'package:kernel/ast.dart'
Procedure,
ProcedureKind,
RedirectingInitializer,
ReturnStatement,
Statement,
StaticInvocation,
StringLiteral,
@@ -53,6 +49,7 @@ import 'package:kernel/ast.dart'
TypeParameter,
TypeParameterType,
VariableDeclaration,
VariableGet,
setParents;
import '../../scanner/token.dart' show Token;
@@ -235,7 +232,7 @@ abstract class FunctionBuilder extends MemberBuilder {
FunctionNode function;
Statement actualBody;
Statement _body;
FunctionBuilder get actualOrigin;
@@ -247,7 +244,7 @@ abstract class FunctionBuilder extends MemberBuilder {
// newBody.fileOffset, fileUri);
// }
// }
actualBody = newBody;
_body = newBody;
if (function != null) {
// 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
@@ -264,18 +261,18 @@ abstract class FunctionBuilder extends MemberBuilder {
}
void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
if (actualBody != null) {
unexpected("null", "${actualBody.runtimeType}", charOffset, fileUri);
if (_body != null) {
unexpected("null", "${_body.runtimeType}", charOffset, fileUri);
}
actualBody = new RedirectingFactoryBody(target, typeArguments);
function.body = actualBody;
actualBody?.parent = function;
_body = new RedirectingFactoryBody(target, typeArguments);
function.body = _body;
_body?.parent = function;
if (isPatch) {
actualOrigin.setRedirectingFactoryBody(target, typeArguments);
}
}
Statement get body => actualBody ??= new EmptyStatement();
Statement get body => _body ??= new EmptyStatement();
bool get isNative => nativeMethodName != null;
@@ -506,10 +503,63 @@ class ProcedureBuilder extends FunctionBuilder {
AsyncMarker get asyncModifier => actualAsyncModifier;
Statement get body {
if (actualBody == null && !isAbstract && !isExternal) {
actualBody = new EmptyStatement();
if (_body == null && !isAbstract && !isExternal) {
_body = new EmptyStatement();
}
return actualBody;
return _body;
}
/// If this is an extension instance setter, wrap the setter body to return
/// the rhs value from the method.
///
/// That is, this setter
///
/// extension E on A {
/// void set property(B value) {
/// value++;
/// }
/// }
///
/// is converted into this top level method
///
/// B E|property(A #this, B value) {
/// final #t1 = value;
/// value++;
/// return #t1;
/// }
///
void _updateExtensionSetterBody() {
if (isExtensionInstanceMember && isSetter) {
// TODO(johnniwinther): Avoid the synthetic variable if the parameter is
// never modified.
VariableDeclaration value = procedure.function.positionalParameters[1];
procedure.function.returnType = value.type;
Statement body = procedure.function.body;
List<Statement> statements = [];
Block block = new Block(statements);
VariableDeclaration variableDeclaration =
new VariableDeclarationJudgment.forValue(
new VariableGet(value)..fileOffset = procedure.fileOffset)
..type = value.type;
statements.add(variableDeclaration);
if (body is Block) {
statements.addAll(body.statements);
} else {
statements.add(body);
}
ReturnStatement returnStatement = new ReturnStatement(
new VariableGet(variableDeclaration)
..fileOffset = procedure.fileEndOffset);
statements.add(returnStatement);
setParents(block.statements, block);
procedure.function.body = block;
block.parent = procedure.function;
}
}
void set body(Statement newBody) {
super.body = newBody;
_updateExtensionSetterBody();
}
void set asyncModifier(AsyncMarker newModifier) {
@@ -896,12 +946,12 @@ class RedirectingFactoryBuilder extends ProcedureBuilder {
nativeMethodName);
@override
Statement get body => actualBody;
Statement get body => _body;
@override
void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
if (actualBody != null) {
unexpected("null", "${actualBody.runtimeType}", charOffset, fileUri);
if (_body != null) {
unexpected("null", "${_body.runtimeType}", charOffset, fileUri);
}
// Ensure that constant factories only have constant targets/bodies.
@@ -910,9 +960,9 @@ class RedirectingFactoryBuilder extends ProcedureBuilder {
noLength, fileUri);
}
actualBody = new RedirectingFactoryBody(target, typeArguments);
function.body = actualBody;
actualBody?.parent = function;
_body = new RedirectingFactoryBody(target, typeArguments);
function.body = _body;
_body?.parent = function;
if (isPatch) {
if (function.typeParameters != null) {
Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
@@ -577,8 +577,8 @@ class InferenceVisitor
// To replicate analyzer behavior, we base type inference on the write
// member. TODO(paulberry): would it be better to use the read member
// when doing compound assignment?
FunctionType calleeType = inferrer.getCalleeFunctionType(
inferrer.getCalleeType(writeTarget, receiverType), false);
FunctionType calleeType =
inferrer.getFunctionType(writeTarget, receiverType, false);
DartType expectedIndexTypeForWrite;
DartType indexContext = const UnknownType();
DartType writeContext = const UnknownType();
@@ -604,8 +604,8 @@ class InferenceVisitor
if (read != null) {
ObjectAccessTarget readMember = inferrer
.findMethodInvocationMember(receiverType, read, instrumented: false);
FunctionType calleeFunctionType = inferrer.getCalleeFunctionType(
inferrer.getCalleeType(readMember, receiverType), false);
FunctionType calleeFunctionType =
inferrer.getFunctionType(readMember, receiverType, false);
inferrer.ensureAssignable(
getPositionalParameterType(calleeFunctionType, 0),
indexType,
@@ -1681,7 +1681,7 @@ class InferenceVisitor
if (node.read != null) {
ObjectAccessTarget readTarget = inferrer
.findPropertyGetMember(receiverType, node.read, instrumented: false);
readType = inferrer.getCalleeType(readTarget, receiverType);
readType = inferrer.getGetterType(readTarget, receiverType);
inferrer.handlePropertyGetContravariance(
node.receiver,
readTarget,
@@ -1702,8 +1702,21 @@ class InferenceVisitor
DartType inferredType =
node._inferRhs(inferrer, readType, writeContext).inferredType;
node.nullAwareGuard?.staticType = node.inferredType;
node._replaceWithDesugared();
return new ExpressionInferenceResult(inferredType);
Expression replacement;
if (writeTarget.isExtensionMember) {
node.parent.replaceChild(
node,
replacement = inferrer.helper.forest.createStaticInvocation(
node.fileOffset,
writeTarget.member,
inferrer.helper.forest.createArguments(
node.fileOffset, [node.receiver, node.rhs])));
inferrer.storeInferredType(replacement, inferredType);
} else {
node._replaceWithDesugared();
}
return new ExpressionInferenceResult(inferredType, replacement);
}
@override
@@ -1711,7 +1724,7 @@ class InferenceVisitor
PropertyGet node, DartType typeContext) {
return inferrer.inferPropertyGet(
node, node.receiver, node.fileOffset, typeContext,
desugaredGet: node);
desugaredGet: node, allowExtensionMethods: true);
}
void visitRedirectingInitializerJudgment(
@@ -293,7 +293,7 @@ abstract class ComplexAssignmentJudgment extends SyntheticExpressionJudgment {
Expression read;
/// The expression appearing on the RHS of the assignment.
final Expression rhs;
Expression rhs;
/// The expression that performs the write (e.g. `a.[]=(b, a.[](b) + 1)` in
/// `++a[b]`).
@@ -367,8 +367,8 @@ abstract class ComplexAssignmentJudgment extends SyntheticExpressionJudgment {
combinerTarget.member, readType);
}
DartType rhsType;
FunctionType combinerType = inferrer.getCalleeFunctionType(
inferrer.getCalleeType(combinerTarget, readType), false);
FunctionType combinerType =
inferrer.getFunctionType(combinerTarget, readType, false);
if (isPreIncDec || isPostIncDec) {
rhsType = inferrer.coreTypes.intClass.rawType;
} else {
@@ -378,8 +378,12 @@ abstract class ComplexAssignmentJudgment extends SyntheticExpressionJudgment {
assert(identical(combiner.arguments.positional.first, rhs));
// Analyzer uses a null context for the RHS here.
// TODO(paulberry): improve on this.
inferrer.inferExpression(rhs, const UnknownType(), true);
rhsType = getInferredType(rhs, inferrer);
ExpressionInferenceResult rhsResult =
inferrer.inferExpression(rhs, const UnknownType(), true);
if (rhsResult.replacement != null) {
rhs = rhsResult.replacement;
}
rhsType = rhsResult.inferredType;
// Do not use rhs after this point because it may be a Shadow node
// that has been replaced in the tree with its desugaring.
DartType expectedType = getPositionalParameterType(combinerType, 0);
@@ -413,6 +417,9 @@ abstract class ComplexAssignmentJudgment extends SyntheticExpressionJudgment {
ExpressionInferenceResult rhsResult = inferrer.inferExpression(
rhs, writeContext ?? const UnknownType(), true,
isVoidAllowed: true);
if (rhsResult.replacement != null) {
rhs = rhsResult.replacement;
}
DartType rhsType = rhsResult.inferredType;
Expression replacedRhs = inferrer.ensureAssignable(
writeContext, rhsType, rhs, writeOffset,
@@ -8,11 +8,15 @@ import 'package:kernel/core_types.dart' show CoreTypes;
import '../fasta_codes.dart' show LocatedMessage, Message;
import '../kernel/forest.dart';
abstract class InferenceHelper {
CoreTypes get coreTypes;
Uri get uri;
Forest get forest;
set transformSetLiterals(bool value);
Expression buildProblem(Message message, int charOffset, int length,
@@ -67,6 +67,10 @@ import '../../base/instrumentation.dart'
InstrumentationValueForType,
InstrumentationValueForTypeArgs;
import '../builder/extension_builder.dart';
import '../builder/member_builder.dart';
import '../builder/procedure_builder.dart';
import '../fasta_codes.dart'
show
LocatedMessage,
@@ -649,7 +653,7 @@ abstract class TypeInferrerImpl extends TypeInferrer {
PropertyGet tearOff =
new PropertyGet(new VariableGet(t), callName, callMember)
..fileOffset = fileOffset;
actualType = getCalleeTypeForMemberTarget(callMember, actualType);
actualType = getGetterTypeForMemberTarget(callMember, actualType);
ConditionalExpression conditional = new ConditionalExpression(
nullCheck,
new NullLiteral()..fileOffset = fileOffset,
@@ -743,7 +747,8 @@ abstract class TypeInferrerImpl extends TypeInferrer {
Expression expression,
Expression receiver,
bool setter: false,
bool instrumented: true}) {
bool instrumented: true,
bool includeExtensionMethods: false}) {
assert(receiverType != null && isKnown(receiverType));
receiverType = resolveTypeParameter(receiverType);
@@ -757,15 +762,39 @@ abstract class TypeInferrerImpl extends TypeInferrer {
: coreTypes.objectClass;
Member interfaceMember =
_getInterfaceMember(classNode, name, setter, fileOffset);
ObjectAccessTarget target = interfaceMember != null
? new ObjectAccessTarget.interfaceMember(interfaceMember)
: const ObjectAccessTarget.unresolved();
if (instrumented &&
receiverType != const DynamicType() &&
interfaceMember != null) {
target.isInstanceMember) {
instrumentation?.record(uri, fileOffset, 'target',
new InstrumentationValueForMember(interfaceMember));
new InstrumentationValueForMember(target.member));
}
if (target.isUnresolved && includeExtensionMethods) {
// TODO(johnniwinther): Find the most specific method.
library.scope.forEachExtension((ExtensionBuilder extensionBuilder) {
MemberBuilder memberBuilder =
extensionBuilder.lookupLocalMember(name.name, setter: setter);
if (memberBuilder != null && !memberBuilder.isStatic) {
ProcedureBuilder procedureBuilder = memberBuilder;
if (procedureBuilder != null) {
DartType onType = extensionBuilder.extension.onType;
// TODO(johnniwinther): Handle generic extensions.
if (typeSchemaEnvironment.isSubtypeOf(receiverType, onType)) {
target = new ObjectAccessTarget.extensionMember(
procedureBuilder.target,
procedureBuilder.kind,
extensionBuilder.typeParameters?.length ?? 0);
}
}
}
});
}
if (!isTopLevel &&
interfaceMember == null &&
target.isUnresolved &&
receiverType is! DynamicType &&
receiverType is! InvalidType &&
!(receiverType == coreTypes.functionClass.rawType &&
@@ -783,9 +812,7 @@ abstract class TypeInferrerImpl extends TypeInferrer {
fileOffset,
length)));
}
return interfaceMember != null
? new ObjectAccessTarget.interfaceMember(interfaceMember)
: const ObjectAccessTarget.unresolved();
return target;
}
/// Finds a member of [receiverType] called [name] and records it in
@@ -801,7 +828,8 @@ abstract class TypeInferrerImpl extends TypeInferrer {
errorTemplate: templateUndefinedMethod,
expression: methodInvocation,
receiver: methodInvocation.receiver,
instrumented: instrumented);
instrumented: instrumented,
includeExtensionMethods: true);
if (interfaceTarget.isInstanceMember) {
Member interfaceMember = interfaceTarget.member;
if (receiverType == const DynamicType() &&
@@ -893,7 +921,8 @@ abstract class TypeInferrerImpl extends TypeInferrer {
expression: propertySet,
receiver: propertySet.receiver,
setter: true,
instrumented: instrumented);
instrumented: instrumented,
includeExtensionMethods: true);
if (writeTarget.isInstanceMember) {
if (instrumented &&
instrumentation != null &&
@@ -919,53 +948,72 @@ abstract class TypeInferrerImpl extends TypeInferrer {
}
}
FunctionType getCalleeFunctionType(DartType calleeType, bool followCall) {
if (calleeType is FunctionType) {
return calleeType;
} else if (followCall && calleeType is InterfaceType) {
Member member =
_getInterfaceMember(calleeType.classNode, callName, false, -1);
DartType callType = getCalleeTypeForMemberTarget(member, calleeType);
if (callType is FunctionType) {
return callType;
}
}
return unknownFunction;
}
DartType getCalleeType(ObjectAccessTarget target, DartType receiverType) {
/// Returns the type of [target] when accessed as a getter on [receiverType].
///
/// For instance
///
/// class Class<T> {
/// T method() {}
/// T getter => null;
/// }
///
/// Class<int> c = ...
/// c.method; // The getter type is `int Function()`.
/// c.getter; // The getter type is `int`.
///
DartType getGetterType(ObjectAccessTarget target, DartType receiverType) {
switch (target.kind) {
case ObjectAccessTargetKind.callFunction:
return receiverType;
case ObjectAccessTargetKind.unresolved:
return const DynamicType();
case ObjectAccessTargetKind.instanceMember:
return getCalleeTypeForMemberTarget(target.member, receiverType);
default:
throw unhandled(
target.runtimeType.toString(), 'getCalleeType', null, null);
return getGetterTypeForMemberTarget(target.member, receiverType);
case ObjectAccessTargetKind.extensionMember:
switch (target.extensionMethodKind) {
case ProcedureKind.Method:
FunctionType functionType = target.member.function.functionType;
// TODO(johnniwinther): Handle tear off of generic extensions.
return new FunctionType(
functionType.positionalParameters.skip(1).toList(),
functionType.returnType,
namedParameters: functionType.namedParameters,
typeParameters: functionType.typeParameters
.skip(target.extensionTypeParameterCount)
.toList(),
requiredParameterCount:
functionType.requiredParameterCount - 1);
case ProcedureKind.Getter:
return target.member.function.returnType;
case ProcedureKind.Setter:
case ProcedureKind.Factory:
case ProcedureKind.Operator:
break;
}
}
throw unhandled('$target', 'getGetterType', null, null);
}
DartType getCalleeTypeForMemberTarget(
/// Returns the getter type of [member] on a receiver of type [receiverType].
///
/// For instance
///
/// class Class<T> {
/// T method() {}
/// T getter => null;
/// }
///
/// Class<int> c = ...
/// c.method; // The getter type is `int Function()`.
/// c.getter; // The getter type is `int`.
///
DartType getGetterTypeForMemberTarget(
Member interfaceMember, DartType receiverType) {
if (interfaceMember == null) {
return const DynamicType();
}
Class memberClass = interfaceMember.enclosingClass;
DartType calleeType;
if (interfaceMember is Procedure) {
if (interfaceMember.kind == ProcedureKind.Getter) {
calleeType = interfaceMember.function.returnType;
} else {
calleeType = interfaceMember.function.functionType;
}
} else if (interfaceMember is Field) {
calleeType = interfaceMember.type;
} else {
throw unhandled(
interfaceMember.runtimeType.toString(), 'getCalleeType', null, null);
}
assert(
interfaceMember is kernel.Field || interfaceMember is kernel.Procedure,
"Unexpected interface member $interfaceMember.");
DartType calleeType = interfaceMember.getterType;
if (memberClass.typeParameters.isNotEmpty) {
receiverType = resolveTypeParameter(receiverType);
if (receiverType is InterfaceType) {
@@ -978,6 +1026,67 @@ abstract class TypeInferrerImpl extends TypeInferrer {
return calleeType;
}
/// Returns the type of [target] when accessed as an invocation on
/// [receiverType].
///
/// If the target is known not to be invokable [unknownFunction] is returned.
///
/// For instance
///
/// class Class<T> {
/// T method() {}
/// T Function() getter1 => null;
/// T getter2 => null;
/// }
///
/// Class<int> c = ...
/// c.method; // The getter type is `int Function()`.
/// c.getter1; // The getter type is `int Function()`.
/// c.getter2; // The getter type is [unknownFunction].
///
FunctionType getFunctionType(
ObjectAccessTarget target, DartType receiverType, bool followCall) {
switch (target.kind) {
case ObjectAccessTargetKind.callFunction:
return _getFunctionType(receiverType, followCall);
case ObjectAccessTargetKind.unresolved:
return unknownFunction;
case ObjectAccessTargetKind.instanceMember:
return _getFunctionType(
getGetterTypeForMemberTarget(target.member, receiverType),
followCall);
case ObjectAccessTargetKind.extensionMember:
switch (target.extensionMethodKind) {
case ProcedureKind.Method:
return target.member.function.functionType;
case ProcedureKind.Getter:
// TODO(johnniwinther): Handle implicit .call on extension getter.
return _getFunctionType(target.member.function.returnType, false);
case ProcedureKind.Setter:
case ProcedureKind.Factory:
case ProcedureKind.Operator:
break;
}
}
throw unhandled('$target', 'getFunctionType', null, null);
}
FunctionType _getFunctionType(DartType calleeType, bool followCall) {
if (calleeType is FunctionType) {
return calleeType;
} else if (followCall && calleeType is InterfaceType) {
Member member =
_getInterfaceMember(calleeType.classNode, callName, false, -1);
if (member != null) {
DartType callType = getGetterTypeForMemberTarget(member, calleeType);
if (callType is FunctionType) {
return callType;
}
}
}
return unknownFunction;
}
DartType getDerivedTypeArgumentOf(DartType type, Class class_) {
if (type is InterfaceType) {
InterfaceType typeAsInstanceOfClass =
@@ -1033,11 +1142,22 @@ abstract class TypeInferrerImpl extends TypeInferrer {
}
}
return setterType;
case ObjectAccessTargetKind.extensionMember:
switch (target.extensionMethodKind) {
case ProcedureKind.Setter:
// TODO(johnniwinther): Is this valid if the method is generic?
return target.member.function.positionalParameters[1].type;
case ProcedureKind.Method:
case ProcedureKind.Getter:
case ProcedureKind.Factory:
case ProcedureKind.Operator:
break;
}
// TODO(johnniwinther): Compute the right setter type.
return const DynamicType();
case ObjectAccessTargetKind.callFunction:
default:
throw unhandled(
target.runtimeType.toString(), 'getSetterType', null, null);
}
throw unhandled(target.runtimeType.toString(), 'getSetterType', null, null);
}
DartType getTypeArgumentOf(DartType type, Class class_) {
@@ -1580,9 +1700,9 @@ abstract class TypeInferrerImpl extends TypeInferrer {
target.member is Procedure &&
typeSchemaEnvironment.isOverloadedArithmeticOperatorAndType(
target.member, receiverType);
DartType calleeType = getCalleeType(target, receiverType);
DartType calleeType = getGetterType(target, receiverType);
FunctionType functionType =
getCalleeFunctionType(calleeType, !isImplicitCall);
getFunctionType(target, receiverType, !isImplicitCall);
if (!target.isUnresolved &&
calleeType is! DynamicType &&
@@ -1601,6 +1721,18 @@ abstract class TypeInferrerImpl extends TypeInferrer {
desugaredInvocation,
arguments,
expression);
Expression replacement;
if (target.isExtensionMember) {
expression.parent.replaceChild(
expression,
replacement = helper.forest.createStaticInvocation(
expression.fileOffset,
target.member,
arguments = helper.forest.createArguments(
arguments.fileOffset, [receiver, ...arguments.positional],
named: arguments.named,
types: getExplicitTypeArguments(arguments))));
}
DartType inferredType = inferInvocation(typeContext, fileOffset,
functionType, functionType.returnType, arguments,
isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
@@ -1659,7 +1791,7 @@ abstract class TypeInferrerImpl extends TypeInferrer {
inferred: getExplicitTypeArguments(arguments) == null);
}
return new ExpressionInferenceResult(inferredType);
return new ExpressionInferenceResult(inferredType, replacement);
}
@override
@@ -1682,7 +1814,8 @@ abstract class TypeInferrerImpl extends TypeInferrer {
{VariableDeclaration receiverVariable,
PropertyGet desugaredGet,
ObjectAccessTarget readTarget,
Name propertyName}) {
Name propertyName,
bool allowExtensionMethods: false}) {
// First infer the receiver so we can look up the getter that was invoked.
DartType receiverType;
if (receiver == null) {
@@ -1698,7 +1831,8 @@ abstract class TypeInferrerImpl extends TypeInferrer {
readTarget = findInterfaceMember(receiverType, propertyName, fileOffset,
errorTemplate: templateUndefinedGetter,
expression: expression,
receiver: receiver);
receiver: receiver,
includeExtensionMethods: allowExtensionMethods);
if (readTarget.isInstanceMember) {
if (instrumentation != null && receiverType == const DynamicType()) {
instrumentation.record(uri, desugaredGet.fileOffset, 'target',
@@ -1707,18 +1841,38 @@ abstract class TypeInferrerImpl extends TypeInferrer {
desugaredGet.interfaceTarget = readTarget.member;
}
}
DartType inferredType = getCalleeType(readTarget, receiverType);
DartType inferredType = getGetterType(readTarget, receiverType);
Expression replacedExpression = handlePropertyGetContravariance(receiver,
readTarget, desugaredGet, expression, inferredType, fileOffset);
Expression replacement;
if (readTarget.isInstanceMember) {
Member member = readTarget.member;
if (member is Procedure && member.kind == ProcedureKind.Method) {
inferredType =
instantiateTearOff(inferredType, typeContext, replacedExpression);
}
} else if (readTarget.isExtensionMember) {
switch (readTarget.extensionMethodKind) {
case kernel.ProcedureKind.Getter:
expression.parent.replaceChild(
expression,
replacement = expression = helper.forest.createStaticInvocation(
expression.fileOffset,
readTarget.member,
helper.forest
.createArguments(expression.fileOffset, [receiver])));
break;
case kernel.ProcedureKind.Method:
// TODO(johnniwinther): Handle extension method tearoff.
case kernel.ProcedureKind.Setter:
case kernel.ProcedureKind.Factory:
case kernel.ProcedureKind.Operator:
unhandled('$readTarget', "inferPropertyGet", fileOffset, uri);
break;
}
}
storeInferredType(expression, inferredType);
return new ExpressionInferenceResult(inferredType);
return new ExpressionInferenceResult(inferredType, replacement);
}
/// Modifies a type as appropriate when inferring a closure return type.
@@ -1800,7 +1954,7 @@ abstract class TypeInferrerImpl extends TypeInferrer {
if (interfaceMember is Field ||
interfaceMember is Procedure &&
interfaceMember.kind == ProcedureKind.Getter) {
DartType getType = getCalleeType(target, receiverType);
DartType getType = getGetterType(target, receiverType);
if (getType is DynamicType) {
return MethodContravarianceCheckKind.none;
}
@@ -2121,6 +2275,7 @@ enum ObjectAccessTargetKind {
instanceMember,
callFunction,
unresolved,
extensionMember,
}
/// Result for performing an access on an object, like `o.foo`, `o.foo()` and
@@ -2138,6 +2293,11 @@ class ObjectAccessTarget {
ObjectAccessTargetKind.instanceMember, member);
}
/// Creates an access to the extension [member].
factory ObjectAccessTarget.extensionMember(
Member member, ProcedureKind kind, int typeParameters) =
ExtensionAccessTarget;
/// Creates an access to a 'call' method on a function, i.e. a function
/// invocation.
const ObjectAccessTarget.callFunction()
@@ -2153,11 +2313,42 @@ class ObjectAccessTarget {
/// Returns `true` if this is an access to an instance member.
bool get isInstanceMember => kind == ObjectAccessTargetKind.instanceMember;
/// Returns `true` if this is an access to an extension member.
bool get isExtensionMember => kind == ObjectAccessTargetKind.extensionMember;
/// Returns `true` if this is an access to the 'call' method on a function.
bool get isCallFunction => kind == ObjectAccessTargetKind.callFunction;
/// Returns `true` if this is an access without a known target.
bool get isUnresolved => kind == ObjectAccessTargetKind.unresolved;
/// Returns the original procedure kind, if this is an extension method
/// target.
///
/// This is need because getters, setters, and methods are converted into
/// top level methods, but access and invocation should still be treated as
/// if they are the original procedure kind.
ProcedureKind get extensionMethodKind =>
throw new UnsupportedError('ObjectAccessTarget.extensionMethodKind');
/// Returns the number of type parameters of an extension method that comes
/// from the extension declaration.
int get extensionTypeParameterCount => throw new UnsupportedError(
'ObjectAccessTarget.extensionTypeParameterCount');
@override
String toString() => 'ObjectAccessTarget($kind,$member)';
}
class ExtensionAccessTarget extends ObjectAccessTarget {
final ProcedureKind extensionMethodKind;
final int extensionTypeParameterCount;
ExtensionAccessTarget(
Member member, this.extensionMethodKind, this.extensionTypeParameterCount)
: super.internal(ObjectAccessTargetKind.extensionMember, member);
@override
String toString() =>
'ExtensionAccessTarget($kind,$member,$extensionMethodKind)';
}
@@ -1412,6 +1412,7 @@ investigate
invocation
invocation's
invocations
invokable
invoke
invoked
invokes
@@ -72,8 +72,10 @@ static method Extension|get#tearOffGetterNamed(final self::Class* #this) → dyn
return ({dynamic value = #C1}) → dynamic => self::Extension|writeSetterNamed(#this, value: value);
static method Extension|get#property(final self::Class* #this) → dynamic
return #this.{self::Class::field};
static method Extension|set#property(final self::Class* #this, dynamic value) → void {
static method Extension|set#property(final self::Class* #this, dynamic value) → dynamic {
final dynamic #t1 = value;
#this.{self::Class::field} = value;
return #t1;
}
static method Extension|invocations(final self::Class* #this, dynamic value) → dynamic {
self::Extension|readGetter(#this);
@@ -126,8 +128,10 @@ static method GenericExtension|genericWriteSetterNamed<#T extends core::Object*
}
static method GenericExtension|get#property<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::#T*>* #this) → self::GenericExtension|get#property::#T*
return #this.{self::GenericClass::field};
static method GenericExtension|set#property<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::#T*>* #this, self::GenericExtension|set#property::#T* value) → void {
static method GenericExtension|set#property<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::#T*>* #this, self::GenericExtension|set#property::#T* value) → self::GenericExtension|set#property::#T* {
final self::GenericExtension|set#property::#T* #t2 = value;
#this.{self::GenericClass::field} = value;
return #t2;
}
static method GenericExtension|get#tearOffGetterNoArgs<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#tearOffGetterNoArgs::#T*>* #this) → dynamic
return () → self::GenericExtension|get#tearOffGetterNoArgs::#T* => self::GenericExtension|readGetter<self::GenericExtension|get#tearOffGetterNoArgs::#T*>(#this);
@@ -72,8 +72,10 @@ static method Extension|get#tearOffGetterNamed(final self::Class* #this) → dyn
return ({dynamic value = #C1}) → dynamic => self::Extension|writeSetterNamed(#this, value: value);
static method Extension|get#property(final self::Class* #this) → dynamic
return #this.{self::Class::field};
static method Extension|set#property(final self::Class* #this, dynamic value) → void {
static method Extension|set#property(final self::Class* #this, dynamic value) → dynamic {
final dynamic #t1 = value;
#this.{self::Class::field} = value;
return #t1;
}
static method Extension|invocations(final self::Class* #this, dynamic value) → dynamic {
self::Extension|readGetter(#this);
@@ -126,8 +128,10 @@ static method GenericExtension|genericWriteSetterNamed<#T extends core::Object*
}
static method GenericExtension|get#property<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#property::#T*>* #this) → self::GenericExtension|get#property::#T*
return #this.{self::GenericClass::field};
static method GenericExtension|set#property<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::#T*>* #this, self::GenericExtension|set#property::#T* value) → void {
static method GenericExtension|set#property<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|set#property::#T*>* #this, self::GenericExtension|set#property::#T* value) → self::GenericExtension|set#property::#T* {
final self::GenericExtension|set#property::#T* #t2 = value;
#this.{self::GenericClass::field} = value;
return #t2;
}
static method GenericExtension|get#tearOffGetterNoArgs<#T extends core::Object* = dynamic>(final self::GenericClass<self::GenericExtension|get#tearOffGetterNoArgs::#T*>* #this) → dynamic
return () → self::GenericExtension|get#tearOffGetterNoArgs::#T* => self::GenericExtension|readGetter<self::GenericExtension|get#tearOffGetterNoArgs::#T*>(#this);
@@ -1,13 +1,4 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/extension_methods.dart:19:26: Error: The getter 'two' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/extensions/extension_methods.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'two'.
// var result = c.one + c.two;
// ^^^
//
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;
@@ -28,10 +19,6 @@ static method E|get#two(final self::C* #this) → core::int*
return 2;
static method main() → dynamic {
self::C* c = new self::C::•();
core::num* result = c.{self::C::one}.{core::num::+}(invalid-expression "pkg/front_end/testcases/extensions/extension_methods.dart:19:26: Error: The getter 'two' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/extensions/extension_methods.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'two'.
var result = c.one + c.two;
^^^" as{TypeError} core::num*);
core::int* result = c.{self::C::one}.{core::num::+}(self::E|get#two(c));
exp::Expect::equals(result, 3);
}
@@ -1,13 +1,4 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/extension_methods.dart:19:26: Error: The getter 'two' isn't defined for the class 'C'.
// - 'C' is from 'pkg/front_end/testcases/extensions/extension_methods.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'two'.
// var result = c.one + c.two;
// ^^^
//
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;
@@ -28,10 +19,6 @@ static method E|get#two(final self::C* #this) → core::int*
return 2;
static method main() → dynamic {
self::C* c = new self::C::•();
core::num* result = c.{self::C::one}.{core::num::+}(invalid-expression "pkg/front_end/testcases/extensions/extension_methods.dart:19:26: Error: The getter 'two' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/extensions/extension_methods.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'two'.
var result = c.one + c.two;
^^^" as{TypeError} core::num*);
core::int* result = c.{self::C::one}.{core::num::+}(self::E|get#two(c));
exp::Expect::equals(result, 3);
}
@@ -0,0 +1,111 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class Class1 {
int field;
Class1(this.field);
String toString() => 'Class1($field)';
}
class Class2 {
int field;
Class2(this.field);
String toString() => 'Class2($field)';
}
extension Extension1 on Class1 {
int method() {
print('Extension1.method on $this');
return field;
}
int genericMethod<T extends num>(T t) {
print('Extension1.genericMethod<$T>($t) on $this');
return field + t;
}
int get property {
print('Extension1.property get on $this');
return field;
}
set property(int value) {
field = value;
print('Extension1.property set($value) on $this');
value++;
}
}
extension Extension2 on Class2 {
int method() {
print('Extension2.method on $this');
return field + 3;
}
int genericMethod<T extends num>(T t) {
print('Extension2.genericMethod<$T>($t) on $this');
return field + t + 4;
}
int get property {
print('Extension2.property get on $this');
return field + 5;
}
set property(int value) {
print('Extension2.property set($value) on $this');
value++;
field = value;
}
}
main() {
testExtension1();
testExtension2();
}
testExtension1() {
Class1 c0 = new Class1(0);
Class1 c1 = new Class1(1);
expect(0, c0.method());
expect(1, c1.method());
expect(42, c0.genericMethod(42));
expect(43, c0.genericMethod<num>(43));
expect(88, c1.genericMethod(87));
expect(89, c1.genericMethod<num>(88));
expect(0, c0.property);
expect(42, c0.property = 42);
expect(1, c1.property);
expect(87, c0.property = 87);
expect(27, c0.property = c1.property = 27);
expect(37, c1.property = c0.property = 37);
expect(77, c1.property = c0.property = c1.property = 77);
expect(67, c0.property = c1.property = c0.property = 67);
}
testExtension2() {
Class2 c0 = new Class2(0);
Class2 c1 = new Class2(1);
expect(3, c0.method());
expect(4, c1.method());
expect(46, c0.genericMethod(42));
expect(47, c0.genericMethod<num>(43));
expect(92, c1.genericMethod(87));
expect(93, c1.genericMethod<num>(88));
expect(5, c0.property);
expect(42, c0.property = 42);
expect(48, c0.property);
expect(6, c1.property);
expect(43, c1.property = 43);
expect(49, c1.property);
expect(49, c0.property = c1.property);
expect(55, c1.property = c0.property);
expect(61, c1.property = c0.property = c1.property);
expect(67, c0.property = c1.property = c0.property);
}
expect(expected, actual) {
if (expected != actual) {
throw 'Mismatch: expected=$expected, actual=$actual';
}
}
@@ -0,0 +1,54 @@
library;
import self as self;
import "dart:core" as core;
class Class1 extends core::Object {
field core::int* field;
constructor •(core::int* field) → self::Class1*
;
method toString() → core::String*
;
}
class Class2 extends core::Object {
field core::int* field;
constructor •(core::int* field) → self::Class2*
;
method toString() → core::String*
;
}
extension Extension1 on self::Class1* {
method method = self::Extension1|method;
method genericMethod = self::Extension1|genericMethod;
get property = self::Extension1|get#property;
set property = self::Extension1|set#property;
}
extension Extension2 on self::Class2* {
method method = self::Extension2|method;
method genericMethod = self::Extension2|genericMethod;
get property = self::Extension2|get#property;
set property = self::Extension2|set#property;
}
static method Extension1|method(final self::Class1* #this) → core::int*
;
static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int*
;
static method Extension1|get#property(final self::Class1* #this) → core::int*
;
static method Extension1|set#property(final self::Class1* #this, core::int* value) → void
;
static method Extension2|method(final self::Class2* #this) → core::int*
;
static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int*
;
static method Extension2|get#property(final self::Class2* #this) → core::int*
;
static method Extension2|set#property(final self::Class2* #this, core::int* value) → void
;
static method main() → dynamic
;
static method testExtension1() → dynamic
;
static method testExtension2() → dynamic
;
static method expect(dynamic expected, dynamic actual) → dynamic
;
@@ -0,0 +1,117 @@
library;
import self as self;
import "dart:core" as core;
class Class1 extends core::Object {
field core::int* field;
constructor •(core::int* field) → self::Class1*
: self::Class1::field = field, super core::Object::•()
;
method toString() → core::String*
return "Class1(${this.{self::Class1::field}})";
}
class Class2 extends core::Object {
field core::int* field;
constructor •(core::int* field) → self::Class2*
: self::Class2::field = field, super core::Object::•()
;
method toString() → core::String*
return "Class2(${this.{self::Class2::field}})";
}
extension Extension1 on self::Class1* {
method method = self::Extension1|method;
method genericMethod = self::Extension1|genericMethod;
get property = self::Extension1|get#property;
set property = self::Extension1|set#property;
}
extension Extension2 on self::Class2* {
method method = self::Extension2|method;
method genericMethod = self::Extension2|genericMethod;
get property = self::Extension2|get#property;
set property = self::Extension2|set#property;
}
static method Extension1|method(final self::Class1* #this) → core::int* {
core::print("Extension1.method on ${#this}");
return #this.{self::Class1::field};
}
static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
core::print("Extension1.genericMethod<${self::Extension1|genericMethod::T*}>(${t}) on ${#this}");
return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
}
static method Extension1|get#property(final self::Class1* #this) → core::int* {
core::print("Extension1.property get on ${#this}");
return #this.{self::Class1::field};
}
static method Extension1|set#property(final self::Class1* #this, core::int* value) → core::int* {
final core::int* #t1 = value;
#this.{self::Class1::field} = value;
core::print("Extension1.property set(${value}) on ${#this}");
value = value.{core::num::+}(1);
return #t1;
}
static method Extension2|method(final self::Class2* #this) → core::int* {
core::print("Extension2.method on ${#this}");
return #this.{self::Class2::field}.{core::num::+}(3);
}
static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
core::print("Extension2.genericMethod<${self::Extension2|genericMethod::T*}>(${t}) on ${#this}");
return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
}
static method Extension2|get#property(final self::Class2* #this) → core::int* {
core::print("Extension2.property get on ${#this}");
return #this.{self::Class2::field}.{core::num::+}(5);
}
static method Extension2|set#property(final self::Class2* #this, core::int* value) → core::int* {
final core::int* #t2 = value;
core::print("Extension2.property set(${value}) on ${#this}");
value = value.{core::num::+}(1);
#this.{self::Class2::field} = value;
return #t2;
}
static method main() → dynamic {
self::testExtension1();
self::testExtension2();
}
static method testExtension1() → dynamic {
self::Class1* c0 = new self::Class1::•(0);
self::Class1* c1 = new self::Class1::•(1);
self::expect(0, self::Extension1|method(c0));
self::expect(1, self::Extension1|method(c1));
self::expect(42, self::Extension1|genericMethod<core::int*>(c0, 42));
self::expect(43, self::Extension1|genericMethod<core::num*>(c0, 43));
self::expect(88, self::Extension1|genericMethod<core::int*>(c1, 87));
self::expect(89, self::Extension1|genericMethod<core::num*>(c1, 88));
self::expect(0, self::Extension1|get#property(c0));
self::expect(42, self::Extension1|set#property(c0, 42));
self::expect(1, self::Extension1|get#property(c1));
self::expect(87, self::Extension1|set#property(c0, 87));
self::expect(27, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 27)));
self::expect(37, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 37)));
self::expect(77, self::Extension1|set#property(c1, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 77))));
self::expect(67, self::Extension1|set#property(c0, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 67))));
}
static method testExtension2() → dynamic {
self::Class2* c0 = new self::Class2::•(0);
self::Class2* c1 = new self::Class2::•(1);
self::expect(3, self::Extension2|method(c0));
self::expect(4, self::Extension2|method(c1));
self::expect(46, self::Extension2|genericMethod<core::int*>(c0, 42));
self::expect(47, self::Extension2|genericMethod<core::num*>(c0, 43));
self::expect(92, self::Extension2|genericMethod<core::int*>(c1, 87));
self::expect(93, self::Extension2|genericMethod<core::num*>(c1, 88));
self::expect(5, self::Extension2|get#property(c0));
self::expect(42, self::Extension2|set#property(c0, 42));
self::expect(48, self::Extension2|get#property(c0));
self::expect(6, self::Extension2|get#property(c1));
self::expect(43, self::Extension2|set#property(c1, 43));
self::expect(49, self::Extension2|get#property(c1));
self::expect(49, self::Extension2|set#property(c0, self::Extension2|get#property(c1)));
self::expect(55, self::Extension2|set#property(c1, self::Extension2|get#property(c0)));
self::expect(61, self::Extension2|set#property(c1, self::Extension2|set#property(c0, self::Extension2|get#property(c1))));
self::expect(67, self::Extension2|set#property(c0, self::Extension2|set#property(c1, self::Extension2|get#property(c0))));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
}
}
@@ -0,0 +1,117 @@
library;
import self as self;
import "dart:core" as core;
class Class1 extends core::Object {
field core::int* field;
constructor •(core::int* field) → self::Class1*
: self::Class1::field = field, super core::Object::•()
;
method toString() → core::String*
return "Class1(${this.{self::Class1::field}})";
}
class Class2 extends core::Object {
field core::int* field;
constructor •(core::int* field) → self::Class2*
: self::Class2::field = field, super core::Object::•()
;
method toString() → core::String*
return "Class2(${this.{self::Class2::field}})";
}
extension Extension1 on self::Class1* {
method method = self::Extension1|method;
method genericMethod = self::Extension1|genericMethod;
get property = self::Extension1|get#property;
set property = self::Extension1|set#property;
}
extension Extension2 on self::Class2* {
method method = self::Extension2|method;
method genericMethod = self::Extension2|genericMethod;
get property = self::Extension2|get#property;
set property = self::Extension2|set#property;
}
static method Extension1|method(final self::Class1* #this) → core::int* {
core::print("Extension1.method on ${#this}");
return #this.{self::Class1::field};
}
static method Extension1|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::Extension1|genericMethod::T* t) → core::int* {
core::print("Extension1.genericMethod<${self::Extension1|genericMethod::T*}>(${t}) on ${#this}");
return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
}
static method Extension1|get#property(final self::Class1* #this) → core::int* {
core::print("Extension1.property get on ${#this}");
return #this.{self::Class1::field};
}
static method Extension1|set#property(final self::Class1* #this, core::int* value) → core::int* {
final core::int* #t1 = value;
#this.{self::Class1::field} = value;
core::print("Extension1.property set(${value}) on ${#this}");
value = value.{core::num::+}(1);
return #t1;
}
static method Extension2|method(final self::Class2* #this) → core::int* {
core::print("Extension2.method on ${#this}");
return #this.{self::Class2::field}.{core::num::+}(3);
}
static method Extension2|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::Extension2|genericMethod::T* t) → core::int* {
core::print("Extension2.genericMethod<${self::Extension2|genericMethod::T*}>(${t}) on ${#this}");
return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
}
static method Extension2|get#property(final self::Class2* #this) → core::int* {
core::print("Extension2.property get on ${#this}");
return #this.{self::Class2::field}.{core::num::+}(5);
}
static method Extension2|set#property(final self::Class2* #this, core::int* value) → core::int* {
final core::int* #t2 = value;
core::print("Extension2.property set(${value}) on ${#this}");
value = value.{core::num::+}(1);
#this.{self::Class2::field} = value;
return #t2;
}
static method main() → dynamic {
self::testExtension1();
self::testExtension2();
}
static method testExtension1() → dynamic {
self::Class1* c0 = new self::Class1::•(0);
self::Class1* c1 = new self::Class1::•(1);
self::expect(0, self::Extension1|method(c0));
self::expect(1, self::Extension1|method(c1));
self::expect(42, self::Extension1|genericMethod<core::int*>(c0, 42));
self::expect(43, self::Extension1|genericMethod<core::num*>(c0, 43));
self::expect(88, self::Extension1|genericMethod<core::int*>(c1, 87));
self::expect(89, self::Extension1|genericMethod<core::num*>(c1, 88));
self::expect(0, self::Extension1|get#property(c0));
self::expect(42, self::Extension1|set#property(c0, 42));
self::expect(1, self::Extension1|get#property(c1));
self::expect(87, self::Extension1|set#property(c0, 87));
self::expect(27, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 27)));
self::expect(37, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 37)));
self::expect(77, self::Extension1|set#property(c1, self::Extension1|set#property(c0, self::Extension1|set#property(c1, 77))));
self::expect(67, self::Extension1|set#property(c0, self::Extension1|set#property(c1, self::Extension1|set#property(c0, 67))));
}
static method testExtension2() → dynamic {
self::Class2* c0 = new self::Class2::•(0);
self::Class2* c1 = new self::Class2::•(1);
self::expect(3, self::Extension2|method(c0));
self::expect(4, self::Extension2|method(c1));
self::expect(46, self::Extension2|genericMethod<core::int*>(c0, 42));
self::expect(47, self::Extension2|genericMethod<core::num*>(c0, 43));
self::expect(92, self::Extension2|genericMethod<core::int*>(c1, 87));
self::expect(93, self::Extension2|genericMethod<core::num*>(c1, 88));
self::expect(5, self::Extension2|get#property(c0));
self::expect(42, self::Extension2|set#property(c0, 42));
self::expect(48, self::Extension2|get#property(c0));
self::expect(6, self::Extension2|get#property(c1));
self::expect(43, self::Extension2|set#property(c1, 43));
self::expect(49, self::Extension2|get#property(c1));
self::expect(49, self::Extension2|set#property(c0, self::Extension2|get#property(c1)));
self::expect(55, self::Extension2|set#property(c1, self::Extension2|get#property(c0)));
self::expect(61, self::Extension2|set#property(c1, self::Extension2|set#property(c0, self::Extension2|get#property(c1))));
self::expect(67, self::Extension2|set#property(c0, self::Extension2|set#property(c1, self::Extension2|get#property(c0))));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
throw "Mismatch: expected=${expected}, actual=${actual}";
}
}
@@ -0,0 +1,6 @@
pkg/front_end/testcases/extensions/instance_access.dart:37:10: Context: Write to value@755
value++;
^^
pkg/front_end/testcases/extensions/instance_access.dart:57:10: Context: Write to value@1217
value++;
^^
@@ -0,0 +1,32 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class Class1 {
}
extension Extension1 on Class1 {
static staticMethod() {
print('Extension1.staticMethod()');
}
static get staticProperty {
print('Extension1.staticProperty()');
}
static set staticProperty(int value) {
print('Extension1.staticProperty($value)');
value++;
}
static var staticField = 42;
}
main() {
Class1 c = new Class1();
c.staticMethod();
c.staticMethod;
c.staticProperty;
c.staticProperty = 42;
c.staticField;
c.staticField = 42;
}
@@ -0,0 +1,23 @@
library;
import self as self;
import "dart:core" as core;
class Class1 extends core::Object {
synthetic constructor •() → self::Class1*
;
}
extension Extension1 on self::Class1* {
static method staticMethod = self::Extension1|staticMethod;
static get staticProperty = get self::Extension1|staticProperty;
static field staticField = self::Extension1|staticField;
static set staticProperty = set self::Extension1|staticProperty;
}
static field core::int* Extension1|staticField;
static method Extension1|staticMethod() → dynamic
;
static get Extension1|staticProperty() → dynamic
;
static set Extension1|staticProperty(core::int* value) → void
;
static method main() → dynamic
;
@@ -0,0 +1,98 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:26:5: Error: The method 'staticMethod' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing method, or defining a method named 'staticMethod'.
// c.staticMethod();
// ^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:27:5: Error: The getter 'staticMethod' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticMethod'.
// c.staticMethod;
// ^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:28:5: Error: The getter 'staticProperty' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticProperty'.
// c.staticProperty;
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:29:5: Error: The setter 'staticProperty' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticProperty'.
// c.staticProperty = 42;
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:30:5: Error: The getter 'staticField' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticField'.
// c.staticField;
// ^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:31:5: Error: The setter 'staticField' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticField'.
// c.staticField = 42;
// ^^^^^^^^^^^
//
import self as self;
import "dart:core" as core;
class Class1 extends core::Object {
synthetic constructor •() → self::Class1*
: super core::Object::•()
;
}
extension Extension1 on self::Class1* {
static method staticMethod = self::Extension1|staticMethod;
static get staticProperty = get self::Extension1|staticProperty;
static field staticField = self::Extension1|staticField;
static set staticProperty = set self::Extension1|staticProperty;
}
static field core::int* Extension1|staticField = 42;
static method Extension1|staticMethod() → dynamic {
core::print("Extension1.staticMethod()");
}
static get Extension1|staticProperty() → dynamic {
core::print("Extension1.staticProperty()");
}
static set Extension1|staticProperty(core::int* value) → void {
core::print("Extension1.staticProperty(${value})");
value = value.{core::num::+}(1);
}
static method main() → dynamic {
self::Class1* c = new self::Class1::•();
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:26:5: Error: The method 'staticMethod' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing method, or defining a method named 'staticMethod'.
c.staticMethod();
^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:27:5: Error: The getter 'staticMethod' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticMethod'.
c.staticMethod;
^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:28:5: Error: The getter 'staticProperty' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticProperty'.
c.staticProperty;
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:29:5: Error: The setter 'staticProperty' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticProperty'.
c.staticProperty = 42;
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:30:5: Error: The getter 'staticField' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticField'.
c.staticField;
^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:31:5: Error: The setter 'staticField' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticField'.
c.staticField = 42;
^^^^^^^^^^^";
}
@@ -0,0 +1,98 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:26:5: Error: The method 'staticMethod' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing method, or defining a method named 'staticMethod'.
// c.staticMethod();
// ^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:27:5: Error: The getter 'staticMethod' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticMethod'.
// c.staticMethod;
// ^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:28:5: Error: The getter 'staticProperty' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticProperty'.
// c.staticProperty;
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:29:5: Error: The setter 'staticProperty' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticProperty'.
// c.staticProperty = 42;
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:30:5: Error: The getter 'staticField' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticField'.
// c.staticField;
// ^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/instance_access_of_static.dart:31:5: Error: The setter 'staticField' isn't defined for the class 'Class1'.
// - 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
// Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticField'.
// c.staticField = 42;
// ^^^^^^^^^^^
//
import self as self;
import "dart:core" as core;
class Class1 extends core::Object {
synthetic constructor •() → self::Class1*
: super core::Object::•()
;
}
extension Extension1 on self::Class1* {
static method staticMethod = self::Extension1|staticMethod;
static get staticProperty = get self::Extension1|staticProperty;
static field staticField = self::Extension1|staticField;
static set staticProperty = set self::Extension1|staticProperty;
}
static field core::int* Extension1|staticField = 42;
static method Extension1|staticMethod() → dynamic {
core::print("Extension1.staticMethod()");
}
static get Extension1|staticProperty() → dynamic {
core::print("Extension1.staticProperty()");
}
static set Extension1|staticProperty(core::int* value) → void {
core::print("Extension1.staticProperty(${value})");
value = value.{core::num::+}(1);
}
static method main() → dynamic {
self::Class1* c = new self::Class1::•();
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:26:5: Error: The method 'staticMethod' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing method, or defining a method named 'staticMethod'.
c.staticMethod();
^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:27:5: Error: The getter 'staticMethod' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticMethod'.
c.staticMethod;
^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:28:5: Error: The getter 'staticProperty' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticProperty'.
c.staticProperty;
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:29:5: Error: The setter 'staticProperty' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticProperty'.
c.staticProperty = 42;
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:30:5: Error: The getter 'staticField' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'staticField'.
c.staticField;
^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/instance_access_of_static.dart:31:5: Error: The setter 'staticField' isn't defined for the class 'Class1'.
- 'Class1' is from 'pkg/front_end/testcases/extensions/instance_access_of_static.dart'.
Try correcting the name to the name of an existing setter, or defining a setter or field named 'staticField'.
c.staticField = 42;
^^^^^^^^^^^";
}
@@ -0,0 +1,3 @@
pkg/front_end/testcases/extensions/instance_access_of_static.dart:18:10: Context: Write to value@447
value++;
^^
@@ -30,8 +30,10 @@ extension A2 on self::A1* {
static field core::int* A2|staticField = self::A1::getStaticField();
static method A2|get#instanceProperty(final self::A1* #this) → core::int*
return #this.{self::A1::getInstanceField}();
static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → void {
static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → core::int* {
final core::int* #t1 = value;
#this.{self::A1::setInstanceField}(value);
return #t1;
}
static method A2|+(final self::A1* #this, core::int* value) → core::int* {
return #this.{self::A1::getInstanceField}().{core::num::+}(value);
@@ -30,8 +30,10 @@ extension A2 on self::A1* {
static field core::int* A2|staticField = self::A1::getStaticField();
static method A2|get#instanceProperty(final self::A1* #this) → core::int*
return #this.{self::A1::getInstanceField}();
static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → void {
static method A2|set#instanceProperty(final self::A1* #this, core::int* value) → core::int* {
final core::int* #t1 = value;
#this.{self::A1::setInstanceField}(value);
return #t1;
}
static method A2|+(final self::A1* #this, core::int* value) → core::int* {
return #this.{self::A1::getInstanceField}().{core::num::+}(value);
@@ -10,6 +10,10 @@ extension Extension on Class {
static get property => 42;
static set property(value) {}
static var field;
instanceMethod() {}
get instanceProperty => 42;
set instanceProperty(value) {}
}
main() {
@@ -22,4 +26,4 @@ main() {
Extension.property = 42;
Extension.field;
Extension.field = 42;
}
}
@@ -11,7 +11,10 @@ extension Extension on self::Class* {
static method genericMethod = self::Extension|genericMethod;
static get property = get self::Extension|property;
static field field = self::Extension|field;
method instanceMethod = self::Extension|instanceMethod;
get instanceProperty = self::Extension|get#instanceProperty;
static set property = set self::Extension|property;
set instanceProperty = self::Extension|set#instanceProperty;
}
static field dynamic Extension|field;
static method Extension|method() → dynamic
@@ -22,5 +25,11 @@ static get Extension|property() → dynamic
;
static set Extension|property(dynamic value) → void
;
static method Extension|instanceMethod(final self::Class* #this) → dynamic
;
static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
;
static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → void
;
static method main() → dynamic
;
@@ -12,7 +12,10 @@ extension Extension on self::Class* {
static method genericMethod = self::Extension|genericMethod;
static get property = get self::Extension|property;
static field field = self::Extension|field;
method instanceMethod = self::Extension|instanceMethod;
get instanceProperty = self::Extension|get#instanceProperty;
static set property = set self::Extension|property;
set instanceProperty = self::Extension|set#instanceProperty;
}
static field dynamic Extension|field;
static method Extension|method() → dynamic {}
@@ -20,6 +23,13 @@ static method Extension|genericMethod<T extends core::Object* = dynamic>(self::E
static get Extension|property() → dynamic
return 42;
static set Extension|property(dynamic value) → void {}
static method Extension|instanceMethod(final self::Class* #this) → dynamic {}
static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
return 42;
static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
final dynamic #t1 = value;
return #t1;
}
static method main() → dynamic {
self::Extension|method();
self::Extension|genericMethod<core::int*>(42);
@@ -12,7 +12,10 @@ extension Extension on self::Class* {
static method genericMethod = self::Extension|genericMethod;
static get property = get self::Extension|property;
static field field = self::Extension|field;
method instanceMethod = self::Extension|instanceMethod;
get instanceProperty = self::Extension|get#instanceProperty;
static set property = set self::Extension|property;
set instanceProperty = self::Extension|set#instanceProperty;
}
static field dynamic Extension|field;
static method Extension|method() → dynamic {}
@@ -20,6 +23,13 @@ static method Extension|genericMethod<T extends core::Object* = dynamic>(self::E
static get Extension|property() → dynamic
return 42;
static set Extension|property(dynamic value) → void {}
static method Extension|instanceMethod(final self::Class* #this) → dynamic {}
static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
return 42;
static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
final dynamic #t1 = value;
return #t1;
}
static method main() → dynamic {
self::Extension|method();
self::Extension|genericMethod<core::int*>(42);
@@ -0,0 +1,18 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class Class {}
extension Extension on Class {
instanceMethod() {}
get instanceProperty => 42;
set instanceProperty(value) {}
}
main() {
Extension.instanceMethod();
Extension.instanceMethod;
Extension.instanceProperty;
Extension.instanceProperty = 42;
}
@@ -0,0 +1,21 @@
library;
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
;
}
extension Extension on self::Class* {
method instanceMethod = self::Extension|instanceMethod;
get instanceProperty = self::Extension|get#instanceProperty;
set instanceProperty = self::Extension|set#instanceProperty;
}
static method Extension|instanceMethod(final self::Class* #this) → dynamic
;
static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
;
static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → void
;
static method main() → dynamic
;
@@ -0,0 +1,54 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:14:13: Error: Method not found: 'Extension.instanceMethod'.
// Extension.instanceMethod();
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:15:13: Error: Getter not found: 'instanceMethod'.
// Extension.instanceMethod;
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:16:13: Error: Getter not found: 'instanceProperty'.
// Extension.instanceProperty;
// ^^^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:17:13: Error: Setter not found: 'instanceProperty'.
// Extension.instanceProperty = 42;
// ^^^^^^^^^^^^^^^^
//
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension Extension on self::Class* {
method instanceMethod = self::Extension|instanceMethod;
get instanceProperty = self::Extension|get#instanceProperty;
set instanceProperty = self::Extension|set#instanceProperty;
}
static method Extension|instanceMethod(final self::Class* #this) → dynamic {}
static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
return 42;
static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
final dynamic #t1 = value;
return #t1;
}
static method main() → dynamic {
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:14:13: Error: Method not found: 'Extension.instanceMethod'.
Extension.instanceMethod();
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:15:13: Error: Getter not found: 'instanceMethod'.
Extension.instanceMethod;
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:16:13: Error: Getter not found: 'instanceProperty'.
Extension.instanceProperty;
^^^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:17:13: Error: Setter not found: 'instanceProperty'.
Extension.instanceProperty = 42;
^^^^^^^^^^^^^^^^";
}
@@ -0,0 +1,54 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:14:13: Error: Method not found: 'Extension.instanceMethod'.
// Extension.instanceMethod();
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:15:13: Error: Getter not found: 'instanceMethod'.
// Extension.instanceMethod;
// ^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:16:13: Error: Getter not found: 'instanceProperty'.
// Extension.instanceProperty;
// ^^^^^^^^^^^^^^^^
//
// pkg/front_end/testcases/extensions/static_access_of_instance.dart:17:13: Error: Setter not found: 'instanceProperty'.
// Extension.instanceProperty = 42;
// ^^^^^^^^^^^^^^^^
//
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class*
: super core::Object::•()
;
}
extension Extension on self::Class* {
method instanceMethod = self::Extension|instanceMethod;
get instanceProperty = self::Extension|get#instanceProperty;
set instanceProperty = self::Extension|set#instanceProperty;
}
static method Extension|instanceMethod(final self::Class* #this) → dynamic {}
static method Extension|get#instanceProperty(final self::Class* #this) → dynamic
return 42;
static method Extension|set#instanceProperty(final self::Class* #this, dynamic value) → dynamic {
final dynamic #t1 = value;
return #t1;
}
static method main() → dynamic {
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:14:13: Error: Method not found: 'Extension.instanceMethod'.
Extension.instanceMethod();
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:15:13: Error: Getter not found: 'instanceMethod'.
Extension.instanceMethod;
^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:16:13: Error: Getter not found: 'instanceProperty'.
Extension.instanceProperty;
^^^^^^^^^^^^^^^^";
invalid-expression "pkg/front_end/testcases/extensions/static_access_of_instance.dart:17:13: Error: Setter not found: 'instanceProperty'.
Extension.instanceProperty = 42;
^^^^^^^^^^^^^^^^";
}
+2 -1
View File
@@ -6,7 +6,8 @@
# Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
# strong-mode enabled.
extensions/extension_methods: RuntimeError
extensions/instance_access_of_static: RuntimeError
extensions/static_access_of_instance: RuntimeError
general/abstract_members: TypeCheckError
general/accessors: RuntimeError
general/ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
@@ -11,11 +11,14 @@ expression/main: TextSerializationFailure # Was: Pass
extensions/explicit_this: TextSerializationFailure
extensions/extension_methods: TextSerializationFailure
extensions/implicit_this: TextSerializationFailure
extensions/instance_access: TextSerializationFailure
extensions/instance_access_of_static: TextSerializationFailure
extensions/direct_instance_access: TextSerializationFailure
extensions/direct_static_access: TextSerializationFailure
extensions/instance_members: TextSerializationFailure
extensions/other_kinds: TextSerializationFailure
extensions/static_access: TextSerializationFailure
extensions/static_access_of_instance: TextSerializationFailure
extensions/type_variables: TextSerializationFailure
extensions/use_this: TextSerializationFailure
general/abstract_members: TypeCheckError