| Index: sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| index 2b2a399d82481b936a7a80d430c56a54bcb159f3..2cc56efd9b0ea3a2ece6b4efb2e69d2d67192d89 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
|
| @@ -396,7 +396,23 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (type.treatAsDynamic) {
|
| return const DynamicAccess();
|
| }
|
| - Member member = type.lookupMember(name,
|
| + DartType originalType = type;
|
| + while (identical(type.kind, TypeKind.TYPE_VARIABLE)) {
|
| + TypeVariableType variable = type;
|
| + type = variable.element.bound;
|
| + if (type == originalType) {
|
| + type = compiler.objectClass.rawType;
|
| + }
|
| + }
|
| + if (type.kind == TypeKind.FUNCTION || type.kind == TypeKind.TYPEDEF) {
|
| + // TODO(karlklose): handle calling `call` on the function type. Do we have
|
| + // to type-check the arguments against the function type.
|
| + type = compiler.functionClass.rawType;
|
| + }
|
| + assert(invariant(node, type.kind == TypeKind.INTERFACE,
|
| + message: "unexpected type kind ${type.kind}."));
|
| + InterfaceType interface = type;
|
| + Member member = interface.lookupMember(name,
|
| isSetter: identical(memberKind, MemberKind.SETTER));
|
| if (member != null) {
|
| checkPrivateAccess(node, member.element, name);
|
| @@ -555,21 +571,6 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| return const DynamicAccess();
|
| }
|
| TypeKind receiverKind = receiverType.kind;
|
| - if (identical(receiverKind, TypeKind.TYPEDEF)) {
|
| - // TODO(johnniwinther): handle typedefs.
|
| - return const DynamicAccess();
|
| - }
|
| - if (identical(receiverKind, TypeKind.FUNCTION)) {
|
| - // TODO(johnniwinther): handle functions.
|
| - return const DynamicAccess();
|
| - }
|
| - if (identical(receiverKind, TypeKind.TYPE_VARIABLE)) {
|
| - // TODO(johnniwinther): handle type variables.
|
| - return const DynamicAccess();
|
| - }
|
| - assert(invariant(node.receiver,
|
| - identical(receiverKind, TypeKind.INTERFACE),
|
| - message: "interface type expected, got ${receiverKind}"));
|
| return lookupMember(node, receiverType, name, memberKind);
|
| } else {
|
| return computeResolvedAccess(node, name, element, memberKind);
|
| @@ -715,8 +716,10 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| identical(name, '[]'),
|
| message: 'Unexpected operator $name'));
|
|
|
| - ElementAccess access = lookupMember(node, receiverType,
|
| - operatorName, MemberKind.OPERATOR);
|
| + // TODO(karlklose): handle `void` in expression context by calling
|
| + // [analyzeNonVoid] instead of [analyze].
|
| + ElementAccess access = receiverType.isVoid ? const DynamicAccess()
|
| + : lookupMember(node, receiverType, operatorName, MemberKind.OPERATOR);
|
| LinkBuilder<DartType> argumentTypesBuilder = new LinkBuilder<DartType>();
|
| DartType resultType =
|
| analyzeInvocation(node, access, argumentTypesBuilder);
|
|
|