| 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 /// Defines static information collected by the type checker and used later by | 5 /// Defines static information collected by the type checker and used later by |
| 6 /// emitters to generate code. | 6 /// emitters to generate code. |
| 7 library dev_compiler.src.info; | 7 library dev_compiler.src.info; |
| 8 | 8 |
| 9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
| 10 | 10 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 assert(rules.maybeNonNullableType(toT)); | 230 assert(rules.maybeNonNullableType(toT)); |
| 231 // TODO(vsm): Create a NullCast for this once we revisit nonnullability. | 231 // TODO(vsm): Create a NullCast for this once we revisit nonnullability. |
| 232 return new DownCastImplicit(rules, expression, cast); | 232 return new DownCastImplicit(rules, expression, cast); |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 // Inference "casts": | 236 // Inference "casts": |
| 237 if (expression is Literal) { | 237 if (expression is Literal) { |
| 238 // fromT should be an exact type - this will almost certainly fail at | 238 // fromT should be an exact type - this will almost certainly fail at |
| 239 // runtime. | 239 // runtime. |
| 240 return new InferableLiteral(rules, expression, cast); | 240 return new StaticTypeError(rules, expression, toT); |
| 241 } | 241 } |
| 242 if (expression is FunctionExpression) { | 242 if (expression is FunctionExpression) { |
| 243 // fromT should be an exact type - this will almost certainly fail at | 243 // fromT should be an exact type - this will almost certainly fail at |
| 244 // runtime. | 244 // runtime. |
| 245 return new InferableClosure(rules, expression, cast); | 245 return new InferableClosure(rules, expression, cast); |
| 246 } | 246 } |
| 247 if (expression is InstanceCreationExpression) { | 247 if (expression is InstanceCreationExpression) { |
| 248 // fromT should be an exact type - this will almost certainly fail at | 248 // fromT should be an exact type - this will almost certainly fail at |
| 249 // runtime. | 249 // runtime. |
| 250 return new InferableAllocation(rules, expression, cast); | 250 return new StaticTypeError(rules, expression, toT); |
| 251 } | 251 } |
| 252 | 252 |
| 253 // Composite cast: these are more likely to fail. | 253 // Composite cast: these are more likely to fail. |
| 254 if (!rules.isGroundType(toT)) { | 254 if (!rules.isGroundType(toT)) { |
| 255 // This cast is (probably) due to our different treatment of dynamic. | 255 // This cast is (probably) due to our different treatment of dynamic. |
| 256 // It may be more likely to fail at runtime. | 256 // It may be more likely to fail at runtime. |
| 257 return new DownCastComposite(rules, expression, cast); | 257 return new DownCastComposite(rules, expression, cast); |
| 258 } | 258 } |
| 259 | 259 |
| 260 // Dynamic cast | 260 // Dynamic cast |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 // | 307 // |
| 308 // Temporary "casts" of allocation sites - literals, constructor invocations, | 308 // Temporary "casts" of allocation sites - literals, constructor invocations, |
| 309 // and closures. These should be handled by contextual inference. In most | 309 // and closures. These should be handled by contextual inference. In most |
| 310 // cases, inference will be sufficient, though in some it may unmask an actual | 310 // cases, inference will be sufficient, though in some it may unmask an actual |
| 311 // error: e.g., | 311 // error: e.g., |
| 312 // List<int> l = [1, 2, 3]; // Inference succeeds | 312 // List<int> l = [1, 2, 3]; // Inference succeeds |
| 313 // List<String> l = [1, 2, 3]; // Inference reveals static type error | 313 // List<String> l = [1, 2, 3]; // Inference reveals static type error |
| 314 // We're marking all as warnings for now. | 314 // We're marking all as warnings for now. |
| 315 // | 315 // |
| 316 | 316 |
| 317 // A "down cast" on a literal expression. | |
| 318 class InferableLiteral extends DownCast { | |
| 319 InferableLiteral(TypeRules rules, Literal expression, Cast cast) | |
| 320 : super._internal(rules, expression, cast); | |
| 321 | |
| 322 final Level level = Level.WARNING; | |
| 323 } | |
| 324 | |
| 325 // A "down cast" on a closure literal. | 317 // A "down cast" on a closure literal. |
| 326 class InferableClosure extends DownCast { | 318 class InferableClosure extends DownCast { |
| 327 InferableClosure(TypeRules rules, FunctionExpression expression, Cast cast) | 319 InferableClosure(TypeRules rules, FunctionExpression expression, Cast cast) |
| 328 : super._internal(rules, expression, cast); | 320 : super._internal(rules, expression, cast); |
| 329 | 321 |
| 330 final Level level = Level.WARNING; | 322 final Level level = Level.WARNING; |
| 331 } | 323 } |
| 332 | 324 |
| 333 // A "down cast" on a non-literal allocation site. | |
| 334 class InferableAllocation extends DownCast { | |
| 335 InferableAllocation( | |
| 336 TypeRules rules, InstanceCreationExpression expression, Cast cast) | |
| 337 : super._internal(rules, expression, cast); | |
| 338 | |
| 339 final Level level = Level.WARNING; | |
| 340 } | |
| 341 | |
| 342 // | 325 // |
| 343 // Implicit down casts. These are only injected by the compiler by flag. | 326 // Implicit down casts. These are only injected by the compiler by flag. |
| 344 // | 327 // |
| 345 | 328 |
| 346 // A down cast to a non-ground type. These behave differently from standard | 329 // A down cast to a non-ground type. These behave differently from standard |
| 347 // Dart and may be more likely to fail at runtime. | 330 // Dart and may be more likely to fail at runtime. |
| 348 class DownCastComposite extends DownCast { | 331 class DownCastComposite extends DownCast { |
| 349 DownCastComposite(TypeRules rules, Expression expression, Cast cast) | 332 DownCastComposite(TypeRules rules, Expression expression, Cast cast) |
| 350 : super._internal(rules, expression, cast); | 333 : super._internal(rules, expression, cast); |
| 351 | 334 |
| 352 final Level level = Level.WARNING; | 335 final Level level = Level.WARNING; |
| 353 } | 336 } |
| 354 | 337 |
| 355 // A down cast to a non-ground type. These behave differently from standard | 338 // A down cast to a non-ground type. These behave differently from standard |
| 356 // Dart and may be more likely to fail at runtime. | 339 // Dart and may be more likely to fail at runtime. |
| 357 class DownCastImplicit extends DownCast { | 340 class DownCastImplicit extends DownCast { |
| 358 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) | 341 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) |
| 359 : super._internal(rules, expression, cast); | 342 : super._internal(rules, expression, cast); |
| 360 | 343 |
| 361 final Level level = Level.WARNING; | 344 final Level level = Level.WARNING; |
| 362 } | 345 } |
| 363 | 346 |
| 347 // An inferred type for the wrapped expression, which may need to be |
| 348 // reified into the term |
| 349 abstract class InferredTypeBase extends Conversion { |
| 350 DartType _type; |
| 351 |
| 352 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) |
| 353 : super(rules, expression); |
| 354 |
| 355 DartType get type => _type; |
| 356 |
| 357 DartType _getConvertedType() => type; |
| 358 |
| 359 String get message => '$expression has inferred type $type'; |
| 360 |
| 361 Level get level => Level.INFO; |
| 362 |
| 363 accept(AstVisitor visitor) { |
| 364 if (visitor is ConversionVisitor) { |
| 365 return visitor.visitInferredTypeBase(this); |
| 366 } else { |
| 367 return expression.accept(visitor); |
| 368 } |
| 369 } |
| 370 } |
| 371 |
| 372 // Standard / unspecialized inferred type |
| 373 class InferredType extends InferredTypeBase { |
| 374 InferredType(TypeRules rules, Expression expression, DartType type) |
| 375 : super._internal(rules, expression, type); |
| 376 |
| 377 // Factory to create correct InferredType variant. |
| 378 static InferredTypeBase create( |
| 379 TypeRules rules, Expression expression, DartType type) { |
| 380 |
| 381 // Specialized inference: |
| 382 if (expression is Literal) { |
| 383 return new InferredTypeLiteral(rules, expression, type); |
| 384 } |
| 385 if (expression is InstanceCreationExpression) { |
| 386 return new InferredTypeAllocation(rules, expression, type); |
| 387 } |
| 388 return new InferredType(rules, expression, type); |
| 389 } |
| 390 } |
| 391 |
| 392 // An infered type for a literal expression. |
| 393 class InferredTypeLiteral extends InferredTypeBase { |
| 394 InferredTypeLiteral(TypeRules rules, Expression expression, DartType type) |
| 395 : super._internal(rules, expression, type); |
| 396 } |
| 397 |
| 398 // An inferred type for a non-literal allocation site. |
| 399 class InferredTypeAllocation extends InferredTypeBase { |
| 400 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) |
| 401 : super._internal(rules, expression, type); |
| 402 } |
| 403 |
| 364 // TODO(vsm): Remove these. | 404 // TODO(vsm): Remove these. |
| 365 | 405 |
| 366 // A wrapped closure coerces the underlying type to the desired type. | 406 // A wrapped closure coerces the underlying type to the desired type. |
| 367 class ClosureWrapBase extends Conversion { | 407 class ClosureWrapBase extends Conversion { |
| 368 FunctionType _wrappedType; | 408 FunctionType _wrappedType; |
| 369 Wrapper _wrapper; | 409 Wrapper _wrapper; |
| 370 | 410 |
| 371 ClosureWrapBase._internal( | 411 ClosureWrapBase._internal( |
| 372 TypeRules rules, Expression expression, this._wrapper, this._wrappedType) | 412 TypeRules rules, Expression expression, this._wrapper, this._wrappedType) |
| 373 : super(rules, expression) { | 413 : super(rules, expression) { |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 R visitRuntimeOperation(RuntimeOperation node) => visitNode(node); | 690 R visitRuntimeOperation(RuntimeOperation node) => visitNode(node); |
| 651 | 691 |
| 652 /// The catch-all for any kind of conversion | 692 /// The catch-all for any kind of conversion |
| 653 R visitConversion(Conversion node) => visitNode(node); | 693 R visitConversion(Conversion node) => visitNode(node); |
| 654 | 694 |
| 655 // Methods for conversion subtypes: | 695 // Methods for conversion subtypes: |
| 656 R visitDownCast(DownCast node) => visitConversion(node); | 696 R visitDownCast(DownCast node) => visitConversion(node); |
| 657 R visitClosureWrapBase(ClosureWrapBase node) => visitConversion(node); | 697 R visitClosureWrapBase(ClosureWrapBase node) => visitConversion(node); |
| 658 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node); | 698 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node); |
| 659 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); | 699 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); |
| 700 R visitInferredTypeBase(InferredTypeBase node) => visitConversion(node); |
| 660 } | 701 } |
| 661 | 702 |
| 662 /// Automatically infer list of types by scanning this library using mirrors. | 703 /// Automatically infer list of types by scanning this library using mirrors. |
| 663 final List<Type> infoTypes = () { | 704 final List<Type> infoTypes = () { |
| 664 var allTypes = new Set(); | 705 var allTypes = new Set(); |
| 665 var baseTypes = new Set(); | 706 var baseTypes = new Set(); |
| 666 var infoMirror = reflectClass(StaticInfo); | 707 var infoMirror = reflectClass(StaticInfo); |
| 667 var declarations = infoMirror.owner.declarations.values; | 708 var declarations = infoMirror.owner.declarations.values; |
| 668 for (var cls in declarations.where((d) => d is ClassMirror)) { | 709 for (var cls in declarations.where((d) => d is ClassMirror)) { |
| 669 if (cls.isSubtypeOf(infoMirror)) { | 710 if (cls.isSubtypeOf(infoMirror)) { |
| 670 allTypes.add(cls); | 711 allTypes.add(cls); |
| 671 baseTypes.add(cls.superclass); | 712 baseTypes.add(cls.superclass); |
| 672 } | 713 } |
| 673 } | 714 } |
| 674 allTypes.removeAll(baseTypes); | 715 allTypes.removeAll(baseTypes); |
| 675 return new List<Type>.from(allTypes.map((mirror) => mirror.reflectedType)) | 716 return new List<Type>.from(allTypes.map((mirror) => mirror.reflectedType)) |
| 676 ..sort((t1, t2) => '$t1'.compareTo('$t2')); | 717 ..sort((t1, t2) => '$t1'.compareTo('$t2')); |
| 677 }(); | 718 }(); |
| OLD | NEW |