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

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: Rebase 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
« no previous file with comments | « lib/src/codegen/reify_coercions.dart ('k') | lib/src/options.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Base class for all casts from base type to sub type.
194 // runtime to recover soundness. 194 abstract class DownCast extends Conversion {
195 abstract class DownCastBase extends Conversion {
196 Cast _cast; 195 Cast _cast;
197 196
198 DownCastBase._internal(TypeRules rules, Expression expression, this._cast) 197 DownCast._internal(TypeRules rules, Expression expression, this._cast)
199 : super(rules, expression) { 198 : super(rules, expression) {
200 assert(_cast.toType != baseType && 199 assert(_cast.toType != baseType &&
201 _cast.fromType == baseType && 200 _cast.fromType == baseType &&
202 (baseType.isDynamic || 201 (baseType.isDynamic ||
203 // Call methods make the following non-redundant 202 // Call methods make the following non-redundant
204 _cast.toType.isSubtypeOf(baseType) || 203 _cast.toType.isSubtypeOf(baseType) ||
205 baseType.isAssignableTo(_cast.toType))); 204 baseType.isAssignableTo(_cast.toType)));
206 } 205 }
207 206
208 Cast get cast => _cast; 207 Cast get cast => _cast;
209 208
210 DartType _getConvertedType() => _cast.toType; 209 DartType _getConvertedType() => _cast.toType;
211 210
212 String get message => '$expression ($baseType) will need runtime check ' 211 String get message => '$expression ($baseType) will need runtime check '
213 'to cast to type $convertedType'; 212 'to cast to type $convertedType';
214 213
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. 214 // Factory to create correct DownCast variant.
235 static DownCastBase create( 215 static StaticInfo create(TypeRules rules, Expression expression, Cast cast) {
236 TypeRules rules, Expression expression, Cast cast) {
237 final fromT = cast.fromType; 216 final fromT = cast.fromType;
238 final toT = cast.toType; 217 final toT = cast.toType;
239 218
240 // toT <:_R fromT => to <: fromT 219 // toT <:_R fromT => to <: fromT
241 // NB: classes with call methods are subtypes of function 220 // NB: classes with call methods are subtypes of function
242 // types, but the function type is not assignable to the class 221 // types, but the function type is not assignable to the class
243 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT)); 222 assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT));
244 223
245 // Specialized casts: 224 // Handle null call specially.
225 if (expression is NullLiteral) {
226 if (rules.isNonNullableType(toT)) {
227 return new StaticTypeError(rules, expression, toT);
228 } else {
229 // We should only get here if some coercion is required.
230 assert(rules.maybeNonNullableType(toT));
231 // TODO(vsm): Create a NullCast for this once we revisit nonnullability.
232 return new DownCastImplicit(rules, expression, cast);
233 }
234 }
235
236 // Inference "casts":
246 if (expression is Literal) { 237 if (expression is Literal) {
247 // 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
248 // runtime. 239 // runtime.
249 return new DownCastLiteral(rules, expression, cast); 240 return new InferableLiteral(rules, expression, cast);
241 }
242 if (expression is FunctionExpression) {
243 // fromT should be an exact type - this will almost certainly fail at
244 // runtime.
245 return new InferableClosure(rules, expression, cast);
250 } 246 }
251 if (expression is InstanceCreationExpression) { 247 if (expression is InstanceCreationExpression) {
252 // 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
253 // runtime. 249 // runtime.
254 return new DownCastExact(rules, expression, cast); 250 return new InferableAllocation(rules, expression, cast);
255 } 251 }
256 if (fromT.isSubtypeOf(toT) && !fromT.isDynamic) { 252
253 // Composite cast: these are more likely to fail.
254 if (!rules.isGroundType(toT)) {
257 // This cast is (probably) due to our different treatment of dynamic. 255 // This cast is (probably) due to our different treatment of dynamic.
258 // It may be more likely to fail at runtime. 256 // It may be more likely to fail at runtime.
259 return new DownCastDynamic(rules, expression, cast); 257 return new DownCastComposite(rules, expression, cast);
260 } 258 }
261 return new DownCast(rules, expression, cast); 259
260 // Dynamic cast
261 if (fromT.isDynamic) {
262 return new DynamicCast(rules, expression, cast);
263 }
264
265 // Assignment cast
266 var parent = expression.parent;
267 if (parent is VariableDeclaration && (parent.initializer == expression)) {
268 return new AssignmentCast(rules, expression, cast);
269 }
270
271 // Other casts
272 return new DownCastImplicit(rules, expression, cast);
273 }
274
275 accept(AstVisitor visitor) {
276 if (visitor is ConversionVisitor) {
277 return visitor.visitDownCast(this);
278 } else {
279 return expression.accept(visitor);
280 }
262 } 281 }
263 } 282 }
264 283
265 // A down cast that would be "unnecessary" with standard Dart rules. 284 //
266 // E.g., the fromType <: toType in standard Dart but not in our restricted 285 // Standard down casts. These casts are implicitly injected by the compiler.
267 // rules. These occur due to our stricter rules on dynamic type parameters in 286 //
268 // generics. 287
269 class DownCastDynamic extends DownCastBase { 288 // A down cast from dynamic to T.
270 DownCastDynamic(TypeRules rules, Expression expression, Cast cast) 289 class DynamicCast extends DownCast {
290 DynamicCast(TypeRules rules, Expression expression, Cast cast)
291 : super._internal(rules, expression, cast);
292
293 final Level level = Level.INFO;
294 }
295
296 // A down cast due to a variable declaration to a ground type. E.g.,
297 // T x = expr;
298 // where T is ground. We exclude non-ground types as these behave differently
299 // compared to standard Dart.
300 class AssignmentCast extends DownCast {
301 AssignmentCast(TypeRules rules, Expression expression, Cast cast)
302 : super._internal(rules, expression, cast);
303
304 final Level level = Level.INFO;
305 }
306
307 //
308 // Temporary "casts" of allocation sites - literals, constructor invocations,
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
311 // error: e.g.,
312 // List<int> l = [1, 2, 3]; // Inference succeeds
313 // List<String> l = [1, 2, 3]; // Inference reveals static type error
314 // We're marking all as warnings for now.
315 //
316
317 // A "down cast" on a literal expression.
318 class InferableLiteral extends DownCast {
319 InferableLiteral(TypeRules rules, Literal expression, Cast cast)
271 : super._internal(rules, expression, cast); 320 : super._internal(rules, expression, cast);
272 321
273 final Level level = Level.WARNING; 322 final Level level = Level.WARNING;
274 } 323 }
275 324
276 // A down cast on a literal expression. This should never succeed. 325 // A "down cast" on a closure literal.
277 // TODO(vsm): Mark as severe / error? 326 class InferableClosure extends DownCast {
278 class DownCastLiteral extends DownCastBase { 327 InferableClosure(TypeRules rules, FunctionExpression expression, Cast cast)
279 DownCastLiteral(TypeRules rules, Expression expression, Cast cast)
280 : super._internal(rules, expression, cast); 328 : super._internal(rules, expression, cast);
281 329
282 final Level level = Level.WARNING; 330 final Level level = Level.WARNING;
283 } 331 }
284 332
285 // A down cast on a non-literal allocation site. This should never succeed. 333 // A "down cast" on a non-literal allocation site.
286 // TODO(vsm): Mark as severe / error? 334 class InferableAllocation extends DownCast {
287 class DownCastExact extends DownCastBase { 335 InferableAllocation(
288 DownCastExact(TypeRules rules, Expression expression, Cast cast) 336 TypeRules rules, InstanceCreationExpression expression, Cast cast)
289 : super._internal(rules, expression, cast); 337 : super._internal(rules, expression, cast);
290 338
291 final Level level = Level.WARNING; 339 final Level level = Level.WARNING;
292 } 340 }
293 341
342 //
343 // Implicit down casts. These are only injected by the compiler by flag.
344 //
345
346 // A down cast to a non-ground type. These behave differently from standard
347 // Dart and may be more likely to fail at runtime.
348 class DownCastComposite extends DownCast {
349 DownCastComposite(TypeRules rules, Expression expression, Cast cast)
350 : super._internal(rules, expression, cast);
351
352 final Level level = Level.WARNING;
353 }
354
355 // A down cast to a non-ground type. These behave differently from standard
356 // Dart and may be more likely to fail at runtime.
357 class DownCastImplicit extends DownCast {
358 DownCastImplicit(TypeRules rules, Expression expression, Cast cast)
359 : super._internal(rules, expression, cast);
360
361 final Level level = Level.WARNING;
362 }
363
364 // TODO(vsm): Remove these.
365
294 // A wrapped closure coerces the underlying type to the desired type. 366 // A wrapped closure coerces the underlying type to the desired type.
295 class ClosureWrapBase extends Conversion { 367 class ClosureWrapBase extends Conversion {
296 FunctionType _wrappedType; 368 FunctionType _wrappedType;
297 Wrapper _wrapper; 369 Wrapper _wrapper;
298 370
299 ClosureWrapBase._internal( 371 ClosureWrapBase._internal(
300 TypeRules rules, Expression expression, this._wrapper, this._wrappedType) 372 TypeRules rules, Expression expression, this._wrapper, this._wrappedType)
301 : super(rules, expression) { 373 : super(rules, expression) {
302 assert(baseType is FunctionType); 374 assert(baseType is FunctionType);
303 assert(!rules.isSubTypeOf(baseType, _wrappedType)); 375 assert(!rules.isSubTypeOf(baseType, _wrappedType));
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 /// GeneralizingAstVisitor<R>. 646 /// GeneralizingAstVisitor<R>.
575 R visitNode(AstNode node); 647 R visitNode(AstNode node);
576 648
577 // Handle runtime operations 649 // Handle runtime operations
578 R visitRuntimeOperation(RuntimeOperation node) => visitNode(node); 650 R visitRuntimeOperation(RuntimeOperation node) => visitNode(node);
579 651
580 /// The catch-all for any kind of conversion 652 /// The catch-all for any kind of conversion
581 R visitConversion(Conversion node) => visitNode(node); 653 R visitConversion(Conversion node) => visitNode(node);
582 654
583 // Methods for conversion subtypes: 655 // Methods for conversion subtypes:
584 R visitDownCastBase(DownCastBase node) => visitConversion(node); 656 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); 657 R visitClosureWrapBase(ClosureWrapBase node) => visitConversion(node);
589 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node); 658 R visitClosureWrap(ClosureWrap node) => visitClosureWrapBase(node);
590 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); 659 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node);
591 } 660 }
592 661
593 /// Automatically infer list of types by scanning this library using mirrors. 662 /// Automatically infer list of types by scanning this library using mirrors.
594 final List<Type> infoTypes = () { 663 final List<Type> infoTypes = () {
595 var allTypes = new Set(); 664 var allTypes = new Set();
596 var baseTypes = new Set(); 665 var baseTypes = new Set();
597 var infoMirror = reflectClass(StaticInfo); 666 var infoMirror = reflectClass(StaticInfo);
598 var declarations = infoMirror.owner.declarations.values; 667 var declarations = infoMirror.owner.declarations.values;
599 for (var cls in declarations.where((d) => d is ClassMirror)) { 668 for (var cls in declarations.where((d) => d is ClassMirror)) {
600 if (cls.isSubtypeOf(infoMirror)) { 669 if (cls.isSubtypeOf(infoMirror)) {
601 allTypes.add(cls); 670 allTypes.add(cls);
602 baseTypes.add(cls.superclass); 671 baseTypes.add(cls.superclass);
603 } 672 }
604 } 673 }
605 allTypes.removeAll(baseTypes); 674 allTypes.removeAll(baseTypes);
606 return new List<Type>.from(allTypes.map((mirror) => mirror.reflectedType)) 675 return new List<Type>.from(allTypes.map((mirror) => mirror.reflectedType))
607 ..sort((t1, t2) => '$t1'.compareTo('$t2')); 676 ..sort((t1, t2) => '$t1'.compareTo('$t2'));
608 }(); 677 }();
OLDNEW
« no previous file with comments | « lib/src/codegen/reify_coercions.dart ('k') | lib/src/options.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698