| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library kernel.type_checker; | 4 library kernel.type_checker; |
| 5 | 5 |
| 6 import 'ast.dart'; | 6 import 'ast.dart'; |
| 7 import 'class_hierarchy.dart'; | 7 import 'class_hierarchy.dart'; |
| 8 import 'core_types.dart'; | 8 import 'core_types.dart'; |
| 9 import 'type_algebra.dart'; | 9 import 'type_algebra.dart'; |
| 10 import 'type_environment.dart'; | 10 import 'type_environment.dart'; |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 // have a declared interface target. | 241 // have a declared interface target. |
| 242 fail(access, '$member is not accessible on a receiver of type $type'); | 242 fail(access, '$member is not accessible on a receiver of type $type'); |
| 243 return Substitution.bottomForClass(superclass); // Continue type checking. | 243 return Substitution.bottomForClass(superclass); // Continue type checking. |
| 244 } | 244 } |
| 245 | 245 |
| 246 Substitution getSuperReceiverType(Member member) { | 246 Substitution getSuperReceiverType(Member member) { |
| 247 return Substitution.fromSupertype( | 247 return Substitution.fromSupertype( |
| 248 hierarchy.getClassAsInstanceOf(currentClass, member.enclosingClass)); | 248 hierarchy.getClassAsInstanceOf(currentClass, member.enclosingClass)); |
| 249 } | 249 } |
| 250 | 250 |
| 251 DartType handleCall(Arguments arguments, FunctionNode function, | 251 DartType handleCall(Arguments arguments, DartType functionType, |
| 252 {Substitution receiver: Substitution.empty, | 252 {Substitution receiver: Substitution.empty, |
| 253 List<TypeParameter> typeParameters}) { | 253 List<TypeParameter> typeParameters}) { |
| 254 typeParameters ??= function.typeParameters; | 254 if (functionType is FunctionType) { |
| 255 if (arguments.positional.length < function.requiredParameterCount) { | 255 typeParameters ??= functionType.typeParameters; |
| 256 fail(arguments, 'Too few positional arguments'); | 256 if (arguments.positional.length < functionType.requiredParameterCount) { |
| 257 return const BottomType(); | 257 fail(arguments, 'Too few positional arguments'); |
| 258 } | 258 return const BottomType(); |
| 259 if (arguments.positional.length > function.positionalParameters.length) { | 259 } |
| 260 fail(arguments, 'Too many positional arguments'); | 260 if (arguments.positional.length > |
| 261 return const BottomType(); | 261 functionType.positionalParameters.length) { |
| 262 } | 262 fail(arguments, 'Too many positional arguments'); |
| 263 if (arguments.types.length != typeParameters.length) { | 263 return const BottomType(); |
| 264 fail(arguments, 'Wrong number of type arguments'); | 264 } |
| 265 return const BottomType(); | 265 if (arguments.types.length != typeParameters.length) { |
| 266 } | 266 fail(arguments, 'Wrong number of type arguments'); |
| 267 var instantiation = Substitution.fromPairs(typeParameters, arguments.types); | 267 return const BottomType(); |
| 268 var substitution = Substitution.combine(receiver, instantiation); | 268 } |
| 269 for (int i = 0; i < typeParameters.length; ++i) { | 269 var instantiation = |
| 270 var argument = arguments.types[i]; | 270 Substitution.fromPairs(typeParameters, arguments.types); |
| 271 var bound = substitution.substituteType(typeParameters[i].bound); | 271 var substitution = Substitution.combine(receiver, instantiation); |
| 272 checkAssignable(arguments, argument, bound); | 272 for (int i = 0; i < typeParameters.length; ++i) { |
| 273 } | 273 var argument = arguments.types[i]; |
| 274 for (int i = 0; i < arguments.positional.length; ++i) { | 274 var bound = substitution.substituteType(typeParameters[i].bound); |
| 275 var expectedType = substitution.substituteType( | 275 checkAssignable(arguments, argument, bound); |
| 276 function.positionalParameters[i].type, | 276 } |
| 277 contravariant: true); | 277 for (int i = 0; i < arguments.positional.length; ++i) { |
| 278 arguments.positional[i] = | 278 var expectedType = substitution.substituteType( |
| 279 checkAndDowncastExpression(arguments.positional[i], expectedType); | 279 functionType.positionalParameters[i], |
| 280 } | 280 contravariant: true); |
| 281 for (int i = 0; i < arguments.named.length; ++i) { | 281 arguments.positional[i] = |
| 282 var argument = arguments.named[i]; | 282 checkAndDowncastExpression(arguments.positional[i], expectedType); |
| 283 bool found = false; | 283 } |
| 284 for (int j = 0; j < function.namedParameters.length; ++j) { | 284 for (int i = 0; i < arguments.named.length; ++i) { |
| 285 if (argument.name == function.namedParameters[j].name) { | 285 var argument = arguments.named[i]; |
| 286 var expectedType = substitution.substituteType( | 286 bool found = false; |
| 287 function.namedParameters[j].type, | 287 for (int j = 0; j < functionType.namedParameters.length; ++j) { |
| 288 contravariant: true); | 288 if (argument.name == functionType.namedParameters[j].name) { |
| 289 argument.value = | 289 var expectedType = substitution.substituteType( |
| 290 checkAndDowncastExpression(argument.value, expectedType); | 290 functionType.namedParameters[j].type, |
| 291 found = true; | 291 contravariant: true); |
| 292 break; | 292 argument.value = |
| 293 checkAndDowncastExpression(argument.value, expectedType); |
| 294 found = true; |
| 295 break; |
| 296 } |
| 297 } |
| 298 if (!found) { |
| 299 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); |
| 300 return const BottomType(); |
| 293 } | 301 } |
| 294 } | 302 } |
| 295 if (!found) { | 303 return substitution.substituteType(functionType.returnType); |
| 296 fail(argument.value, 'Unexpected named parameter: ${argument.name}'); | 304 } else { |
| 297 return const BottomType(); | 305 // Note: attempting to resolve .call() on [functionType] could lead to an |
| 298 } | 306 // infinite regress, so just assume `dynamic`. |
| 307 return const DynamicType(); |
| 299 } | 308 } |
| 300 return substitution.substituteType(function.returnType); | |
| 301 } | 309 } |
| 302 | 310 |
| 303 DartType _getInternalReturnType(FunctionNode function) { | 311 DartType _getInternalReturnType(FunctionNode function) { |
| 304 switch (function.asyncMarker) { | 312 switch (function.asyncMarker) { |
| 305 case AsyncMarker.Sync: | 313 case AsyncMarker.Sync: |
| 306 return function.returnType; | 314 return function.returnType; |
| 307 | 315 |
| 308 case AsyncMarker.Async: | 316 case AsyncMarker.Async: |
| 309 Class container = coreTypes.futureClass; | 317 Class container = coreTypes.futureClass; |
| 310 DartType returnType = function.returnType; | 318 DartType returnType = function.returnType; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 node.otherwise = | 380 node.otherwise = |
| 373 checkAndDowncastExpression(node.otherwise, node.staticType); | 381 checkAndDowncastExpression(node.otherwise, node.staticType); |
| 374 return node.staticType; | 382 return node.staticType; |
| 375 } | 383 } |
| 376 | 384 |
| 377 @override | 385 @override |
| 378 DartType visitConstructorInvocation(ConstructorInvocation node) { | 386 DartType visitConstructorInvocation(ConstructorInvocation node) { |
| 379 Constructor target = node.target; | 387 Constructor target = node.target; |
| 380 Arguments arguments = node.arguments; | 388 Arguments arguments = node.arguments; |
| 381 Class class_ = target.enclosingClass; | 389 Class class_ = target.enclosingClass; |
| 382 handleCall(arguments, target.function, | 390 handleCall(arguments, target.function.functionType, |
| 383 typeParameters: class_.typeParameters); | 391 typeParameters: class_.typeParameters); |
| 384 return new InterfaceType(target.enclosingClass, arguments.types); | 392 return new InterfaceType(target.enclosingClass, arguments.types); |
| 385 } | 393 } |
| 386 | 394 |
| 387 @override | 395 @override |
| 388 DartType visitDirectMethodInvocation(DirectMethodInvocation node) { | 396 DartType visitDirectMethodInvocation(DirectMethodInvocation node) { |
| 389 return handleCall(node.arguments, node.target.function, | 397 return handleCall(node.arguments, node.target.getterType, |
| 390 receiver: getReceiverType(node, node.receiver, node.target)); | 398 receiver: getReceiverType(node, node.receiver, node.target)); |
| 391 } | 399 } |
| 392 | 400 |
| 393 @override | 401 @override |
| 394 DartType visitDirectPropertyGet(DirectPropertyGet node) { | 402 DartType visitDirectPropertyGet(DirectPropertyGet node) { |
| 395 var receiver = getReceiverType(node, node.receiver, node.target); | 403 var receiver = getReceiverType(node, node.receiver, node.target); |
| 396 return receiver.substituteType(node.target.getterType); | 404 return receiver.substituteType(node.target.getterType); |
| 397 } | 405 } |
| 398 | 406 |
| 399 @override | 407 @override |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 if (target == null) { | 525 if (target == null) { |
| 518 var receiver = visitExpression(node.receiver); | 526 var receiver = visitExpression(node.receiver); |
| 519 if (node.name.name == '==') { | 527 if (node.name.name == '==') { |
| 520 visitExpression(node.arguments.positional.single); | 528 visitExpression(node.arguments.positional.single); |
| 521 return environment.boolType; | 529 return environment.boolType; |
| 522 } | 530 } |
| 523 if (node.name.name == 'call' && receiver is FunctionType) { | 531 if (node.name.name == 'call' && receiver is FunctionType) { |
| 524 return handleFunctionCall(node, receiver, node.arguments); | 532 return handleFunctionCall(node, receiver, node.arguments); |
| 525 } | 533 } |
| 526 return handleDynamicCall(receiver, node.arguments); | 534 return handleDynamicCall(receiver, node.arguments); |
| 527 } else if (environment.isOverloadedArithmeticOperator(target)) { | 535 } else if (target is Procedure && |
| 536 environment.isOverloadedArithmeticOperator(target)) { |
| 528 assert(node.arguments.positional.length == 1); | 537 assert(node.arguments.positional.length == 1); |
| 529 var receiver = visitExpression(node.receiver); | 538 var receiver = visitExpression(node.receiver); |
| 530 var argument = visitExpression(node.arguments.positional[0]); | 539 var argument = visitExpression(node.arguments.positional[0]); |
| 531 return environment.getTypeOfOverloadedArithmetic(receiver, argument); | 540 return environment.getTypeOfOverloadedArithmetic(receiver, argument); |
| 532 } else { | 541 } else { |
| 533 return handleCall(node.arguments, target.function, | 542 return handleCall(node.arguments, target.getterType, |
| 534 receiver: getReceiverType(node, node.receiver, node.interfaceTarget)); | 543 receiver: getReceiverType(node, node.receiver, node.interfaceTarget)); |
| 535 } | 544 } |
| 536 } | 545 } |
| 537 | 546 |
| 538 @override | 547 @override |
| 539 DartType visitPropertyGet(PropertyGet node) { | 548 DartType visitPropertyGet(PropertyGet node) { |
| 540 if (node.interfaceTarget == null) { | 549 if (node.interfaceTarget == null) { |
| 541 visitExpression(node.receiver); | 550 visitExpression(node.receiver); |
| 542 return const DynamicType(); | 551 return const DynamicType(); |
| 543 } else { | 552 } else { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 return const BottomType(); | 587 return const BottomType(); |
| 579 } | 588 } |
| 580 | 589 |
| 581 @override | 590 @override |
| 582 DartType visitStaticGet(StaticGet node) { | 591 DartType visitStaticGet(StaticGet node) { |
| 583 return node.target.getterType; | 592 return node.target.getterType; |
| 584 } | 593 } |
| 585 | 594 |
| 586 @override | 595 @override |
| 587 DartType visitStaticInvocation(StaticInvocation node) { | 596 DartType visitStaticInvocation(StaticInvocation node) { |
| 588 return handleCall(node.arguments, node.target.function); | 597 return handleCall(node.arguments, node.target.getterType); |
| 589 } | 598 } |
| 590 | 599 |
| 591 @override | 600 @override |
| 592 DartType visitStaticSet(StaticSet node) { | 601 DartType visitStaticSet(StaticSet node) { |
| 593 var value = visitExpression(node.value); | 602 var value = visitExpression(node.value); |
| 594 checkAssignable(node.value, value, node.target.setterType); | 603 checkAssignable(node.value, value, node.target.setterType); |
| 595 return value; | 604 return value; |
| 596 } | 605 } |
| 597 | 606 |
| 598 @override | 607 @override |
| 599 DartType visitStringConcatenation(StringConcatenation node) { | 608 DartType visitStringConcatenation(StringConcatenation node) { |
| 600 node.expressions.forEach(visitExpression); | 609 node.expressions.forEach(visitExpression); |
| 601 return environment.stringType; | 610 return environment.stringType; |
| 602 } | 611 } |
| 603 | 612 |
| 604 @override | 613 @override |
| 605 DartType visitStringLiteral(StringLiteral node) { | 614 DartType visitStringLiteral(StringLiteral node) { |
| 606 return environment.stringType; | 615 return environment.stringType; |
| 607 } | 616 } |
| 608 | 617 |
| 609 @override | 618 @override |
| 610 DartType visitSuperMethodInvocation(SuperMethodInvocation node) { | 619 DartType visitSuperMethodInvocation(SuperMethodInvocation node) { |
| 611 if (node.interfaceTarget == null) { | 620 if (node.interfaceTarget == null) { |
| 612 return handleDynamicCall(environment.thisType, node.arguments); | 621 return handleDynamicCall(environment.thisType, node.arguments); |
| 613 } else { | 622 } else { |
| 614 return handleCall(node.arguments, node.interfaceTarget.function, | 623 return handleCall(node.arguments, node.interfaceTarget.getterType, |
| 615 receiver: getSuperReceiverType(node.interfaceTarget)); | 624 receiver: getSuperReceiverType(node.interfaceTarget)); |
| 616 } | 625 } |
| 617 } | 626 } |
| 618 | 627 |
| 619 @override | 628 @override |
| 620 DartType visitSuperPropertyGet(SuperPropertyGet node) { | 629 DartType visitSuperPropertyGet(SuperPropertyGet node) { |
| 621 if (node.interfaceTarget == null) { | 630 if (node.interfaceTarget == null) { |
| 622 return const DynamicType(); | 631 return const DynamicType(); |
| 623 } else { | 632 } else { |
| 624 var receiver = getSuperReceiverType(node.interfaceTarget); | 633 var receiver = getSuperReceiverType(node.interfaceTarget); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 } | 939 } |
| 931 } | 940 } |
| 932 | 941 |
| 933 @override | 942 @override |
| 934 visitFieldInitializer(FieldInitializer node) { | 943 visitFieldInitializer(FieldInitializer node) { |
| 935 node.value = checkAndDowncastExpression(node.value, node.field.type); | 944 node.value = checkAndDowncastExpression(node.value, node.field.type); |
| 936 } | 945 } |
| 937 | 946 |
| 938 @override | 947 @override |
| 939 visitRedirectingInitializer(RedirectingInitializer node) { | 948 visitRedirectingInitializer(RedirectingInitializer node) { |
| 940 handleCall(node.arguments, node.target.function, | 949 handleCall(node.arguments, node.target.getterType, |
| 941 typeParameters: const <TypeParameter>[]); | 950 typeParameters: const <TypeParameter>[]); |
| 942 } | 951 } |
| 943 | 952 |
| 944 @override | 953 @override |
| 945 visitSuperInitializer(SuperInitializer node) { | 954 visitSuperInitializer(SuperInitializer node) { |
| 946 handleCall(node.arguments, node.target.function, | 955 handleCall(node.arguments, node.target.getterType, |
| 947 typeParameters: const <TypeParameter>[], | 956 typeParameters: const <TypeParameter>[], |
| 948 receiver: getSuperReceiverType(node.target)); | 957 receiver: getSuperReceiverType(node.target)); |
| 949 } | 958 } |
| 950 | 959 |
| 951 @override | 960 @override |
| 952 visitLocalInitializer(LocalInitializer node) { | 961 visitLocalInitializer(LocalInitializer node) { |
| 953 visitVariableDeclaration(node.variable); | 962 visitVariableDeclaration(node.variable); |
| 954 } | 963 } |
| 955 | 964 |
| 956 @override | 965 @override |
| 957 visitInvalidInitializer(InvalidInitializer node) {} | 966 visitInvalidInitializer(InvalidInitializer node) {} |
| 958 } | 967 } |
| OLD | NEW |