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

Side by Side Diff: lib/src/info.dart

Issue 1038583004: Rationalize coercions (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 9 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 /// 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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 expression.accept(visitor); 183 expression.accept(visitor);
184 } 184 }
185 185
186 // Use same precedence as MethodInvocation. 186 // Use same precedence as MethodInvocation.
187 int get precedence => 15; 187 int get precedence => 15;
188 188
189 @override 189 @override
190 Iterable get childEntities => new ChildEntities()..add(expression); 190 Iterable get childEntities => new ChildEntities()..add(expression);
191 } 191 }
192 192
193 // A down cast from a subtype to a supertype. This must be checked at 193 // TODO(vsm): Merge with DCB
194 // runtime to recover soundness. 194 // Standard / unspecialized down cast.
195 abstract class DownCastBase extends Conversion { 195 abstract class DownCast extends Conversion {
196 Cast _cast; 196 Cast _cast;
197 197
198 DownCastBase._internal(TypeRules rules, Expression expression, this._cast) 198 DownCast._internal(TypeRules rules, Expression expression, this._cast)
199 : super(rules, expression) { 199 : super(rules, expression) {
200 assert(_cast.toType != baseType && 200 assert(_cast.toType != baseType &&
201 _cast.fromType == baseType && 201 _cast.fromType == baseType &&
202 (baseType.isDynamic || 202 (baseType.isDynamic ||
203 // Call methods make the following non-redundant 203 // Call methods make the following non-redundant
204 _cast.toType.isSubtypeOf(baseType) || 204 _cast.toType.isSubtypeOf(baseType) ||
205 baseType.isAssignableTo(_cast.toType))); 205 baseType.isAssignableTo(_cast.toType)));
206 } 206 }
207 207
208 Cast get cast => _cast; 208 Cast get cast => _cast;
209 209
210 DartType _getConvertedType() => _cast.toType; 210 DartType _getConvertedType() => _cast.toType;
211 211
212 String get message => '$expression ($baseType) will need runtime check ' 212 String get message => '$expression ($baseType) will need runtime check '
213 'to cast to type $convertedType'; 213 'to cast to type $convertedType';
214 214
215 // Differentiate between Function down cast and non-Function down cast? The
216 // former seems less likely to actually succeed.
217 Level get level =>
218 (_cast.toType is FunctionType) ? Level.WARNING : super.level;
219
220 accept(AstVisitor visitor) {
221 if (visitor is ConversionVisitor) {
222 return visitor.visitDownCastBase(this);
223 } else {
224 return expression.accept(visitor);
225 }
226 }
227 }
228
229 // Standard / unspecialized down cast.
230 class DownCast extends DownCastBase {
231 DownCast(TypeRules rules, Expression expression, Cast cast)
232 : super._internal(rules, expression, cast);
233
234 // Factory to create correct DownCast variant. 215 // Factory to create correct DownCast variant.
235 static DownCastBase create( 216 static DownCast create(TypeRules rules, Expression expression, Cast cast) {
236 TypeRules rules, Expression expression, Cast cast) {
237 final fromT = cast.fromType; 217 final fromT = cast.fromType;
238 final toT = cast.toType; 218 final toT = cast.toType;
239 219
240 // toT <:_R fromT => to <: fromT 220 // toT <:_R fromT => to <: fromT
241 // NB: classes with call methods are subtypes of function 221 // NB: classes with call methods are subtypes of function
242 // types, but the function type is not assignable to the class 222 // types, but the function type is not assignable to the class
243 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT)); 223 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT));
244 224
245 // Specialized casts: 225 // Inference "casts":
246 if (expression is Literal) { 226 if (expression is Literal) {
247 // fromT should be an exact type - this will almost certainly fail at 227 // fromT should be an exact type - this will almost certainly fail at
248 // runtime. 228 // runtime.
249 return new DownCastLiteral(rules, expression, cast); 229 return new InferableLiteral(rules, expression, cast);
Leaf 2015/03/25 21:06:28 We'll need to split out the inferable literals fro
230 }
231 if (expression is FunctionExpression) {
232 // fromT should be an exact type - this will almost certainly fail at
233 // runtime.
234 return new InferableClosure(rules, expression, cast);
250 } 235 }
251 if (expression is InstanceCreationExpression) { 236 if (expression is InstanceCreationExpression) {
252 // fromT should be an exact type - this will almost certainly fail at 237 // fromT should be an exact type - this will almost certainly fail at
253 // runtime. 238 // runtime.
254 return new DownCastExact(rules, expression, cast); 239 return new InferableAllocation(rules, expression, cast);
255 } 240 }
256 if (fromT.isSubtypeOf(toT) && !fromT.isDynamic) { 241
242 // Composite cast: these are more likely to fail.
243 if (!rules.isGroundType(toT)) {
257 // This cast is (probably) due to our different treatment of dynamic. 244 // This cast is (probably) due to our different treatment of dynamic.
258 // It may be more likely to fail at runtime. 245 // It may be more likely to fail at runtime.
259 return new DownCastDynamic(rules, expression, cast); 246 return new DownCastComposite(rules, expression, cast);
260 } 247 }
261 return new DownCast(rules, expression, cast); 248
249 // Dynamic cast
250 if (fromT.isDynamic) {
251 return new DynamicCast(rules, expression, cast);
252 }
253
254 // Assignment cast
255 var parent = expression.parent;
256 if (parent is VariableDeclaration && (parent.initializer == expression)) {
257 return new AssignmentCast(rules, expression, cast);
258 }
259
260 // Other casts
261 return new DownCastImplicit(rules, expression, cast);
262 } 262 }
263
264 accept(AstVisitor visitor) {
265 if (visitor is ConversionVisitor) {
266 return visitor.visitDownCast(this);
267 } else {
268 return expression.accept(visitor);
269 }
270 }
271 }
272
273 //
274 // Standard down casts. These casts are implicitly injected by the compiler.
275 //
276
277 // A down cast from dynamic to T.
278 class DynamicCast extends DownCast {
279 DynamicCast(TypeRules rules, Expression expression, Cast cast)
280 : super._internal(rules, expression, cast);
281
282 final Level level = Level.INFO;
283 }
284
285 // A down cast due to a variable declaration to a ground type. E.g.,
286 // T x = expr;
287 // where T is ground. We exclude non-ground types as these behave differently
288 // compared to standard Dart.
289 class AssignmentCast extends DownCast {
290 AssignmentCast(TypeRules rules, Expression expression, Cast cast)
291 : super._internal(rules, expression, cast);
292
293 final Level level = Level.INFO;
294 }
295
296 //
297 // Temporary "casts" of allocation sites - literals, constructor invocations,
298 // and closures. These should be handled by contextual inference. In most
299 // cases, inference will be sufficient, though in some it may unmask an actual
300 // error: e.g.,
301 // List<int> l = [1, 2, 3]; // Inference succeeds
302 // List<String> l = [1, 2, 3]; // Inference reveals static type error
303 // We're marking all as warnings for now.
304 //
305
306 // A "down cast" on a literal expression.
307 class InferableLiteral extends DownCast {
308 InferableLiteral(TypeRules rules, Literal expression, Cast cast)
309 : super._internal(rules, expression, cast);
310
311 final Level level = Level.WARNING;
312 }
313
314 // A "down cast" on a closure literal.
315 class InferableClosure extends DownCast {
316 InferableClosure(TypeRules rules, FunctionExpression expression, Cast cast)
317 : super._internal(rules, expression, cast);
318
319 final Level level = Level.WARNING;
320 }
321
322 // A "down cast" on a non-literal allocation site.
323 class InferableAllocation extends DownCast {
324 InferableAllocation(
325 TypeRules rules, InstanceCreationExpression expression, Cast cast)
326 : super._internal(rules, expression, cast);
327
328 final Level level = Level.WARNING;
263 } 329 }
264 330
265 // A down cast that would be "unnecessary" with standard Dart rules. 331 // A down cast that would be "unnecessary" with standard Dart rules.
266 // E.g., the fromType <: toType in standard Dart but not in our restricted 332 // E.g., the fromType <: toType in standard Dart but not in our restricted
267 // rules. These occur due to our stricter rules on dynamic type parameters in 333 // rules. These occur due to our stricter rules on dynamic type parameters in
268 // generics. 334 // generics.
Leaf 2015/03/25 21:06:28 I think this comment is orphaned?
269 class DownCastDynamic extends DownCastBase { 335
270 DownCastDynamic(TypeRules rules, Expression expression, Cast cast) 336 //
337 // Implicit down casts. These are only injected by the compiler by flag.
338 //
339
340 // A down cast to a non-ground type. These behave differently from standard
341 // Dart and may be more likely to fail at runtime.
342 class DownCastComposite extends DownCast {
343 DownCastComposite(TypeRules rules, Expression expression, Cast cast)
271 : super._internal(rules, expression, cast); 344 : super._internal(rules, expression, cast);
272 345
273 final Level level = Level.WARNING; 346 final Level level = Level.WARNING;
274 } 347 }
275 348
276 // A down cast on a literal expression. This should never succeed. 349 // A down cast to a non-ground type. These behave differently from standard
277 // TODO(vsm): Mark as severe / error? 350 // Dart and may be more likely to fail at runtime.
278 class DownCastLiteral extends DownCastBase { 351 class DownCastImplicit extends DownCast {
279 DownCastLiteral(TypeRules rules, Expression expression, Cast cast) 352 DownCastImplicit(TypeRules rules, Expression expression, Cast cast)
280 : super._internal(rules, expression, cast); 353 : super._internal(rules, expression, cast);
281 354
282 final Level level = Level.WARNING; 355 final Level level = Level.WARNING;
283 } 356 }
284 357
285 // A down cast on a non-literal allocation site. This should never succeed. 358 // TODO(vsm): Remove these.
286 // TODO(vsm): Mark as severe / error?
287 class DownCastExact extends DownCastBase {
288 DownCastExact(TypeRules rules, Expression expression, Cast cast)
289 : super._internal(rules, expression, cast);
290
291 final Level level = Level.WARNING;
292 }
293 359
294 // A wrapped closure coerces the underlying type to the desired type. 360 // A wrapped closure coerces the underlying type to the desired type.
295 class ClosureWrapBase extends Conversion { 361 class ClosureWrapBase extends Conversion {
296 FunctionType _wrappedType; 362 FunctionType _wrappedType;
297 Wrapper _wrapper; 363 Wrapper _wrapper;
298 364
299 ClosureWrapBase._internal( 365 ClosureWrapBase._internal(
300 TypeRules rules, Expression expression, this._wrapper, this._wrappedType) 366 TypeRules rules, Expression expression, this._wrapper, this._wrappedType)
301 : super(rules, expression) { 367 : super(rules, expression) {
302 assert(baseType is FunctionType); 368 assert(baseType is FunctionType);
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 /// GeneralizingAstVisitor<R>. 640 /// GeneralizingAstVisitor<R>.
575 R visitNode(AstNode node); 641 R visitNode(AstNode node);
576 642
577 // Handle runtime operations 643 // Handle runtime operations
578 R visitRuntimeOperation(RuntimeOperation node) => visitNode(node); 644 R visitRuntimeOperation(RuntimeOperation node) => visitNode(node);
579 645
580 /// The catch-all for any kind of conversion 646 /// The catch-all for any kind of conversion
581 R visitConversion(Conversion node) => visitNode(node); 647 R visitConversion(Conversion node) => visitNode(node);
582 648
583 // Methods for conversion subtypes: 649 // Methods for conversion subtypes:
584 R visitDownCastBase(DownCastBase node) => visitConversion(node); 650 R visitDownCast(DownCast node) => visitConversion(node);
585 R visitDownCast(DownCast node) => visitDownCastBase(node);
586 R visitDownCastDynamic(DownCastDynamic node) => visitDownCastBase(node);
587 R visitDownCastExact(DownCastExact node) => visitDownCastBase(node);
588 R visitClosureWrapBase(ClosureWrapBase node) => visitConversion(node); 651 R visitClosureWrapBase(ClosureWrapBase node) => visitConversion(node);
589 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node); 652 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node);
590 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); 653 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node);
591 } 654 }
592 655
593 /// Automatically infer list of types by scanning this library using mirrors. 656 /// Automatically infer list of types by scanning this library using mirrors.
594 final List<Type> infoTypes = () { 657 final List<Type> infoTypes = () {
595 var allTypes = new Set(); 658 var allTypes = new Set();
596 var baseTypes = new Set(); 659 var baseTypes = new Set();
597 var infoMirror = reflectClass(StaticInfo); 660 var infoMirror = reflectClass(StaticInfo);
598 var declarations = infoMirror.owner.declarations.values; 661 var declarations = infoMirror.owner.declarations.values;
599 for (var cls in declarations.where((d) => d is ClassMirror)) { 662 for (var cls in declarations.where((d) => d is ClassMirror)) {
600 if (cls.isSubtypeOf(infoMirror)) { 663 if (cls.isSubtypeOf(infoMirror)) {
601 allTypes.add(cls); 664 allTypes.add(cls);
602 baseTypes.add(cls.superclass); 665 baseTypes.add(cls.superclass);
603 } 666 }
604 } 667 }
605 allTypes.removeAll(baseTypes); 668 allTypes.removeAll(baseTypes);
606 return new List<Type>.from(allTypes.map((mirror) => mirror.reflectedType)) 669 return new List<Type>.from(allTypes.map((mirror) => mirror.reflectedType))
607 ..sort((t1, t2) => '$t1'.compareTo('$t2')); 670 ..sort((t1, t2) => '$t1'.compareTo('$t2'));
608 }(); 671 }();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698