| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 /** | 5 /** |
| 6 * This library is capable of producing linked summaries from unlinked | 6 * This library is capable of producing linked summaries from unlinked |
| 7 * ones (or prelinked ones). It functions by building a miniature | 7 * ones (or prelinked ones). It functions by building a miniature |
| 8 * element model to represent the contents of the summaries, and then | 8 * element model to represent the contents of the summaries, and then |
| 9 * scanning the element model to gather linked information and adding | 9 * scanning the element model to gather linked information and adding |
| 10 * it to the summary data structures. | 10 * it to the summary data structures. |
| (...skipping 2396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2407 /** | 2407 /** |
| 2408 * Specialization of [FieldElementForLink] for class fields. | 2408 * Specialization of [FieldElementForLink] for class fields. |
| 2409 */ | 2409 */ |
| 2410 class FieldElementForLink_ClassField extends VariableElementForLink | 2410 class FieldElementForLink_ClassField extends VariableElementForLink |
| 2411 implements FieldElementForLink { | 2411 implements FieldElementForLink { |
| 2412 @override | 2412 @override |
| 2413 final ClassElementForLink_Class enclosingElement; | 2413 final ClassElementForLink_Class enclosingElement; |
| 2414 | 2414 |
| 2415 /** | 2415 /** |
| 2416 * If this is an instance field, the type that was computed by | 2416 * If this is an instance field, the type that was computed by |
| 2417 * [InstanceMemberInferrer]. | 2417 * [InstanceMemberInferrer] (if any). Otherwise `null`. |
| 2418 */ | 2418 */ |
| 2419 DartType _inferredInstanceType; | 2419 DartType _inferredInstanceType; |
| 2420 | 2420 |
| 2421 DartType _declaredType; | |
| 2422 | |
| 2423 FieldElementForLink_ClassField(ClassElementForLink_Class enclosingElement, | 2421 FieldElementForLink_ClassField(ClassElementForLink_Class enclosingElement, |
| 2424 UnlinkedVariable unlinkedVariable) | 2422 UnlinkedVariable unlinkedVariable) |
| 2425 : enclosingElement = enclosingElement, | 2423 : enclosingElement = enclosingElement, |
| 2426 super(unlinkedVariable, enclosingElement.enclosingElement); | 2424 super(unlinkedVariable, enclosingElement.enclosingElement); |
| 2427 | 2425 |
| 2428 @override | 2426 @override |
| 2429 bool get isStatic => unlinkedVariable.isStatic; | 2427 bool get isStatic => unlinkedVariable.isStatic; |
| 2430 | 2428 |
| 2431 @override | 2429 @override |
| 2432 DartType get type { | |
| 2433 // TODO(paulberry): can this be unified with | |
| 2434 // [VariableElementForLink.asStaticType]? | |
| 2435 assert(!isStatic); | |
| 2436 if (_inferredInstanceType != null) { | |
| 2437 return _inferredInstanceType; | |
| 2438 } else if (_declaredType == null) { | |
| 2439 if (unlinkedVariable.type == null) { | |
| 2440 if (!compilationUnit.isInBuildUnit) { | |
| 2441 _inferredInstanceType = compilationUnit.getLinkedType( | |
| 2442 unlinkedVariable.inferredTypeSlot, enclosingElement); | |
| 2443 return _inferredInstanceType; | |
| 2444 } | |
| 2445 _declaredType = DynamicTypeImpl.instance; | |
| 2446 } else { | |
| 2447 _declaredType = compilationUnit._resolveTypeRef( | |
| 2448 unlinkedVariable.type, enclosingElement); | |
| 2449 } | |
| 2450 } | |
| 2451 return _declaredType; | |
| 2452 } | |
| 2453 | |
| 2454 @override | |
| 2455 void set type(DartType inferredType) { | 2430 void set type(DartType inferredType) { |
| 2456 assert(!isStatic); | 2431 assert(!isStatic); |
| 2457 assert(_inferredInstanceType == null); | 2432 assert(_inferredInstanceType == null); |
| 2458 _inferredInstanceType = inferredType; | 2433 _inferredInstanceType = inferredType; |
| 2459 } | 2434 } |
| 2460 | 2435 |
| 2461 @override | 2436 @override |
| 2462 TypeParameterizedElementForLink get _typeParameterContext => enclosingElement; | 2437 TypeParameterizedElementForLink get _typeParameterContext => enclosingElement; |
| 2463 | 2438 |
| 2464 /** | 2439 /** |
| 2465 * Store the results of type inference for this field in | 2440 * Store the results of type inference for this field in |
| 2466 * [compilationUnit]. | 2441 * [compilationUnit]. |
| 2467 */ | 2442 */ |
| 2468 void link(CompilationUnitElementInBuildUnit compilationUnit) { | 2443 void link(CompilationUnitElementInBuildUnit compilationUnit) { |
| 2469 if (hasImplicitType) { | 2444 if (hasImplicitType) { |
| 2470 if (isStatic) { | 2445 compilationUnit._storeLinkedType( |
| 2471 TypeInferenceNode typeInferenceNode = this.asTypeInferenceNode; | 2446 unlinkedVariable.inferredTypeSlot, |
| 2472 if (typeInferenceNode != null) { | 2447 isStatic ? inferredType : _inferredInstanceType, |
| 2473 compilationUnit._storeLinkedType(unlinkedVariable.inferredTypeSlot, | 2448 _typeParameterContext); |
| 2474 typeInferenceNode.inferredType, enclosingElement); | |
| 2475 } | |
| 2476 } else { | |
| 2477 compilationUnit._storeLinkedType(unlinkedVariable.inferredTypeSlot, | |
| 2478 _inferredInstanceType, enclosingElement); | |
| 2479 } | |
| 2480 } | 2449 } |
| 2481 } | 2450 } |
| 2482 | 2451 |
| 2483 @override | 2452 @override |
| 2484 String toString() => '$enclosingElement.$name'; | 2453 String toString() => '$enclosingElement.$name'; |
| 2485 } | 2454 } |
| 2486 | 2455 |
| 2487 /** | 2456 /** |
| 2488 * Specialization of [FieldElementForLink] for enum fields. | 2457 * Specialization of [FieldElementForLink] for enum fields. |
| 2489 */ | 2458 */ |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2596 /** | 2565 /** |
| 2597 * The variable for which this element is the initializer. | 2566 * The variable for which this element is the initializer. |
| 2598 */ | 2567 */ |
| 2599 final VariableElementForLink _variable; | 2568 final VariableElementForLink _variable; |
| 2600 | 2569 |
| 2601 FunctionElementForLink_Initializer(this._variable); | 2570 FunctionElementForLink_Initializer(this._variable); |
| 2602 | 2571 |
| 2603 @override | 2572 @override |
| 2604 DartType get returnType { | 2573 DartType get returnType { |
| 2605 // If this is a variable whose type needs inferring, infer it. | 2574 // If this is a variable whose type needs inferring, infer it. |
| 2606 TypeInferenceNode typeInferenceNode = _variable._typeInferenceNode; | 2575 if (_variable.hasImplicitType) { |
| 2607 if (typeInferenceNode != null) { | 2576 return _variable.inferredType; |
| 2608 return typeInferenceNode.inferredType; | |
| 2609 } else { | 2577 } else { |
| 2610 // There's no reason linking should need to access the type of | 2578 // There's no reason linking should need to access the type of |
| 2611 // this FunctionElement, since the variable doesn't need its | 2579 // this FunctionElement, since the variable doesn't need its |
| 2612 // type inferred. | 2580 // type inferred. |
| 2613 assert(false); | 2581 assert(false); |
| 2614 // But for robustness, return the dynamic type. | 2582 // But for robustness, return the dynamic type. |
| 2615 return DynamicTypeImpl.instance; | 2583 return DynamicTypeImpl.instance; |
| 2616 } | 2584 } |
| 2617 } | 2585 } |
| 2618 | 2586 |
| 2619 @override | 2587 @override |
| 2620 void set returnType(DartType newType) { | 2588 void set returnType(DartType newType) { |
| 2621 // TODO(paulberry): store inferred type. | 2589 // InstanceMemberInferrer stores the new type both here and on the variable |
| 2590 // element. We don't need to record both values, so we ignore it here. |
| 2622 } | 2591 } |
| 2623 | 2592 |
| 2624 @override | 2593 @override |
| 2625 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 2594 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| 2626 } | 2595 } |
| 2627 | 2596 |
| 2628 /** | 2597 /** |
| 2629 * Specialization of [DependencyWalker] for linking library cycles. | 2598 * Specialization of [DependencyWalker] for linking library cycles. |
| 2630 */ | 2599 */ |
| 2631 class LibraryCycleDependencyWalker extends DependencyWalker<LibraryCycleNode> { | 2600 class LibraryCycleDependencyWalker extends DependencyWalker<LibraryCycleNode> { |
| (...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3736 TypeParameterizedElementForLink get _typeParameterContext => null; | 3705 TypeParameterizedElementForLink get _typeParameterContext => null; |
| 3737 | 3706 |
| 3738 /** | 3707 /** |
| 3739 * Store the results of type inference for this variable in | 3708 * Store the results of type inference for this variable in |
| 3740 * [compilationUnit]. | 3709 * [compilationUnit]. |
| 3741 */ | 3710 */ |
| 3742 void link(CompilationUnitElementInBuildUnit compilationUnit) { | 3711 void link(CompilationUnitElementInBuildUnit compilationUnit) { |
| 3743 if (hasImplicitType) { | 3712 if (hasImplicitType) { |
| 3744 TypeInferenceNode typeInferenceNode = this.asTypeInferenceNode; | 3713 TypeInferenceNode typeInferenceNode = this.asTypeInferenceNode; |
| 3745 if (typeInferenceNode != null) { | 3714 if (typeInferenceNode != null) { |
| 3746 compilationUnit._storeLinkedType(unlinkedVariable.inferredTypeSlot, | 3715 compilationUnit._storeLinkedType( |
| 3747 typeInferenceNode.inferredType, null); | 3716 unlinkedVariable.inferredTypeSlot, inferredType, null); |
| 3748 } | 3717 } |
| 3749 } | 3718 } |
| 3750 } | 3719 } |
| 3751 } | 3720 } |
| 3752 | 3721 |
| 3753 /** | 3722 /** |
| 3754 * Specialization of [DependencyWalker] for performing type inferrence | 3723 * Specialization of [DependencyWalker] for performing type inferrence |
| 3755 * on static and top level variables. | 3724 * on static and top level variables. |
| 3756 */ | 3725 */ |
| 3757 class TypeInferenceDependencyWalker | 3726 class TypeInferenceDependencyWalker |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3773 * Specialization of [Node] used to construct the type inference dependency | 3742 * Specialization of [Node] used to construct the type inference dependency |
| 3774 * graph. | 3743 * graph. |
| 3775 */ | 3744 */ |
| 3776 class TypeInferenceNode extends Node<TypeInferenceNode> { | 3745 class TypeInferenceNode extends Node<TypeInferenceNode> { |
| 3777 /** | 3746 /** |
| 3778 * The [FieldElement] or [TopLevelVariableElement] to which this | 3747 * The [FieldElement] or [TopLevelVariableElement] to which this |
| 3779 * node refers. | 3748 * node refers. |
| 3780 */ | 3749 */ |
| 3781 final VariableElementForLink variableElement; | 3750 final VariableElementForLink variableElement; |
| 3782 | 3751 |
| 3783 /** | |
| 3784 * If a type has been inferred for this node, the inferred type (may be | |
| 3785 * `dynamic`). Otherwise `null`. | |
| 3786 */ | |
| 3787 DartType _inferredType; | |
| 3788 | |
| 3789 TypeInferenceNode(this.variableElement); | 3752 TypeInferenceNode(this.variableElement); |
| 3790 | 3753 |
| 3791 /** | |
| 3792 * Infer a type for this node if necessary, and return it. | |
| 3793 */ | |
| 3794 DartType get inferredType { | |
| 3795 if (_inferredType == null) { | |
| 3796 Linker._initializerTypeInferenceCycle = | |
| 3797 variableElement.compilationUnit.library.libraryCycleForLink; | |
| 3798 new TypeInferenceDependencyWalker().walk(this); | |
| 3799 assert(_inferredType != null); | |
| 3800 Linker._initializerTypeInferenceCycle = null; | |
| 3801 } | |
| 3802 return _inferredType; | |
| 3803 } | |
| 3804 | |
| 3805 @override | 3754 @override |
| 3806 bool get isEvaluated => _inferredType != null; | 3755 bool get isEvaluated => variableElement._inferredType != null; |
| 3807 | 3756 |
| 3808 /** | 3757 /** |
| 3809 * Collect the type inference dependencies in [unlinkedConst] (which should be | 3758 * Collect the type inference dependencies in [unlinkedConst] (which should be |
| 3810 * interpreted relative to [compilationUnit]) and store them in | 3759 * interpreted relative to [compilationUnit]) and store them in |
| 3811 * [dependencies]. | 3760 * [dependencies]. |
| 3812 */ | 3761 */ |
| 3813 void collectDependencies( | 3762 void collectDependencies( |
| 3814 List<TypeInferenceNode> dependencies, | 3763 List<TypeInferenceNode> dependencies, |
| 3815 UnlinkedConst unlinkedConst, | 3764 UnlinkedConst unlinkedConst, |
| 3816 CompilationUnitElementForLink compilationUnit) { | 3765 CompilationUnitElementForLink compilationUnit) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3864 List<TypeInferenceNode> dependencies = <TypeInferenceNode>[]; | 3813 List<TypeInferenceNode> dependencies = <TypeInferenceNode>[]; |
| 3865 collectDependencies( | 3814 collectDependencies( |
| 3866 dependencies, | 3815 dependencies, |
| 3867 variableElement.unlinkedVariable.constExpr, | 3816 variableElement.unlinkedVariable.constExpr, |
| 3868 variableElement.compilationUnit); | 3817 variableElement.compilationUnit); |
| 3869 return dependencies; | 3818 return dependencies; |
| 3870 } | 3819 } |
| 3871 | 3820 |
| 3872 void evaluate(bool inCycle) { | 3821 void evaluate(bool inCycle) { |
| 3873 if (inCycle) { | 3822 if (inCycle) { |
| 3874 _inferredType = DynamicTypeImpl.instance; | 3823 variableElement._inferredType = DynamicTypeImpl.instance; |
| 3875 } else { | 3824 } else { |
| 3876 _inferredType = new ExprTypeComputer(variableElement).compute(); | 3825 variableElement._inferredType = |
| 3826 new ExprTypeComputer(variableElement).compute(); |
| 3877 } | 3827 } |
| 3878 } | 3828 } |
| 3879 } | 3829 } |
| 3880 | 3830 |
| 3881 /** | 3831 /** |
| 3882 * Element representing a type parameter resynthesized from a summary during | 3832 * Element representing a type parameter resynthesized from a summary during |
| 3883 * linking. | 3833 * linking. |
| 3884 */ | 3834 */ |
| 3885 class TypeParameterElementForLink implements TypeParameterElementImpl { | 3835 class TypeParameterElementForLink implements TypeParameterElementImpl { |
| 3886 /** | 3836 /** |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4203 ConstNode _constNode; | 4153 ConstNode _constNode; |
| 4204 | 4154 |
| 4205 /** | 4155 /** |
| 4206 * If this variable has an initializer and an implicit type, and the enclosing | 4156 * If this variable has an initializer and an implicit type, and the enclosing |
| 4207 * library is part of the build unit being linked, the variable's node in the | 4157 * library is part of the build unit being linked, the variable's node in the |
| 4208 * type inference dependency graph. Otherwise `null`. | 4158 * type inference dependency graph. Otherwise `null`. |
| 4209 */ | 4159 */ |
| 4210 TypeInferenceNode _typeInferenceNode; | 4160 TypeInferenceNode _typeInferenceNode; |
| 4211 | 4161 |
| 4212 FunctionElementForLink_Initializer _initializer; | 4162 FunctionElementForLink_Initializer _initializer; |
| 4213 DartType _staticType; | 4163 DartType _inferredType; |
| 4164 DartType _declaredType; |
| 4214 | 4165 |
| 4215 /** | 4166 /** |
| 4216 * The compilation unit in which this variable appears. | 4167 * The compilation unit in which this variable appears. |
| 4217 */ | 4168 */ |
| 4218 final CompilationUnitElementForLink compilationUnit; | 4169 final CompilationUnitElementForLink compilationUnit; |
| 4219 | 4170 |
| 4220 VariableElementForLink(this.unlinkedVariable, this.compilationUnit) { | 4171 VariableElementForLink(this.unlinkedVariable, this.compilationUnit) { |
| 4221 if (compilationUnit.isInBuildUnit && unlinkedVariable.constExpr != null) { | 4172 if (compilationUnit.isInBuildUnit && unlinkedVariable.constExpr != null) { |
| 4222 _constNode = new ConstVariableNode(this); | 4173 _constNode = new ConstVariableNode(this); |
| 4223 if (unlinkedVariable.type == null) { | 4174 if (unlinkedVariable.type == null) { |
| 4224 _typeInferenceNode = new TypeInferenceNode(this); | 4175 _typeInferenceNode = new TypeInferenceNode(this); |
| 4225 } | 4176 } |
| 4226 } | 4177 } |
| 4227 } | 4178 } |
| 4228 | 4179 |
| 4229 @override | 4180 @override |
| 4230 ConstructorElementForLink get asConstructor => null; | 4181 ConstructorElementForLink get asConstructor => null; |
| 4231 | 4182 |
| 4232 @override | 4183 @override |
| 4233 ConstVariableNode get asConstVariable => _constNode; | 4184 ConstVariableNode get asConstVariable => _constNode; |
| 4234 | 4185 |
| 4235 @override | 4186 @override |
| 4236 DartType get asStaticType { | 4187 DartType get asStaticType => type; |
| 4237 if (_staticType == null) { | |
| 4238 if (_typeInferenceNode != null) { | |
| 4239 assert(_typeInferenceNode.isEvaluated); | |
| 4240 _staticType = _typeInferenceNode.inferredType; | |
| 4241 } else if (hasImplicitType) { | |
| 4242 if (!compilationUnit.isInBuildUnit) { | |
| 4243 _staticType = compilationUnit.getLinkedType( | |
| 4244 unlinkedVariable.inferredTypeSlot, _typeParameterContext); | |
| 4245 } else { | |
| 4246 _staticType = DynamicTypeImpl.instance; | |
| 4247 } | |
| 4248 } else { | |
| 4249 _staticType = compilationUnit._resolveTypeRef( | |
| 4250 unlinkedVariable.type, _typeParameterContext); | |
| 4251 } | |
| 4252 } | |
| 4253 return _staticType; | |
| 4254 } | |
| 4255 | 4188 |
| 4256 @override | 4189 @override |
| 4257 TypeInferenceNode get asTypeInferenceNode => _typeInferenceNode; | 4190 TypeInferenceNode get asTypeInferenceNode => _typeInferenceNode; |
| 4258 | 4191 |
| 4192 /** |
| 4193 * If the variable has an explicitly declared return type, return it. |
| 4194 * Otherwise return `null`. |
| 4195 */ |
| 4196 DartType get declaredType { |
| 4197 if (unlinkedVariable.type == null) { |
| 4198 return null; |
| 4199 } else { |
| 4200 return _declaredType ??= compilationUnit._resolveTypeRef( |
| 4201 unlinkedVariable.type, _typeParameterContext); |
| 4202 } |
| 4203 } |
| 4204 |
| 4259 @override | 4205 @override |
| 4260 bool get hasImplicitType => unlinkedVariable.type == null; | 4206 bool get hasImplicitType => unlinkedVariable.type == null; |
| 4261 | 4207 |
| 4208 /** |
| 4209 * Return the inferred type of the variable element. Should only be called if |
| 4210 * no type was explicitly declared. |
| 4211 */ |
| 4212 DartType get inferredType { |
| 4213 // We should only try to infer a type when none is explicitly declared. |
| 4214 assert(unlinkedVariable.type == null); |
| 4215 if (_inferredType == null) { |
| 4216 if (_typeInferenceNode != null) { |
| 4217 assert(Linker._initializerTypeInferenceCycle == null); |
| 4218 Linker._initializerTypeInferenceCycle = |
| 4219 compilationUnit.library.libraryCycleForLink; |
| 4220 try { |
| 4221 new TypeInferenceDependencyWalker().walk(_typeInferenceNode); |
| 4222 assert(_inferredType != null); |
| 4223 } finally { |
| 4224 Linker._initializerTypeInferenceCycle = null; |
| 4225 } |
| 4226 } else if (compilationUnit.isInBuildUnit) { |
| 4227 _inferredType = DynamicTypeImpl.instance; |
| 4228 } else { |
| 4229 _inferredType = compilationUnit.getLinkedType( |
| 4230 unlinkedVariable.inferredTypeSlot, _typeParameterContext); |
| 4231 } |
| 4232 } |
| 4233 return _inferredType; |
| 4234 } |
| 4235 |
| 4262 @override | 4236 @override |
| 4263 FunctionElementForLink_Initializer get initializer { | 4237 FunctionElementForLink_Initializer get initializer { |
| 4264 if (unlinkedVariable.constExpr == null) { | 4238 if (unlinkedVariable.constExpr == null) { |
| 4265 return null; | 4239 return null; |
| 4266 } else { | 4240 } else { |
| 4267 return _initializer ??= new FunctionElementForLink_Initializer(this); | 4241 return _initializer ??= new FunctionElementForLink_Initializer(this); |
| 4268 } | 4242 } |
| 4269 } | 4243 } |
| 4270 | 4244 |
| 4271 @override | 4245 @override |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4283 @override | 4257 @override |
| 4284 String get name => unlinkedVariable.name; | 4258 String get name => unlinkedVariable.name; |
| 4285 | 4259 |
| 4286 @override | 4260 @override |
| 4287 DartType get propagatedType { | 4261 DartType get propagatedType { |
| 4288 // TODO(paulberry): implement propagated types in the linker. | 4262 // TODO(paulberry): implement propagated types in the linker. |
| 4289 return DynamicTypeImpl.instance; | 4263 return DynamicTypeImpl.instance; |
| 4290 } | 4264 } |
| 4291 | 4265 |
| 4292 @override | 4266 @override |
| 4267 DartType get type => declaredType ?? inferredType; |
| 4268 |
| 4269 @override |
| 4293 void set type(DartType newType) { | 4270 void set type(DartType newType) { |
| 4294 // TODO(paulberry): store inferred type. | 4271 // TODO(paulberry): store inferred type. |
| 4295 } | 4272 } |
| 4296 | 4273 |
| 4297 /** | 4274 /** |
| 4298 * The context in which type parameters should be interpreted, or `null` if | 4275 * The context in which type parameters should be interpreted, or `null` if |
| 4299 * there are no type parameters in scope. | 4276 * there are no type parameters in scope. |
| 4300 */ | 4277 */ |
| 4301 TypeParameterizedElementForLink get _typeParameterContext; | 4278 TypeParameterizedElementForLink get _typeParameterContext; |
| 4302 | 4279 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4325 if (type is InterfaceType) { | 4302 if (type is InterfaceType) { |
| 4326 Element result = type.lookUpGetter(name, compilationUnit.library); | 4303 Element result = type.lookUpGetter(name, compilationUnit.library); |
| 4327 result ??= type.lookUpMethod(name, compilationUnit.library); | 4304 result ??= type.lookUpMethod(name, compilationUnit.library); |
| 4328 return result; | 4305 return result; |
| 4329 } | 4306 } |
| 4330 } | 4307 } |
| 4331 // TODO(scheglov): implement for propagated types | 4308 // TODO(scheglov): implement for propagated types |
| 4332 return null; | 4309 return null; |
| 4333 } | 4310 } |
| 4334 } | 4311 } |
| OLD | NEW |