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

Side by Side Diff: pkg/compiler/lib/src/js_backend/runtime_types.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 part of js_backend; 5 part of js_backend;
6 6
7 /// For each class, stores the possible class subtype tests that could succeed. 7 /// For each class, stores the possible class subtype tests that could succeed.
8 abstract class TypeChecks { 8 abstract class TypeChecks {
9 /// Get the set of checks required for class [element]. 9 /// Get the set of checks required for class [element].
10 Iterable<TypeCheck> operator[](ClassElement element); 10 Iterable<TypeCheck> operator [](ClassElement element);
11
11 /// Get the iterable for all classes that need type checks. 12 /// Get the iterable for all classes that need type checks.
12 Iterable<ClassElement> get classes; 13 Iterable<ClassElement> get classes;
13 } 14 }
14 15
15 typedef jsAst.Expression OnVariableCallback(TypeVariableType variable); 16 typedef jsAst.Expression OnVariableCallback(TypeVariableType variable);
16 typedef bool ShouldEncodeTypedefCallback(TypedefType variable); 17 typedef bool ShouldEncodeTypedefCallback(TypedefType variable);
17 18
18 // TODO(johnniwinther): Rename to something like [RuntimeTypeUsageCollector] 19 // TODO(johnniwinther): Rename to something like [RuntimeTypeUsageCollector]
19 // we semantics is more clear. 20 // we semantics is more clear.
20 abstract class RuntimeTypes { 21 abstract class RuntimeTypes {
21 TypeChecks get requiredChecks; 22 TypeChecks get requiredChecks;
22 Iterable<ClassElement> get classesNeedingRti; 23 Iterable<ClassElement> get classesNeedingRti;
23 Iterable<Element> get methodsNeedingRti; 24 Iterable<Element> get methodsNeedingRti;
24 25
25 /// The set of classes that use one of their type variables as expressions 26 /// The set of classes that use one of their type variables as expressions
26 /// to get the runtime type. 27 /// to get the runtime type.
27 Iterable<ClassElement> get classesUsingTypeVariableExpression; 28 Iterable<ClassElement> get classesUsingTypeVariableExpression;
28 29
29 void registerClassUsingTypeVariableExpression(ClassElement cls); 30 void registerClassUsingTypeVariableExpression(ClassElement cls);
30 void registerRtiDependency(Element element, Element dependency); 31 void registerRtiDependency(Element element, Element dependency);
31 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, 32 void registerTypeVariableBoundsSubtypeCheck(
32 DartType bound); 33 DartType typeArgument, DartType bound);
33 34
34 Set<ClassElement> getClassesUsedInSubstitutions(JavaScriptBackend backend, 35 Set<ClassElement> getClassesUsedInSubstitutions(
35 TypeChecks checks); 36 JavaScriptBackend backend, TypeChecks checks);
36 void computeClassesNeedingRti(); 37 void computeClassesNeedingRti();
37 38
38 /// Compute the required type checkes and substitutions for the given 39 /// Compute the required type checkes and substitutions for the given
39 /// instantitated and checked classes. 40 /// instantitated and checked classes.
40 TypeChecks computeChecks(Set<ClassElement> instantiated, 41 TypeChecks computeChecks(
41 Set<ClassElement> checked); 42 Set<ClassElement> instantiated, Set<ClassElement> checked);
42 43
43 /// Compute type arguments of classes that use one of their type variables in 44 /// Compute type arguments of classes that use one of their type variables in
44 /// is-checks and add the is-checks that they imply. 45 /// is-checks and add the is-checks that they imply.
45 /// 46 ///
46 /// This function must be called after all is-checks have been registered. 47 /// This function must be called after all is-checks have been registered.
47 void addImplicitChecks(Universe universe, 48 void addImplicitChecks(
48 Iterable<ClassElement> classesUsingChecks); 49 Universe universe, Iterable<ClassElement> classesUsingChecks);
49 50
50 /// Return all classes that are referenced in the type of the function, i.e., 51 /// Return all classes that are referenced in the type of the function, i.e.,
51 /// in the return type or the argument types. 52 /// in the return type or the argument types.
52 Set<ClassElement> getReferencedClasses(FunctionType type); 53 Set<ClassElement> getReferencedClasses(FunctionType type);
53 54
54 /// Return all classes that are uses a type arguments. 55 /// Return all classes that are uses a type arguments.
55 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend); 56 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend);
56 57
57 bool isTrivialSubstitution(ClassElement cls, ClassElement check); 58 bool isTrivialSubstitution(ClassElement cls, ClassElement check);
58 59
59 Substitution getSubstitution(ClassElement cls, ClassElement other); 60 Substitution getSubstitution(ClassElement cls, ClassElement other);
60 61
61 static bool hasTypeArguments(DartType type) { 62 static bool hasTypeArguments(DartType type) {
62 if (type is InterfaceType) { 63 if (type is InterfaceType) {
63 InterfaceType interfaceType = type; 64 InterfaceType interfaceType = type;
64 return !interfaceType.treatAsRaw; 65 return !interfaceType.treatAsRaw;
65 } 66 }
66 return false; 67 return false;
67 } 68 }
68 } 69 }
69 70
70 abstract class RuntimeTypesEncoder { 71 abstract class RuntimeTypesEncoder {
71 bool isSimpleFunctionType(FunctionType type); 72 bool isSimpleFunctionType(FunctionType type);
72 73
73 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_); 74 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_);
74 75
75 jsAst.Expression getSubstitutionRepresentation( 76 jsAst.Expression getSubstitutionRepresentation(
76 List<DartType> types, 77 List<DartType> types, OnVariableCallback onVariable);
77 OnVariableCallback onVariable);
78 jsAst.Expression getSubstitutionCode(Substitution substitution); 78 jsAst.Expression getSubstitutionCode(Substitution substitution);
79 jsAst.Expression getSubstitutionCodeForVariable( 79 jsAst.Expression getSubstitutionCodeForVariable(
80 Substitution substitution, int index); 80 Substitution substitution, int index);
81 81
82 /// Returns the JavaScript template to determine at runtime if a type object 82 /// Returns the JavaScript template to determine at runtime if a type object
83 /// is a function type. 83 /// is a function type.
84 jsAst.Template get templateForIsFunctionType; 84 jsAst.Template get templateForIsFunctionType;
85 85
86 /// Returns the JavaScript template that creates at runtime a new function 86 /// Returns the JavaScript template that creates at runtime a new function
87 /// type object. 87 /// type object.
88 jsAst.Template get templateForCreateFunctionType; 88 jsAst.Template get templateForCreateFunctionType;
89 jsAst.Name get getFunctionThatReturnsNullName; 89 jsAst.Name get getFunctionThatReturnsNullName;
90 90
91 jsAst.Expression getTypeRepresentation( 91 jsAst.Expression getTypeRepresentation(
92 DartType type, 92 DartType type, OnVariableCallback onVariable,
93 OnVariableCallback onVariable, 93 [ShouldEncodeTypedefCallback shouldEncodeTypedef]);
94 [ShouldEncodeTypedefCallback shouldEncodeTypedef]);
95 /** 94 /**
96 * Returns a [jsAst.Expression] representing the given [type]. Type 95 * Returns a [jsAst.Expression] representing the given [type]. Type
97 * variables are replaced by placeholders in the ast. 96 * variables are replaced by placeholders in the ast.
98 * 97 *
99 * [firstPlaceholderIndex] is the index to use for the first placeholder. 98 * [firstPlaceholderIndex] is the index to use for the first placeholder.
100 * This is useful if the returned [jsAst.Expression] is only part of a 99 * This is useful if the returned [jsAst.Expression] is only part of a
101 * larger template. By default, indexing starts with 0. 100 * larger template. By default, indexing starts with 0.
102 */ 101 */
103 jsAst.Expression getTypeRepresentationWithPlaceholders(DartType type, 102 jsAst.Expression getTypeRepresentationWithPlaceholders(
104 OnVariableCallback onVariable, {int firstPlaceholderIndex : 0}); 103 DartType type, OnVariableCallback onVariable,
104 {int firstPlaceholderIndex: 0});
105 105
106 String getTypeRepresentationForTypeConstant(DartType type); 106 String getTypeRepresentationForTypeConstant(DartType type);
107 } 107 }
108 108
109 class _RuntimeTypes implements RuntimeTypes { 109 class _RuntimeTypes implements RuntimeTypes {
110 final Compiler compiler; 110 final Compiler compiler;
111 111
112 final Map<ClassElement, Set<ClassElement>> rtiDependencies; 112 final Map<ClassElement, Set<ClassElement>> rtiDependencies;
113 113
114 @override 114 @override
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 @override 150 @override
151 void registerRtiDependency(Element element, Element dependency) { 151 void registerRtiDependency(Element element, Element dependency) {
152 // We're not dealing with typedef for now. 152 // We're not dealing with typedef for now.
153 if (!element.isClass || !dependency.isClass) return; 153 if (!element.isClass || !dependency.isClass) return;
154 Set<ClassElement> classes = 154 Set<ClassElement> classes =
155 rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>()); 155 rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>());
156 classes.add(dependency); 156 classes.add(dependency);
157 } 157 }
158 158
159 @override 159 @override
160 void registerTypeVariableBoundsSubtypeCheck(DartType typeArgument, 160 void registerTypeVariableBoundsSubtypeCheck(
161 DartType bound) { 161 DartType typeArgument, DartType bound) {
162 checkedTypeArguments.add(typeArgument); 162 checkedTypeArguments.add(typeArgument);
163 checkedBounds.add(bound); 163 checkedBounds.add(bound);
164 } 164 }
165 165
166 // TODO(21969): remove this and analyze instantiated types and factory calls 166 // TODO(21969): remove this and analyze instantiated types and factory calls
167 // instead to find out which types are instantiated, if finitely many, or if 167 // instead to find out which types are instantiated, if finitely many, or if
168 // we have to use the more imprecise generic algorithm. 168 // we have to use the more imprecise generic algorithm.
169 bool get cannotDetermineInstantiatedTypesPrecisely => true; 169 bool get cannotDetermineInstantiatedTypesPrecisely => true;
170 170
171 /** 171 /**
172 * Compute type arguments of classes that use one of their type variables in 172 * Compute type arguments of classes that use one of their type variables in
173 * is-checks and add the is-checks that they imply. 173 * is-checks and add the is-checks that they imply.
174 * 174 *
175 * This function must be called after all is-checks have been registered. 175 * This function must be called after all is-checks have been registered.
176 * 176 *
177 * TODO(karlklose): move these computations into a function producing an 177 * TODO(karlklose): move these computations into a function producing an
178 * immutable datastructure. 178 * immutable datastructure.
179 */ 179 */
180 @override 180 @override
181 void addImplicitChecks(Universe universe, 181 void addImplicitChecks(
182 Iterable<ClassElement> classesUsingChecks) { 182 Universe universe, Iterable<ClassElement> classesUsingChecks) {
183 // If there are no classes that use their variables in checks, there is 183 // If there are no classes that use their variables in checks, there is
184 // nothing to do. 184 // nothing to do.
185 if (classesUsingChecks.isEmpty) return; 185 if (classesUsingChecks.isEmpty) return;
186 Set<DartType> instantiatedTypes = universe.instantiatedTypes; 186 Set<DartType> instantiatedTypes = universe.instantiatedTypes;
187 if (cannotDetermineInstantiatedTypesPrecisely) { 187 if (cannotDetermineInstantiatedTypesPrecisely) {
188 for (DartType type in instantiatedTypes) { 188 for (DartType type in instantiatedTypes) {
189 if (type.kind != TypeKind.INTERFACE) continue; 189 if (type.kind != TypeKind.INTERFACE) continue;
190 InterfaceType interface = type; 190 InterfaceType interface = type;
191 do { 191 do {
192 for (DartType argument in interface.typeArguments) { 192 for (DartType argument in interface.typeArguments) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 if (type.isFunctionType) { 286 if (type.isFunctionType) {
287 void analyzeMethod(TypedElement method) { 287 void analyzeMethod(TypedElement method) {
288 DartType memberType = method.type; 288 DartType memberType = method.type;
289 ClassElement contextClass = Types.getClassContext(memberType); 289 ClassElement contextClass = Types.getClassContext(memberType);
290 if (contextClass != null && 290 if (contextClass != null &&
291 compiler.types.isPotentialSubtype(memberType, type)) { 291 compiler.types.isPotentialSubtype(memberType, type)) {
292 potentiallyAddForRti(contextClass); 292 potentiallyAddForRti(contextClass);
293 methodsNeedingRti.add(method); 293 methodsNeedingRti.add(method);
294 } 294 }
295 } 295 }
296 compiler.resolverWorld.closuresWithFreeTypeVariables.forEach( 296 compiler.resolverWorld.closuresWithFreeTypeVariables
297 analyzeMethod); 297 .forEach(analyzeMethod);
298 compiler.resolverWorld.callMethodsWithFreeTypeVariables.forEach( 298 compiler.resolverWorld.callMethodsWithFreeTypeVariables
299 analyzeMethod); 299 .forEach(analyzeMethod);
300 } 300 }
301 } 301 }
302 }); 302 });
303 if (compiler.options.enableTypeAssertions) { 303 if (compiler.options.enableTypeAssertions) {
304 void analyzeMethod(TypedElement method) { 304 void analyzeMethod(TypedElement method) {
305 DartType memberType = method.type; 305 DartType memberType = method.type;
306 ClassElement contextClass = Types.getClassContext(memberType); 306 ClassElement contextClass = Types.getClassContext(memberType);
307 if (contextClass != null) { 307 if (contextClass != null) {
308 potentiallyAddForRti(contextClass); 308 potentiallyAddForRti(contextClass);
309 methodsNeedingRti.add(method); 309 methodsNeedingRti.add(method);
310 } 310 }
311 } 311 }
312 compiler.resolverWorld.closuresWithFreeTypeVariables.forEach( 312 compiler.resolverWorld.closuresWithFreeTypeVariables
313 analyzeMethod); 313 .forEach(analyzeMethod);
314 compiler.resolverWorld.callMethodsWithFreeTypeVariables.forEach( 314 compiler.resolverWorld.callMethodsWithFreeTypeVariables
315 analyzeMethod); 315 .forEach(analyzeMethod);
316 } 316 }
317 // Add the classes that need RTI because they use a type variable as 317 // Add the classes that need RTI because they use a type variable as
318 // expression. 318 // expression.
319 classesUsingTypeVariableExpression.forEach(potentiallyAddForRti); 319 classesUsingTypeVariableExpression.forEach(potentiallyAddForRti);
320 } 320 }
321 321
322 @override 322 @override
323 TypeChecks get requiredChecks { 323 TypeChecks get requiredChecks {
324 if (cachedRequiredChecks == null) { 324 if (cachedRequiredChecks == null) {
325 computeRequiredChecks(); 325 computeRequiredChecks();
326 } 326 }
327 assert(cachedRequiredChecks != null); 327 assert(cachedRequiredChecks != null);
328 return cachedRequiredChecks; 328 return cachedRequiredChecks;
329 } 329 }
330 330
331 @override 331 @override
332 TypeChecks computeChecks(Set<ClassElement> instantiated, 332 TypeChecks computeChecks(
333 Set<ClassElement> checked) { 333 Set<ClassElement> instantiated, Set<ClassElement> checked) {
334 // Run through the combination of instantiated and checked 334 // Run through the combination of instantiated and checked
335 // arguments and record all combination where the element of a checked 335 // arguments and record all combination where the element of a checked
336 // argument is a superclass of the element of an instantiated type. 336 // argument is a superclass of the element of an instantiated type.
337 TypeCheckMapping result = new TypeCheckMapping(); 337 TypeCheckMapping result = new TypeCheckMapping();
338 for (ClassElement element in instantiated) { 338 for (ClassElement element in instantiated) {
339 if (checked.contains(element)) { 339 if (checked.contains(element)) {
340 result.add(element, element, null); 340 result.add(element, element, null);
341 } 341 }
342 // Find all supertypes of [element] in [checkedArguments] and add checks 342 // Find all supertypes of [element] in [checkedArguments] and add checks
343 // and precompute the substitutions for them. 343 // and precompute the substitutions for them.
344 assert(invariant(element, element.allSupertypes != null, 344 assert(invariant(element, element.allSupertypes != null,
345 message: 'Supertypes have not been computed for $element.')); 345 message: 'Supertypes have not been computed for $element.'));
346 for (DartType supertype in element.allSupertypes) { 346 for (DartType supertype in element.allSupertypes) {
347 ClassElement superelement = supertype.element; 347 ClassElement superelement = supertype.element;
348 if (checked.contains(superelement)) { 348 if (checked.contains(superelement)) {
349 Substitution substitution = 349 Substitution substitution =
350 computeSubstitution(element, superelement); 350 computeSubstitution(element, superelement);
351 result.add(element, superelement, substitution); 351 result.add(element, superelement, substitution);
352 } 352 }
353 } 353 }
354 } 354 }
355 return result; 355 return result;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 return instantiatedTypes; 391 return instantiatedTypes;
392 } 392 }
393 393
394 /** 394 /**
395 * Collects all types used in type arguments of instantiated types. 395 * Collects all types used in type arguments of instantiated types.
396 * 396 *
397 * This includes type arguments used in supertype relations, because we may 397 * This includes type arguments used in supertype relations, because we may
398 * have a type check against this supertype that includes a check against 398 * have a type check against this supertype that includes a check against
399 * the type arguments. 399 * the type arguments.
400 */ 400 */
401 void computeInstantiatedArguments(Set<DartType> instantiatedTypes, 401 void computeInstantiatedArguments(
402 Set<DartType> isChecks) { 402 Set<DartType> instantiatedTypes, Set<DartType> isChecks) {
403 ArgumentCollector superCollector = new ArgumentCollector(backend); 403 ArgumentCollector superCollector = new ArgumentCollector(backend);
404 ArgumentCollector directCollector = new ArgumentCollector(backend); 404 ArgumentCollector directCollector = new ArgumentCollector(backend);
405 FunctionArgumentCollector functionArgumentCollector = 405 FunctionArgumentCollector functionArgumentCollector =
406 new FunctionArgumentCollector(backend); 406 new FunctionArgumentCollector(backend);
407 407
408 // We need to add classes occuring in function type arguments, like for 408 // We need to add classes occuring in function type arguments, like for
409 // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :]. 409 // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :].
410 void collectFunctionTypeArguments(Iterable<DartType> types) { 410 void collectFunctionTypeArguments(Iterable<DartType> types) {
411 for (DartType type in types) { 411 for (DartType type in types) {
412 functionArgumentCollector.collect(type); 412 functionArgumentCollector.collect(type);
413 } 413 }
414 } 414 }
415 collectFunctionTypeArguments(isChecks); 415 collectFunctionTypeArguments(isChecks);
416 collectFunctionTypeArguments(checkedBounds); 416 collectFunctionTypeArguments(checkedBounds);
417 417
418 void collectTypeArguments(Iterable<DartType> types, 418 void collectTypeArguments(Iterable<DartType> types,
419 {bool isTypeArgument: false}) { 419 {bool isTypeArgument: false}) {
420 for (DartType type in types) { 420 for (DartType type in types) {
421 directCollector.collect(type, isTypeArgument: isTypeArgument); 421 directCollector.collect(type, isTypeArgument: isTypeArgument);
422 if (type.isInterfaceType) { 422 if (type.isInterfaceType) {
423 ClassElement cls = type.element; 423 ClassElement cls = type.element;
424 for (DartType supertype in cls.allSupertypes) { 424 for (DartType supertype in cls.allSupertypes) {
425 superCollector.collect(supertype, isTypeArgument: isTypeArgument); 425 superCollector.collect(supertype, isTypeArgument: isTypeArgument);
426 } 426 }
427 } 427 }
428 } 428 }
429 } 429 }
430 collectTypeArguments(instantiatedTypes); 430 collectTypeArguments(instantiatedTypes);
431 collectTypeArguments(checkedTypeArguments, isTypeArgument: true); 431 collectTypeArguments(checkedTypeArguments, isTypeArgument: true);
432 432
433 for (ClassElement cls in superCollector.classes.toList()) { 433 for (ClassElement cls in superCollector.classes.toList()) {
434 for (DartType supertype in cls.allSupertypes) { 434 for (DartType supertype in cls.allSupertypes) {
435 superCollector.collect(supertype); 435 superCollector.collect(supertype);
436 } 436 }
437 } 437 }
438 438
439 directlyInstantiatedArguments = 439 directlyInstantiatedArguments = directCollector.classes
440 directCollector.classes..addAll(functionArgumentCollector.classes); 440 ..addAll(functionArgumentCollector.classes);
441 allInstantiatedArguments = 441 allInstantiatedArguments = superCollector.classes
442 superCollector.classes..addAll(directlyInstantiatedArguments); 442 ..addAll(directlyInstantiatedArguments);
443 } 443 }
444 444
445 /// Collects all type arguments used in is-checks. 445 /// Collects all type arguments used in is-checks.
446 void computeCheckedArguments(Set<DartType> instantiatedTypes, 446 void computeCheckedArguments(
447 Set<DartType> isChecks) { 447 Set<DartType> instantiatedTypes, Set<DartType> isChecks) {
448 ArgumentCollector collector = new ArgumentCollector(backend); 448 ArgumentCollector collector = new ArgumentCollector(backend);
449 FunctionArgumentCollector functionArgumentCollector = 449 FunctionArgumentCollector functionArgumentCollector =
450 new FunctionArgumentCollector(backend); 450 new FunctionArgumentCollector(backend);
451 451
452 // We need to add types occuring in function type arguments, like for 452 // We need to add types occuring in function type arguments, like for
453 // instance 'J' for [: (J j) {} is f :] where f is 453 // instance 'J' for [: (J j) {} is f :] where f is
454 // [: typedef void f(I i); :] and 'J' is a subtype of 'I'. 454 // [: typedef void f(I i); :] and 'J' is a subtype of 'I'.
455 void collectFunctionTypeArguments(Iterable<DartType> types) { 455 void collectFunctionTypeArguments(Iterable<DartType> types) {
456 for (DartType type in types) { 456 for (DartType type in types) {
457 functionArgumentCollector.collect(type); 457 functionArgumentCollector.collect(type);
458 } 458 }
459 } 459 }
460 collectFunctionTypeArguments(instantiatedTypes); 460 collectFunctionTypeArguments(instantiatedTypes);
461 collectFunctionTypeArguments(checkedTypeArguments); 461 collectFunctionTypeArguments(checkedTypeArguments);
462 462
463 void collectTypeArguments(Iterable<DartType> types, 463 void collectTypeArguments(Iterable<DartType> types,
464 {bool isTypeArgument: false}) { 464 {bool isTypeArgument: false}) {
465 for (DartType type in types) { 465 for (DartType type in types) {
466 collector.collect(type, isTypeArgument: isTypeArgument); 466 collector.collect(type, isTypeArgument: isTypeArgument);
467 } 467 }
468 } 468 }
469 collectTypeArguments(isChecks); 469 collectTypeArguments(isChecks);
470 collectTypeArguments(checkedBounds, isTypeArgument: true); 470 collectTypeArguments(checkedBounds, isTypeArgument: true);
471 471
472 checkedArguments = 472 checkedArguments = collector.classes
473 collector.classes..addAll(functionArgumentCollector.classes); 473 ..addAll(functionArgumentCollector.classes);
474 } 474 }
475 475
476 @override 476 @override
477 Set<ClassElement> getClassesUsedInSubstitutions(JavaScriptBackend backend, 477 Set<ClassElement> getClassesUsedInSubstitutions(
478 TypeChecks checks) { 478 JavaScriptBackend backend, TypeChecks checks) {
479 Set<ClassElement> instantiated = new Set<ClassElement>(); 479 Set<ClassElement> instantiated = new Set<ClassElement>();
480 ArgumentCollector collector = new ArgumentCollector(backend); 480 ArgumentCollector collector = new ArgumentCollector(backend);
481 for (ClassElement target in checks.classes) { 481 for (ClassElement target in checks.classes) {
482 instantiated.add(target); 482 instantiated.add(target);
483 for (TypeCheck check in checks[target]) { 483 for (TypeCheck check in checks[target]) {
484 Substitution substitution = check.substitution; 484 Substitution substitution = check.substitution;
485 if (substitution != null) { 485 if (substitution != null) {
486 collector.collectAll(substitution.arguments); 486 collector.collectAll(substitution.arguments);
487 } 487 }
488 } 488 }
489 } 489 }
490 return instantiated..addAll(collector.classes); 490 return instantiated..addAll(collector.classes);
491 } 491 }
492 492
493 @override 493 @override
494 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend) { 494 Set<ClassElement> getRequiredArgumentClasses(JavaScriptBackend backend) {
495 Set<ClassElement> requiredArgumentClasses = 495 Set<ClassElement> requiredArgumentClasses = new Set<ClassElement>.from(
496 new Set<ClassElement>.from( 496 getClassesUsedInSubstitutions(backend, requiredChecks));
497 getClassesUsedInSubstitutions(backend, requiredChecks));
498 return requiredArgumentClasses 497 return requiredArgumentClasses
499 ..addAll(directlyInstantiatedArguments) 498 ..addAll(directlyInstantiatedArguments)
500 ..addAll(checkedArguments); 499 ..addAll(checkedArguments);
501 } 500 }
502 501
503 @override 502 @override
504 Set<ClassElement> getReferencedClasses(FunctionType type) { 503 Set<ClassElement> getReferencedClasses(FunctionType type) {
505 FunctionArgumentCollector collector = 504 FunctionArgumentCollector collector =
506 new FunctionArgumentCollector(backend); 505 new FunctionArgumentCollector(backend);
507 collector.collect(type); 506 collector.collect(type);
508 return collector.classes; 507 return collector.classes;
509 } 508 }
510 509
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 if (check.cls == other) { 550 if (check.cls == other) {
552 return check.substitution; 551 return check.substitution;
553 } 552 }
554 } 553 }
555 // There is no precomputed check for this pair (because the check is not 554 // There is no precomputed check for this pair (because the check is not
556 // done on type arguments only. Compute a new substitution. 555 // done on type arguments only. Compute a new substitution.
557 return computeSubstitution(cls, other); 556 return computeSubstitution(cls, other);
558 } 557 }
559 558
560 Substitution computeSubstitution(ClassElement cls, ClassElement check, 559 Substitution computeSubstitution(ClassElement cls, ClassElement check,
561 { bool alwaysGenerateFunction: false }) { 560 {bool alwaysGenerateFunction: false}) {
562 if (isTrivialSubstitution(cls, check)) return null; 561 if (isTrivialSubstitution(cls, check)) return null;
563 562
564 // Unnamed mixin application classes do not need substitutions, because they 563 // Unnamed mixin application classes do not need substitutions, because they
565 // are never instantiated and their checks are overwritten by the class that 564 // are never instantiated and their checks are overwritten by the class that
566 // they are mixed into. 565 // they are mixed into.
567 InterfaceType type = cls.thisType; 566 InterfaceType type = cls.thisType;
568 InterfaceType target = type.asInstanceOf(check); 567 InterfaceType target = type.asInstanceOf(check);
569 List<DartType> typeVariables = cls.typeVariables; 568 List<DartType> typeVariables = cls.typeVariables;
570 if (typeVariables.isEmpty && !alwaysGenerateFunction) { 569 if (typeVariables.isEmpty && !alwaysGenerateFunction) {
571 return new Substitution.list(target.typeArguments); 570 return new Substitution.list(target.typeArguments);
(...skipping 23 matching lines...) Expand all
595 594
596 /// Returns the JavaScript template that creates at runtime a new function 595 /// Returns the JavaScript template that creates at runtime a new function
597 /// type object. 596 /// type object.
598 @override 597 @override
599 jsAst.Template get templateForCreateFunctionType { 598 jsAst.Template get templateForCreateFunctionType {
600 return representationGenerator.templateForCreateFunctionType; 599 return representationGenerator.templateForCreateFunctionType;
601 } 600 }
602 601
603 @override 602 @override
604 jsAst.Expression getTypeRepresentation( 603 jsAst.Expression getTypeRepresentation(
605 DartType type, 604 DartType type, OnVariableCallback onVariable,
606 OnVariableCallback onVariable,
607 [ShouldEncodeTypedefCallback shouldEncodeTypedef]) { 605 [ShouldEncodeTypedefCallback shouldEncodeTypedef]) {
608 return representationGenerator.getTypeRepresentation( 606 return representationGenerator.getTypeRepresentation(
609 type, onVariable, shouldEncodeTypedef); 607 type, onVariable, shouldEncodeTypedef);
610 } 608 }
611 609
612 @override 610 @override
613 jsAst.Expression getTypeRepresentationWithPlaceholders(DartType type, 611 jsAst.Expression getTypeRepresentationWithPlaceholders(
614 OnVariableCallback onVariable, {int firstPlaceholderIndex : 0}) { 612 DartType type, OnVariableCallback onVariable,
613 {int firstPlaceholderIndex: 0}) {
615 // Create a type representation. For type variables call the original 614 // Create a type representation. For type variables call the original
616 // callback for side effects and return a template placeholder. 615 // callback for side effects and return a template placeholder.
617 int positions = firstPlaceholderIndex; 616 int positions = firstPlaceholderIndex;
618 jsAst.Expression representation = getTypeRepresentation(type, (variable) { 617 jsAst.Expression representation = getTypeRepresentation(type, (variable) {
619 onVariable(variable); 618 onVariable(variable);
620 return new jsAst.InterpolatedExpression(positions++); 619 return new jsAst.InterpolatedExpression(positions++);
621 }); 620 });
622 return representation; 621 return representation;
623 } 622 }
624 623
625 @override 624 @override
626 jsAst.Expression getSubstitutionRepresentation( 625 jsAst.Expression getSubstitutionRepresentation(
627 List<DartType> types, 626 List<DartType> types, OnVariableCallback onVariable) {
628 OnVariableCallback onVariable) {
629 List<jsAst.Expression> elements = types 627 List<jsAst.Expression> elements = types
630 .map((DartType type) => getTypeRepresentation(type, onVariable)) 628 .map((DartType type) => getTypeRepresentation(type, onVariable))
631 .toList(growable: false); 629 .toList(growable: false);
632 return new jsAst.ArrayInitializer(elements); 630 return new jsAst.ArrayInitializer(elements);
633 } 631 }
634 632
635 jsAst.Expression getTypeEncoding(DartType type, 633 jsAst.Expression getTypeEncoding(DartType type,
636 {bool alwaysGenerateFunction: false}) { 634 {bool alwaysGenerateFunction: false}) {
637 ClassElement contextClass = Types.getClassContext(type); 635 ClassElement contextClass = Types.getClassContext(type);
638 jsAst.Expression onVariable(TypeVariableType v) { 636 jsAst.Expression onVariable(TypeVariableType v) {
639 return new jsAst.VariableUse(v.name); 637 return new jsAst.VariableUse(v.name);
640 }; 638 }
639 ;
641 jsAst.Expression encoding = getTypeRepresentation(type, onVariable); 640 jsAst.Expression encoding = getTypeRepresentation(type, onVariable);
642 if (contextClass == null && !alwaysGenerateFunction) { 641 if (contextClass == null && !alwaysGenerateFunction) {
643 return encoding; 642 return encoding;
644 } else { 643 } else {
645 List<String> parameters = const <String>[]; 644 List<String> parameters = const <String>[];
646 if (contextClass != null) { 645 if (contextClass != null) {
647 parameters = contextClass.typeVariables.map((type) { 646 parameters = contextClass.typeVariables.map((type) {
648 return type.toString(); 647 return type.toString();
649 }).toList(); 648 }).toList();
650 } 649 }
651 return js('function(#) { return # }', [parameters, encoding]); 650 return js('function(#) { return # }', [parameters, encoding]);
652 } 651 }
653 } 652 }
654 653
655 @override 654 @override
656 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_) { 655 jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_) {
657 ClassElement contextClass = Types.getClassContext(type); 656 ClassElement contextClass = Types.getClassContext(type);
658 jsAst.Expression encoding = 657 jsAst.Expression encoding =
659 getTypeEncoding(type, alwaysGenerateFunction: true); 658 getTypeEncoding(type, alwaysGenerateFunction: true);
660 if (contextClass != null) { 659 if (contextClass != null) {
661 JavaScriptBackend backend = compiler.backend; 660 JavaScriptBackend backend = compiler.backend;
662 jsAst.Name contextName = backend.namer.className(contextClass); 661 jsAst.Name contextName = backend.namer.className(contextClass);
663 return js('function () { return #(#, #, #); }', 662 return js('function () { return #(#, #, #); }', [
664 [ backend.emitter.staticFunctionAccess( 663 backend.emitter.staticFunctionAccess(backend.helpers.computeSignature),
665 backend.helpers.computeSignature), 664 encoding,
666 encoding, this_, js.quoteName(contextName) ]); 665 this_,
666 js.quoteName(contextName)
667 ]);
667 } else { 668 } else {
668 return encoding; 669 return encoding;
669 } 670 }
670 } 671 }
671 672
672 /** 673 /**
673 * Compute a JavaScript expression that describes the necessary substitution 674 * Compute a JavaScript expression that describes the necessary substitution
674 * for type arguments in a subtype test. 675 * for type arguments in a subtype test.
675 * 676 *
676 * The result can be: 677 * The result can be:
(...skipping 25 matching lines...) Expand all
702 Iterable<jsAst.Expression> formals = 703 Iterable<jsAst.Expression> formals =
703 substitution.parameters.map(declaration); 704 substitution.parameters.map(declaration);
704 return js('function(#) { return # }', [formals, value]); 705 return js('function(#) { return # }', [formals, value]);
705 } else { 706 } else {
706 return js('function() { return # }', value); 707 return js('function() { return # }', value);
707 } 708 }
708 } 709 }
709 } 710 }
710 711
711 @override 712 @override
712 jsAst.Expression getSubstitutionCodeForVariable(Substitution substitution, 713 jsAst.Expression getSubstitutionCodeForVariable(
713 int index) { 714 Substitution substitution, int index) {
714 jsAst.Expression declaration(TypeVariableType variable) { 715 jsAst.Expression declaration(TypeVariableType variable) {
715 return new jsAst.Parameter(getVariableName(variable.name)); 716 return new jsAst.Parameter(getVariableName(variable.name));
716 } 717 }
717 718
718 jsAst.Expression use(TypeVariableType variable) { 719 jsAst.Expression use(TypeVariableType variable) {
719 return new jsAst.VariableUse(getVariableName(variable.name)); 720 return new jsAst.VariableUse(getVariableName(variable.name));
720 } 721 }
721 722
722 if (substitution.arguments[index].isDynamic) { 723 if (substitution.arguments[index].isDynamic) {
723 return backend.emitter.emitter.generateFunctionThatReturnsNull(); 724 return backend.emitter.emitter.generateFunctionThatReturnsNull();
724 } else { 725 } else {
725 jsAst.Expression value = 726 jsAst.Expression value =
726 getTypeRepresentation(substitution.arguments[index], use); 727 getTypeRepresentation(substitution.arguments[index], use);
727 Iterable<jsAst.Expression> formals = 728 Iterable<jsAst.Expression> formals =
728 substitution.parameters.map(declaration); 729 substitution.parameters.map(declaration);
729 return js('function(#) { return # }', [formals, value]); 730 return js('function(#) { return # }', [formals, value]);
730 } 731 }
731 } 732 }
732 733
733 String getVariableName(String name) { 734 String getVariableName(String name) {
734 return backend.namer.safeVariableName(name); 735 return backend.namer.safeVariableName(name);
735 } 736 }
736 737
737 @override 738 @override
738 jsAst.Name get getFunctionThatReturnsNullName 739 jsAst.Name get getFunctionThatReturnsNullName =>
739 => backend.namer.internalGlobal('functionThatReturnsNull'); 740 backend.namer.internalGlobal('functionThatReturnsNull');
740 741
741 @override 742 @override
742 String getTypeRepresentationForTypeConstant(DartType type) { 743 String getTypeRepresentationForTypeConstant(DartType type) {
743 JavaScriptBackend backend = compiler.backend; 744 JavaScriptBackend backend = compiler.backend;
744 Namer namer = backend.namer; 745 Namer namer = backend.namer;
745 if (type.isDynamic) return "dynamic"; 746 if (type.isDynamic) return "dynamic";
746 String name = namer.uniqueNameForTypeConstantElement(type.element); 747 String name = namer.uniqueNameForTypeConstantElement(type.element);
747 if (!type.element.isClass) return name; 748 if (!type.element.isClass) return name;
748 InterfaceType interface = type; 749 InterfaceType interface = type;
749 List<DartType> variables = interface.element.typeVariables; 750 List<DartType> variables = interface.element.typeVariables;
750 // Type constants can currently only be raw types, so there is no point 751 // Type constants can currently only be raw types, so there is no point
751 // adding ground-term type parameters, as they would just be 'dynamic'. 752 // adding ground-term type parameters, as they would just be 'dynamic'.
752 // TODO(sra): Since the result string is used only in constructing constant 753 // TODO(sra): Since the result string is used only in constructing constant
753 // names, it would result in more readable names if the final string was a 754 // names, it would result in more readable names if the final string was a
754 // legal JavaScript identifer. 755 // legal JavaScript identifer.
755 if (variables.isEmpty) return name; 756 if (variables.isEmpty) return name;
756 String arguments = 757 String arguments = new List.filled(variables.length, 'dynamic').join(', ');
757 new List.filled(variables.length, 'dynamic').join(', ');
758 return '$name<$arguments>'; 758 return '$name<$arguments>';
759 } 759 }
760 760
761 @override 761 @override
762 bool isSimpleFunctionType(FunctionType type) { 762 bool isSimpleFunctionType(FunctionType type) {
763 if (!type.returnType.isDynamic) return false; 763 if (!type.returnType.isDynamic) return false;
764 if (!type.optionalParameterTypes.isEmpty) return false; 764 if (!type.optionalParameterTypes.isEmpty) return false;
765 if (!type.namedParameterTypes.isEmpty) return false; 765 if (!type.namedParameterTypes.isEmpty) return false;
766 for (DartType parameter in type.parameterTypes ) { 766 for (DartType parameter in type.parameterTypes) {
767 if (!parameter.isDynamic) return false; 767 if (!parameter.isDynamic) return false;
768 } 768 }
769 return true; 769 return true;
770 } 770 }
771 } 771 }
772 772
773 class TypeRepresentationGenerator implements DartTypeVisitor { 773 class TypeRepresentationGenerator implements DartTypeVisitor {
774 final Compiler compiler; 774 final Compiler compiler;
775 OnVariableCallback onVariable; 775 OnVariableCallback onVariable;
776 ShouldEncodeTypedefCallback shouldEncodeTypedef; 776 ShouldEncodeTypedefCallback shouldEncodeTypedef;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 /// is a function type. 838 /// is a function type.
839 jsAst.Template get templateForIsFunctionType { 839 jsAst.Template get templateForIsFunctionType {
840 return jsAst.js.expressionTemplateFor("'${namer.functionTypeTag}' in #"); 840 return jsAst.js.expressionTemplateFor("'${namer.functionTypeTag}' in #");
841 } 841 }
842 842
843 /// Returns the JavaScript template that creates at runtime a new function 843 /// Returns the JavaScript template that creates at runtime a new function
844 /// type object. 844 /// type object.
845 jsAst.Template get templateForCreateFunctionType { 845 jsAst.Template get templateForCreateFunctionType {
846 // The value of the functionTypeTag can be anything. We use "dynaFunc" for 846 // The value of the functionTypeTag can be anything. We use "dynaFunc" for
847 // easier debugging. 847 // easier debugging.
848 return jsAst.js.expressionTemplateFor( 848 return jsAst.js
849 '{ ${namer.functionTypeTag}: "dynafunc" }'); 849 .expressionTemplateFor('{ ${namer.functionTypeTag}: "dynafunc" }');
850 } 850 }
851 851
852 visitFunctionType(FunctionType type, _) { 852 visitFunctionType(FunctionType type, _) {
853 List<jsAst.Property> properties = <jsAst.Property>[]; 853 List<jsAst.Property> properties = <jsAst.Property>[];
854 854
855 void addProperty(String name, jsAst.Expression value) { 855 void addProperty(String name, jsAst.Expression value) {
856 properties.add(new jsAst.Property(js.string(name), value)); 856 properties.add(new jsAst.Property(js.string(name), value));
857 } 857 }
858 858
859 // Type representations for functions have a property which is a tag marking 859 // Type representations for functions have a property which is a tag marking
860 // them as function types. The value is not used, so '1' is just a dummy. 860 // them as function types. The value is not used, so '1' is just a dummy.
861 addProperty(namer.functionTypeTag, js.number(1)); 861 addProperty(namer.functionTypeTag, js.number(1));
862 if (type.returnType.isVoid) { 862 if (type.returnType.isVoid) {
863 addProperty(namer.functionTypeVoidReturnTag, js('true')); 863 addProperty(namer.functionTypeVoidReturnTag, js('true'));
864 } else if (!type.returnType.treatAsDynamic) { 864 } else if (!type.returnType.treatAsDynamic) {
865 addProperty(namer.functionTypeReturnTypeTag, visit(type.returnType)); 865 addProperty(namer.functionTypeReturnTypeTag, visit(type.returnType));
866 } 866 }
867 if (!type.parameterTypes.isEmpty) { 867 if (!type.parameterTypes.isEmpty) {
868 addProperty(namer.functionTypeRequiredParametersTag, 868 addProperty(namer.functionTypeRequiredParametersTag,
869 visitList(type.parameterTypes)); 869 visitList(type.parameterTypes));
870 } 870 }
871 if (!type.optionalParameterTypes.isEmpty) { 871 if (!type.optionalParameterTypes.isEmpty) {
872 addProperty(namer.functionTypeOptionalParametersTag, 872 addProperty(namer.functionTypeOptionalParametersTag,
873 visitList(type.optionalParameterTypes)); 873 visitList(type.optionalParameterTypes));
874 } 874 }
875 if (!type.namedParameterTypes.isEmpty) { 875 if (!type.namedParameterTypes.isEmpty) {
876 List<jsAst.Property> namedArguments = <jsAst.Property>[]; 876 List<jsAst.Property> namedArguments = <jsAst.Property>[];
877 List<String> names = type.namedParameters; 877 List<String> names = type.namedParameters;
878 List<DartType> types = type.namedParameterTypes; 878 List<DartType> types = type.namedParameterTypes;
879 assert(types.length == names.length); 879 assert(types.length == names.length);
880 for (int index = 0; index < types.length; index++) { 880 for (int index = 0; index < types.length; index++) {
881 jsAst.Expression name = js.string(names[index]); 881 jsAst.Expression name = js.string(names[index]);
882 namedArguments.add(new jsAst.Property(name, visit(types[index]))); 882 namedArguments.add(new jsAst.Property(name, visit(types[index])));
883 } 883 }
884 addProperty(namer.functionTypeNamedParametersTag, 884 addProperty(namer.functionTypeNamedParametersTag,
885 new jsAst.ObjectInitializer(namedArguments)); 885 new jsAst.ObjectInitializer(namedArguments));
886 } 886 }
887 return new jsAst.ObjectInitializer(properties); 887 return new jsAst.ObjectInitializer(properties);
888 } 888 }
889 889
890 visitMalformedType(MalformedType type, _) { 890 visitMalformedType(MalformedType type, _) {
891 // Treat malformed types as dynamic at runtime. 891 // Treat malformed types as dynamic at runtime.
892 return js('null'); 892 return js('null');
893 } 893 }
894 894
895 visitVoidType(VoidType type, _) { 895 visitVoidType(VoidType type, _) {
(...skipping 14 matching lines...) Expand all
910 // Add it to the function-type object. 910 // Add it to the function-type object.
911 jsAst.LiteralString tag = js.string(namer.typedefTag); 911 jsAst.LiteralString tag = js.string(namer.typedefTag);
912 initializer.properties.add(new jsAst.Property(tag, encodedTypedef)); 912 initializer.properties.add(new jsAst.Property(tag, encodedTypedef));
913 return initializer; 913 return initializer;
914 } else { 914 } else {
915 return unaliasedType.accept(this, null); 915 return unaliasedType.accept(this, null);
916 } 916 }
917 } 917 }
918 918
919 visitStatementType(StatementType type, _) { 919 visitStatementType(StatementType type, _) {
920 reporter.internalError(NO_LOCATION_SPANNABLE, 920 reporter.internalError(
921 'Unexpected type: $type (${type.kind}).'); 921 NO_LOCATION_SPANNABLE, 'Unexpected type: $type (${type.kind}).');
922 } 922 }
923 } 923 }
924 924
925
926 class TypeCheckMapping implements TypeChecks { 925 class TypeCheckMapping implements TypeChecks {
927 final Map<ClassElement, Set<TypeCheck>> map = 926 final Map<ClassElement, Set<TypeCheck>> map =
928 new Map<ClassElement, Set<TypeCheck>>(); 927 new Map<ClassElement, Set<TypeCheck>>();
929 928
930 Iterable<TypeCheck> operator[](ClassElement element) { 929 Iterable<TypeCheck> operator [](ClassElement element) {
931 Set<TypeCheck> result = map[element]; 930 Set<TypeCheck> result = map[element];
932 return result != null ? result : const <TypeCheck>[]; 931 return result != null ? result : const <TypeCheck>[];
933 } 932 }
934 933
935 void add(ClassElement cls, ClassElement check, Substitution substitution) { 934 void add(ClassElement cls, ClassElement check, Substitution substitution) {
936 map.putIfAbsent(cls, () => new Set<TypeCheck>()); 935 map.putIfAbsent(cls, () => new Set<TypeCheck>());
937 map[cls].add(new TypeCheck(check, substitution)); 936 map[cls].add(new TypeCheck(check, substitution));
938 } 937 }
939 938
940 Iterable<ClassElement> get classes => map.keys; 939 Iterable<ClassElement> get classes => map.keys;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 //TODO(floitsch): Remove support for non-function substitutions. 1027 //TODO(floitsch): Remove support for non-function substitutions.
1029 class Substitution { 1028 class Substitution {
1030 final bool isFunction; 1029 final bool isFunction;
1031 final List<DartType> arguments; 1030 final List<DartType> arguments;
1032 final List<DartType> parameters; 1031 final List<DartType> parameters;
1033 1032
1034 Substitution.list(this.arguments) 1033 Substitution.list(this.arguments)
1035 : isFunction = false, 1034 : isFunction = false,
1036 parameters = const <DartType>[]; 1035 parameters = const <DartType>[];
1037 1036
1038 Substitution.function(this.arguments, this.parameters) 1037 Substitution.function(this.arguments, this.parameters) : isFunction = true;
1039 : isFunction = true;
1040 } 1038 }
1041 1039
1042 /** 1040 /**
1043 * A pair of a class that we need a check against and the type argument 1041 * A pair of a class that we need a check against and the type argument
1044 * substition for this check. 1042 * substition for this check.
1045 */ 1043 */
1046 class TypeCheck { 1044 class TypeCheck {
1047 final ClassElement cls; 1045 final ClassElement cls;
1048 final Substitution substitution; 1046 final Substitution substitution;
1049 final int hashCode = (nextHash++) & 0x3fffffff; 1047 final int hashCode = (nextHash++) & 0x3fffffff;
1050 static int nextHash = 49; 1048 static int nextHash = 49;
1051 1049
1052 TypeCheck(this.cls, this.substitution); 1050 TypeCheck(this.cls, this.substitution);
1053 } 1051 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/patch_resolver.dart ('k') | pkg/compiler/lib/src/js_backend/type_variable_handler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698