Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Issue 2935323002: Lift nearly all top-level type inference restrictions. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 4
5 /// This file declares a "shadow hierarchy" of concrete classes which extend 5 /// This file declares a "shadow hierarchy" of concrete classes which extend
6 /// the kernel class hierarchy, adding methods and fields needed by the 6 /// the kernel class hierarchy, adding methods and fields needed by the
7 /// BodyBuilder. 7 /// BodyBuilder.
8 /// 8 ///
9 /// Instances of these classes may be created using the factory methods in 9 /// Instances of these classes may be created using the factory methods in
10 /// `ast_factory.dart`. 10 /// `ast_factory.dart`.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 if (arguments is KernelArguments) { 46 if (arguments is KernelArguments) {
47 return arguments._hasExplicitTypeArguments ? arguments.types : null; 47 return arguments._hasExplicitTypeArguments ? arguments.types : null;
48 } else { 48 } else {
49 // This code path should only be taken in situations where there are no 49 // This code path should only be taken in situations where there are no
50 // type arguments at all, e.g. calling a user-definable operator. 50 // type arguments at all, e.g. calling a user-definable operator.
51 assert(arguments.types.isEmpty); 51 assert(arguments.types.isEmpty);
52 return null; 52 return null;
53 } 53 }
54 } 54 }
55 55
56 bool _isOverloadableArithmeticOperator(String name) {
57 return identical(name, '+') ||
58 identical(name, '-') ||
59 identical(name, '*') ||
60 identical(name, '%');
61 }
62
63 bool _isUserDefinableOperator(String name) {
64 return identical(name, '<') ||
65 identical(name, '>') ||
66 identical(name, '<=') ||
67 identical(name, '>=') ||
68 identical(name, '==') ||
69 identical(name, '-') ||
70 identical(name, '+') ||
71 identical(name, '/') ||
72 identical(name, '~/') ||
73 identical(name, '*') ||
74 identical(name, '%') ||
75 identical(name, '|') ||
76 identical(name, '^') ||
77 identical(name, '&') ||
78 identical(name, '<<') ||
79 identical(name, '>>') ||
80 identical(name, '[]=') ||
81 identical(name, '~');
82 }
83
56 /// Concrete shadow object representing a set of invocation arguments. 84 /// Concrete shadow object representing a set of invocation arguments.
57 class KernelArguments extends Arguments { 85 class KernelArguments extends Arguments {
58 bool _hasExplicitTypeArguments; 86 bool _hasExplicitTypeArguments;
59 87
60 KernelArguments(List<Expression> positional, 88 KernelArguments(List<Expression> positional,
61 {List<DartType> types, List<NamedExpression> named}) 89 {List<DartType> types, List<NamedExpression> named})
62 : _hasExplicitTypeArguments = types != null && types.isNotEmpty, 90 : _hasExplicitTypeArguments = types != null && types.isNotEmpty,
63 super(positional, types: types, named: named); 91 super(positional, types: types, named: named);
64 92
65 static void setExplicitArgumentTypes( 93 static void setExplicitArgumentTypes(
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 for (var parameter in function.positionalParameters) { 777 for (var parameter in function.positionalParameters) {
750 if (parameter.initializer != null) { 778 if (parameter.initializer != null) {
751 inferrer.inferExpression(parameter.initializer, parameter.type, false); 779 inferrer.inferExpression(parameter.initializer, parameter.type, false);
752 } 780 }
753 } 781 }
754 for (var parameter in function.namedParameters) { 782 for (var parameter in function.namedParameters) {
755 if (parameter.initializer != null) { 783 if (parameter.initializer != null) {
756 inferrer.inferExpression(parameter.initializer, parameter.type, false); 784 inferrer.inferExpression(parameter.initializer, parameter.type, false);
757 } 785 }
758 } 786 }
759 var oldClosureContext = inferrer.closureContext; 787 if (!inferrer.isTopLevel) {
760 inferrer.closureContext = 788 var oldClosureContext = inferrer.closureContext;
761 new ClosureContext(inferrer, function.asyncMarker, function.returnType); 789 inferrer.closureContext = new ClosureContext(
762 inferrer.inferStatement(function.body); 790 inferrer, function.asyncMarker, function.returnType);
763 inferrer.closureContext = oldClosureContext; 791 inferrer.inferStatement(function.body);
792 inferrer.closureContext = oldClosureContext;
793 }
764 inferrer.listener.functionDeclarationExit(this); 794 inferrer.listener.functionDeclarationExit(this);
765 } 795 }
766 } 796 }
767 797
768 /// Concrete shadow object representing a function expression in kernel form. 798 /// Concrete shadow object representing a function expression in kernel form.
769 class KernelFunctionExpression extends FunctionExpression 799 class KernelFunctionExpression extends FunctionExpression
770 implements KernelExpression { 800 implements KernelExpression {
771 KernelFunctionExpression(FunctionNode function) : super(function); 801 KernelFunctionExpression(FunctionNode function) : super(function);
772 802
773 @override 803 @override
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 KernelMethodInvocation(Expression receiver, Name name, Arguments arguments, 1296 KernelMethodInvocation(Expression receiver, Name name, Arguments arguments,
1267 {bool isImplicitCall: false, Member interfaceTarget}) 1297 {bool isImplicitCall: false, Member interfaceTarget})
1268 : _isImplicitCall = isImplicitCall, 1298 : _isImplicitCall = isImplicitCall,
1269 super(receiver, name, arguments, interfaceTarget); 1299 super(receiver, name, arguments, interfaceTarget);
1270 1300
1271 @override 1301 @override
1272 void _collectDependencies(KernelDependencyCollector collector) { 1302 void _collectDependencies(KernelDependencyCollector collector) {
1273 // The inference dependencies are the inference dependencies of the 1303 // The inference dependencies are the inference dependencies of the
1274 // receiver. 1304 // receiver.
1275 collector.collectDependencies(receiver); 1305 collector.collectDependencies(receiver);
1276 if (identical(name, '+') || 1306 if (_isOverloadableArithmeticOperator(name.name)) {
1277 identical(name, '-') ||
1278 identical(name, '*') ||
1279 identical(name, '%')) {
1280 collector.collectDependencies(arguments.positional[0]); 1307 collector.collectDependencies(arguments.positional[0]);
1281 } 1308 }
1282 } 1309 }
1283 1310
1284 @override 1311 @override
1285 DartType _inferExpression( 1312 DartType _inferExpression(
1286 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { 1313 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
1287 typeNeeded = inferrer.listener.methodInvocationEnter(this, typeContext) || 1314 typeNeeded = inferrer.listener.methodInvocationEnter(this, typeContext) ||
1288 typeNeeded; 1315 typeNeeded;
1289 // First infer the receiver so we can look up the method that was invoked. 1316 // First infer the receiver so we can look up the method that was invoked.
1290 var receiverType = inferrer.inferExpression(receiver, null, true); 1317 var receiverType = inferrer.inferExpression(receiver, null, true);
1291 bool isOverloadedArithmeticOperator = false; 1318 bool isOverloadedArithmeticOperator = false;
1292 Member interfaceMember = 1319 Member interfaceMember =
1293 inferrer.findMethodInvocationMember(receiverType, this); 1320 inferrer.findMethodInvocationMember(receiverType, this);
1294 if (interfaceMember is Procedure) { 1321 if (interfaceMember is Procedure) {
1295 isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment 1322 isOverloadedArithmeticOperator = inferrer.typeSchemaEnvironment
1296 .isOverloadedArithmeticOperator(interfaceMember); 1323 .isOverloadedArithmeticOperator(interfaceMember);
1297 } 1324 }
1298 var calleeType = inferrer.getCalleeFunctionType( 1325 var calleeType = inferrer.getCalleeFunctionType(
1299 interfaceMember, receiverType, name, !_isImplicitCall); 1326 interfaceMember, receiverType, name, !_isImplicitCall);
1327 bool forceArgumentInference = false;
1328 if (inferrer.isDryRun) {
1329 if (_isUserDefinableOperator(name.name)) {
1330 // If this is an overloadable arithmetic operator, then type inference
1331 // might depend on the RHS, so conservatively assume it does.
1332 forceArgumentInference = _isOverloadableArithmeticOperator(name.name);
1333 } else {
1334 // If no type arguments were given, then type inference might depend on
1335 // the arguments (because the called method might be generic), so
1336 // conservatively assume it does.
1337 forceArgumentInference = getExplicitTypeArguments(arguments) == null;
1338 }
1339 }
1300 var inferredType = inferrer.inferInvocation(typeContext, typeNeeded, 1340 var inferredType = inferrer.inferInvocation(typeContext, typeNeeded,
1301 fileOffset, calleeType, calleeType.returnType, arguments, 1341 fileOffset, calleeType, calleeType.returnType, arguments,
1302 isOverloadedArithmeticOperator: isOverloadedArithmeticOperator, 1342 isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
1303 receiverType: receiverType); 1343 receiverType: receiverType,
1344 forceArgumentInference: forceArgumentInference);
1304 inferrer.listener.methodInvocationExit(this, inferredType); 1345 inferrer.listener.methodInvocationExit(this, inferredType);
1305 return inferredType; 1346 return inferredType;
1306 } 1347 }
1307 } 1348 }
1308 1349
1309 /// Shadow object for [Not]. 1350 /// Shadow object for [Not].
1310 class KernelNot extends Not implements KernelExpression { 1351 class KernelNot extends Not implements KernelExpression {
1311 KernelNot(Expression operand) : super(operand); 1352 KernelNot(Expression operand) : super(operand);
1312 1353
1313 @override 1354 @override
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 typeNeeded; 1412 typeNeeded;
1372 // TODO(paulberry): record the appropriate types on let variables and 1413 // TODO(paulberry): record the appropriate types on let variables and
1373 // conditional expressions. 1414 // conditional expressions.
1374 var receiverType = _inferReceiver(inferrer); 1415 var receiverType = _inferReceiver(inferrer);
1375 if (read != null) { 1416 if (read != null) {
1376 inferrer.findPropertyGetMember(receiverType, read, silent: true); 1417 inferrer.findPropertyGetMember(receiverType, read, silent: true);
1377 } 1418 }
1378 Member writeMember; 1419 Member writeMember;
1379 if (write != null) { 1420 if (write != null) {
1380 writeMember = inferrer.findPropertySetMember(receiverType, write); 1421 writeMember = inferrer.findPropertySetMember(receiverType, write);
1422 if (inferrer.isTopLevel &&
1423 ((writeMember is Procedure &&
1424 writeMember.kind == ProcedureKind.Setter) ||
1425 writeMember is Field)) {
1426 // References to fields and setters can't be relied upon for top level
1427 // inference.
1428 inferrer.recordNotImmediatelyEvident(fileOffset);
1429 }
1381 } 1430 }
1382 // To replicate analyzer behavior, we base type inference on the write 1431 // To replicate analyzer behavior, we base type inference on the write
1383 // member. TODO(paulberry): would it be better to use the read member when 1432 // member. TODO(paulberry): would it be better to use the read member when
1384 // doing compound assignment? 1433 // doing compound assignment?
1385 var writeContext = writeMember?.setterType; 1434 var writeContext = writeMember?.setterType;
1386 var inferredType = _inferRhs(inferrer, writeContext); 1435 var inferredType = _inferRhs(inferrer, writeContext);
1387 inferrer.listener.propertyAssignExit(desugared, inferredType); 1436 inferrer.listener.propertyAssignExit(desugared, inferredType);
1388 return inferredType; 1437 return inferredType;
1389 } 1438 }
1390 } 1439 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 DartType _inferExpression( 1596 DartType _inferExpression(
1548 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { 1597 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
1549 typeNeeded = inferrer.listener.staticAssignEnter(desugared, typeContext) || 1598 typeNeeded = inferrer.listener.staticAssignEnter(desugared, typeContext) ||
1550 typeNeeded; 1599 typeNeeded;
1551 // TODO(paulberry): record the appropriate types on let variables and 1600 // TODO(paulberry): record the appropriate types on let variables and
1552 // conditional expressions. 1601 // conditional expressions.
1553 DartType writeContext; 1602 DartType writeContext;
1554 var write = this.write; 1603 var write = this.write;
1555 if (write is StaticSet) { 1604 if (write is StaticSet) {
1556 writeContext = write.target.setterType; 1605 writeContext = write.target.setterType;
1606 if (inferrer.isDryRun) {
1607 var target = write.target;
1608 if (target is KernelField && target._fieldNode != null) {
1609 inferrer.recordDryRunDependency(target._fieldNode);
1610 }
1611 }
1557 } 1612 }
1558 var inferredType = _inferRhs(inferrer, writeContext); 1613 var inferredType = _inferRhs(inferrer, writeContext);
1559 inferrer.listener.staticAssignExit(desugared, inferredType); 1614 inferrer.listener.staticAssignExit(desugared, inferredType);
1560 return inferredType; 1615 return inferredType;
1561 } 1616 }
1562 } 1617 }
1563 1618
1564 /// Concrete shadow object representing a read of a static variable in kernel 1619 /// Concrete shadow object representing a read of a static variable in kernel
1565 /// form. 1620 /// form.
1566 class KernelStaticGet extends StaticGet implements KernelExpression { 1621 class KernelStaticGet extends StaticGet implements KernelExpression {
(...skipping 16 matching lines...) Expand all
1583 if (target is KernelField && target._fieldNode != null) { 1638 if (target is KernelField && target._fieldNode != null) {
1584 collector.recordDependency(target._fieldNode); 1639 collector.recordDependency(target._fieldNode);
1585 } 1640 }
1586 } 1641 }
1587 1642
1588 @override 1643 @override
1589 DartType _inferExpression( 1644 DartType _inferExpression(
1590 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { 1645 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
1591 typeNeeded = 1646 typeNeeded =
1592 inferrer.listener.staticGetEnter(this, typeContext) || typeNeeded; 1647 inferrer.listener.staticGetEnter(this, typeContext) || typeNeeded;
1648 if (inferrer.isDryRun) {
1649 var target = this.target;
1650 if (target is KernelField && target._fieldNode != null) {
1651 inferrer.recordDryRunDependency(target._fieldNode);
1652 }
1653 }
1593 var inferredType = typeNeeded ? target.getterType : null; 1654 var inferredType = typeNeeded ? target.getterType : null;
1594 inferrer.listener.staticGetExit(this, inferredType); 1655 inferrer.listener.staticGetExit(this, inferredType);
1595 return inferredType; 1656 return inferredType;
1596 } 1657 }
1597 } 1658 }
1598 1659
1599 /// Shadow object for [StaticInvocation]. 1660 /// Shadow object for [StaticInvocation].
1600 class KernelStaticInvocation extends StaticInvocation 1661 class KernelStaticInvocation extends StaticInvocation
1601 implements KernelExpression { 1662 implements KernelExpression {
1602 KernelStaticInvocation(Procedure target, Arguments arguments, 1663 KernelStaticInvocation(Procedure target, Arguments arguments,
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 : super(engine, uri, listener, topLevel, thisType); 1955 : super(engine, uri, listener, topLevel, thisType);
1895 1956
1896 @override 1957 @override
1897 Expression getFieldInitializer(KernelField field) { 1958 Expression getFieldInitializer(KernelField field) {
1898 return field.initializer; 1959 return field.initializer;
1899 } 1960 }
1900 1961
1901 @override 1962 @override
1902 DartType inferExpression( 1963 DartType inferExpression(
1903 Expression expression, DartType typeContext, bool typeNeeded) { 1964 Expression expression, DartType typeContext, bool typeNeeded) {
1965 // When doing top level inference, we skip subexpressions whose type isn't
1966 // needed so that we don't induce bogus dependencies on fields mentioned in
1967 // those subexpressions.
1968 if (!typeNeeded && isTopLevel) return null;
1969
1904 if (expression is KernelExpression) { 1970 if (expression is KernelExpression) {
1905 // Use polymorphic dispatch on [KernelExpression] to perform whatever kind 1971 // Use polymorphic dispatch on [KernelExpression] to perform whatever kind
1906 // of type inference is correct for this kind of statement. 1972 // of type inference is correct for this kind of statement.
1907 // TODO(paulberry): experiment to see if dynamic dispatch would be better, 1973 // TODO(paulberry): experiment to see if dynamic dispatch would be better,
1908 // so that the type hierarchy will be simpler (which may speed up "is" 1974 // so that the type hierarchy will be simpler (which may speed up "is"
1909 // checks). 1975 // checks).
1910 return expression._inferExpression(this, typeContext, typeNeeded); 1976 return expression._inferExpression(this, typeContext, typeNeeded);
1911 } else { 1977 } else {
1912 // Encountered an expression type for which type inference is not yet 1978 // Encountered an expression type for which type inference is not yet
1913 // implemented, so just infer dynamic for now. 1979 // implemented, so just infer dynamic for now.
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
2227 } 2293 }
2228 2294
2229 transformChildren(v) { 2295 transformChildren(v) {
2230 return internalError("Internal error: Unsupported operation."); 2296 return internalError("Internal error: Unsupported operation.");
2231 } 2297 }
2232 2298
2233 visitChildren(v) { 2299 visitChildren(v) {
2234 return internalError("Internal error: Unsupported operation."); 2300 return internalError("Internal error: Unsupported operation.");
2235 } 2301 }
2236 } 2302 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698