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 |