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

Side by Side Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2271223004: fix #27110, mark implicit downcasts for op assign (Closed)
Patch Set: Created 4 years, 3 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be 5 // TODO(jmesserly): this was ported from package:dev_compiler, and needs to be
6 // refactored to fit into analyzer. 6 // refactored to fit into analyzer.
7 library analyzer.src.task.strong.checker; 7 library analyzer.src.task.strong.checker;
8 8
9 import 'package:analyzer/analyzer.dart'; 9 import 'package:analyzer/analyzer.dart';
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 NodeList<Expression> list = node.arguments; 179 NodeList<Expression> list = node.arguments;
180 int len = list.length; 180 int len = list.length;
181 for (int i = 0; i < len; ++i) { 181 for (int i = 0; i < len; ++i) {
182 Expression arg = list[i]; 182 Expression arg = list[i];
183 ParameterElement element = arg.staticParameterElement; 183 ParameterElement element = arg.staticParameterElement;
184 if (element == null) { 184 if (element == null) {
185 // We found an argument mismatch, the analyzer will report this too, 185 // We found an argument mismatch, the analyzer will report this too,
186 // so no need to insert an error for this here. 186 // so no need to insert an error for this here.
187 continue; 187 continue;
188 } 188 }
189 DartType expectedType = _elementType(element); 189 checkArgument(arg, _elementType(element));
190 if (expectedType == null) expectedType = DynamicTypeImpl.instance;
191 checkArgument(arg, expectedType);
192 } 190 }
193 } 191 }
194 192
195 void checkAssignment(Expression expr, DartType type) { 193 void checkAssignment(Expression expr, DartType type) {
196 if (expr is ParenthesizedExpression) { 194 if (expr is ParenthesizedExpression) {
197 checkAssignment(expr.expression, type); 195 checkAssignment(expr.expression, type);
198 } else { 196 } else {
199 if (_checkNonNullAssignment(expr, type)) { 197 if (_checkNonNullAssignment(expr, type)) {
200 _checkDowncast(expr, type); 198 _checkDowncast(expr, type);
201 } 199 }
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 _recordDynamicInvoke(expr, expr.leftHandSide); 692 _recordDynamicInvoke(expr, expr.leftHandSide);
695 } else { 693 } else {
696 // Sanity check the operator. 694 // Sanity check the operator.
697 assert(methodElement.isOperator); 695 assert(methodElement.isOperator);
698 var functionType = methodElement.type; 696 var functionType = methodElement.type;
699 var paramTypes = functionType.normalParameterTypes; 697 var paramTypes = functionType.normalParameterTypes;
700 assert(paramTypes.length == 1); 698 assert(paramTypes.length == 1);
701 assert(functionType.namedParameterTypes.isEmpty); 699 assert(functionType.namedParameterTypes.isEmpty);
702 assert(functionType.optionalParameterTypes.isEmpty); 700 assert(functionType.optionalParameterTypes.isEmpty);
703 701
704 // Check the LHS type. 702 // Refine the return type.
705 var rhsType = _getDefiniteType(expr.rightHandSide); 703 var rhsType = _getDefiniteType(expr.rightHandSide);
706 var lhsType = _getDefiniteType(expr.leftHandSide); 704 var lhsType = _getDefiniteType(expr.leftHandSide);
707 var returnType = rules.refineBinaryExpressionType( 705 var returnType = rules.refineBinaryExpressionType(
708 typeProvider, lhsType, op, rhsType, functionType.returnType); 706 typeProvider, lhsType, op, rhsType, functionType.returnType);
709 707
710 if (!rules.isSubtypeOf(returnType, lhsType)) { 708 // Check the argument for an implicit cast.
711 final numType = typeProvider.numType; 709 _checkDowncast(expr.rightHandSide, paramTypes[0], from: rhsType);
Jennifer Messerly 2016/08/25 22:27:15 this is my attempt to fix by simplification :)
Leaf 2016/08/25 22:35:34 :)
712 // TODO(jmesserly): this seems to duplicate logic in StaticTypeAnalyzer. 710
713 // Try to fix up the numerical case if possible. 711 // Check the return type for an implicit cast.
714 if (rules.isSubtypeOf(lhsType, numType) && 712 //
715 rules.isSubtypeOf(lhsType, rhsType)) { 713 // If needed, mark the left size to indicate a down cast when we assign
Leaf 2016/08/25 22:35:34 size -> side?
716 // This is also slightly different from spec, but allows us to keep 714 // back to it. so these two implicit casts are equivalent:
717 // compound operators in the int += num and num += dynamic cases. 715 //
718 _recordImplicitCast(expr.rightHandSide, rhsType, lhsType); 716 // y = /*implicit cast*/(y + 42);
719 } else { 717 // y/*implicit cast*/ += 42;
720 // TODO(jmesserly): this results in a duplicate error, because 718 //
721 // ErrorVerifier also reports it. 719 // TODO(jmesserly): this is an unambiguous way to represent it, but it's
Jennifer Messerly 2016/08/25 22:27:15 https://github.com/dart-lang/dev_compiler/issues/6
722 _recordMessage(expr, StrongModeCode.STATIC_TYPE_ERROR, 720 // a bit sneaky. We can't use the rightHandSide because that could be a
723 [expr, returnType, lhsType]); 721 // downcast on its own, and we can't use the entire expression because its
724 } 722 // result value could used and then implicitly downcast.
725 } else { 723 _checkDowncast(expr.leftHandSide, lhsType, from: returnType);
726 // Check the RHS type.
727 //
728 // This is only needed if we didn't already need a cast, and avoids
729 // emitting two messages for the same expression.
730 _checkDowncast(expr.rightHandSide, paramTypes.first);
731 }
732 } 724 }
733 } 725 }
734 726
735 /// Records a [DownCast] of [expr] from [from] to [to], if there is one. 727 /// Records a [DownCast] of [expr] from [from] to [to], if there is one.
736 /// 728 ///
737 /// If [from] is omitted, uses the static type of [expr]. 729 /// If [from] is omitted, uses the static type of [expr].
738 /// 730 ///
739 /// If [expr] does not require a downcast because it is not related to [to] 731 /// If [expr] does not require a downcast because it is not related to [to]
740 /// or is already a subtype of it, does nothing. 732 /// or is already a subtype of it, does nothing.
741 void _checkDowncast(Expression expr, DartType to, {DartType from}) { 733 void _checkDowncast(Expression expr, DartType to, {DartType from}) {
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 var visited = new Set<InterfaceType>(); 1469 var visited = new Set<InterfaceType>();
1478 do { 1470 do {
1479 visited.add(current); 1471 visited.add(current);
1480 current.mixins.reversed.forEach( 1472 current.mixins.reversed.forEach(
1481 (m) => _checkIndividualOverridesFromClass(node, m, seen, true)); 1473 (m) => _checkIndividualOverridesFromClass(node, m, seen, true));
1482 _checkIndividualOverridesFromClass(node, current.superclass, seen, true); 1474 _checkIndividualOverridesFromClass(node, current.superclass, seen, true);
1483 current = current.superclass; 1475 current = current.superclass;
1484 } while (!current.isObject && !visited.contains(current)); 1476 } while (!current.isObject && !visited.contains(current));
1485 } 1477 }
1486 } 1478 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698