| OLD | NEW |
| 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.rules; | 7 library analyzer.src.task.strong.rules; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 // issues. | 369 // issues. |
| 370 return isFunctionSubTypeOf(t1 as FunctionType, t2 as FunctionType); | 370 return isFunctionSubTypeOf(t1 as FunctionType, t2 as FunctionType); |
| 371 } | 371 } |
| 372 | 372 |
| 373 bool isAssignable(DartType t1, DartType t2) { | 373 bool isAssignable(DartType t1, DartType t2) { |
| 374 return isSubTypeOf(t1, t2); | 374 return isSubTypeOf(t1, t2); |
| 375 } | 375 } |
| 376 | 376 |
| 377 // Produce a coercion which coerces something of type fromT | 377 // Produce a coercion which coerces something of type fromT |
| 378 // to something of type toT. | 378 // to something of type toT. |
| 379 // If wrap is true and both are function types, a closure | |
| 380 // wrapper coercion is produced using _wrapTo (see above) | |
| 381 // Returns the error coercion if the types cannot be coerced | 379 // Returns the error coercion if the types cannot be coerced |
| 382 // according to our current criteria. | 380 // according to our current criteria. |
| 383 Coercion _coerceTo(DartType fromT, DartType toT) { | 381 Coercion _coerceTo(DartType fromT, DartType toT) { |
| 384 // We can use anything as void | 382 // We can use anything as void |
| 385 if (toT.isVoid) return Coercion.identity(toT); | 383 if (toT.isVoid) return Coercion.identity(toT); |
| 386 | 384 |
| 387 // fromT <: toT, no coercion needed | 385 // fromT <: toT, no coercion needed |
| 388 if (isSubTypeOf(fromT, toT)) return Coercion.identity(toT); | 386 if (isSubTypeOf(fromT, toT)) return Coercion.identity(toT); |
| 389 | 387 |
| 390 // For now, reject conversions between function types and | 388 // TODO(vsm): We can get rid of the second clause if we disallow |
| 391 // call method objects. We could choose to allow casts here. | 389 // all sideways casts - see TODO below. |
| 392 // Wrapping a function type to assign it to a call method | 390 // ------- |
| 393 // object will never succeed. Wrapping the other way could | 391 // Note: a function type is never assignable to a class per the Dart |
| 394 // be allowed. | 392 // spec - even if it has a compatible call method. We disallow as |
| 393 // well for consistency. |
| 395 if ((fromT is FunctionType && getCallMethodType(toT) != null) || | 394 if ((fromT is FunctionType && getCallMethodType(toT) != null) || |
| 396 (toT is FunctionType && getCallMethodType(fromT) != null)) { | 395 (toT is FunctionType && getCallMethodType(fromT) != null)) { |
| 397 return Coercion.error(); | 396 return Coercion.error(); |
| 398 } | 397 } |
| 399 | 398 |
| 400 // Downcast if toT <: fromT | 399 // Downcast if toT <: fromT |
| 401 if (isSubTypeOf(toT, fromT)) return Coercion.cast(fromT, toT); | 400 if (isSubTypeOf(toT, fromT)) return Coercion.cast(fromT, toT); |
| 402 | 401 |
| 402 // TODO(vsm): Once we have generic methods, we should delete this |
| 403 // workaround. These sideways casts are always ones we warn about |
| 404 // - i.e., we think they are likely to fail at runtime. |
| 405 // ------- |
| 403 // Downcast if toT <===> fromT | 406 // Downcast if toT <===> fromT |
| 404 // The intention here is to allow casts that are sideways in the restricted | 407 // The intention here is to allow casts that are sideways in the restricted |
| 405 // type system, but allowed in the regular dart type system, since these | 408 // type system, but allowed in the regular dart type system, since these |
| 406 // are likely to succeed. The canonical example is List<dynamic> and | 409 // are likely to succeed. The canonical example is List<dynamic> and |
| 407 // Iterable<T> for some concrete T (e.g. Object). These are unrelated | 410 // Iterable<T> for some concrete T (e.g. Object). These are unrelated |
| 408 // in the restricted system, but List<dynamic> <: Iterable<T> in dart. | 411 // in the restricted system, but List<dynamic> <: Iterable<T> in dart. |
| 409 if (fromT.isAssignableTo(toT)) { | 412 if (fromT.isAssignableTo(toT)) { |
| 410 return Coercion.cast(fromT, toT); | 413 return Coercion.cast(fromT, toT); |
| 411 } | 414 } |
| 415 |
| 412 return Coercion.error(); | 416 return Coercion.error(); |
| 413 } | 417 } |
| 414 | 418 |
| 415 StaticInfo checkAssignment(Expression expr, DartType toT) { | 419 StaticInfo checkAssignment(Expression expr, DartType toT) { |
| 416 final fromT = getStaticType(expr); | 420 final fromT = getStaticType(expr); |
| 417 final Coercion c = _coerceTo(fromT, toT); | 421 final Coercion c = _coerceTo(fromT, toT); |
| 418 if (c is Identity) return null; | 422 if (c is Identity) return null; |
| 419 if (c is CoercionError) return new StaticTypeError(this, expr, toT); | 423 if (c is CoercionError) return new StaticTypeError(this, expr, toT); |
| 420 var reason = null; | 424 var reason = null; |
| 421 | 425 |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 var entries = e.entries; | 765 var entries = e.entries; |
| 762 bool inferEntry(MapLiteralEntry entry) { | 766 bool inferEntry(MapLiteralEntry entry) { |
| 763 return _inferExpression(entry.key, kType, errors) && | 767 return _inferExpression(entry.key, kType, errors) && |
| 764 _inferExpression(entry.value, vType, errors); | 768 _inferExpression(entry.value, vType, errors); |
| 765 } | 769 } |
| 766 var b = entries.every(inferEntry); | 770 var b = entries.every(inferEntry); |
| 767 if (b) annotateMapLiteral(e, targs); | 771 if (b) annotateMapLiteral(e, targs); |
| 768 return b; | 772 return b; |
| 769 } | 773 } |
| 770 } | 774 } |
| OLD | NEW |