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

Side by Side Diff: pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart

Issue 2948773002: Rename "field" -> "accessor" in several type inference methods. (Closed)
Patch Set: Created 3 years, 6 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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 import 'package:front_end/src/base/instrumentation.dart'; 5 import 'package:front_end/src/base/instrumentation.dart';
6 import 'package:front_end/src/dependency_walker.dart' as dependencyWalker; 6 import 'package:front_end/src/dependency_walker.dart' as dependencyWalker;
7 import 'package:front_end/src/fasta/errors.dart'; 7 import 'package:front_end/src/fasta/errors.dart';
8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; 8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
9 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart' ; 9 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart' ;
10 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'; 10 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
11 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart' ; 11 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart' ;
12 import 'package:kernel/ast.dart' 12 import 'package:kernel/ast.dart'
13 show Class, DartType, DynamicType, Field, InterfaceType, Member, Procedure; 13 show Class, DartType, DynamicType, Field, InterfaceType, Member, Procedure;
14 import 'package:kernel/class_hierarchy.dart'; 14 import 'package:kernel/class_hierarchy.dart';
15 import 'package:kernel/core_types.dart'; 15 import 'package:kernel/core_types.dart';
16 import 'package:kernel/type_algebra.dart'; 16 import 'package:kernel/type_algebra.dart';
17 17
18 /// Data structure for tracking dependencies among fields, getters, and setters 18 /// Data structure for tracking dependencies among fields, getters, and setters
19 /// that require type inference. 19 /// that require type inference.
20 /// 20 ///
21 /// TODO(paulberry): see if it's possible to make this class more lightweight 21 /// TODO(paulberry): see if it's possible to make this class more lightweight
22 /// by changing the API so that the walker is passed to computeDependencies(). 22 /// by changing the API so that the walker is passed to computeDependencies().
23 /// (This should allow us to drop the _typeInferenceEngine field). 23 /// (This should allow us to drop the _typeInferenceEngine field).
24 class FieldNode extends dependencyWalker.Node<FieldNode> { 24 class AccessorNode extends dependencyWalker.Node<AccessorNode> {
25 final TypeInferenceEngineImpl _typeInferenceEngine; 25 final TypeInferenceEngineImpl _typeInferenceEngine;
26 26
27 final KernelMember member; 27 final KernelMember member;
28 28
29 bool isImmediatelyEvident = false; 29 bool isImmediatelyEvident = false;
30 30
31 FieldState state = FieldState.NotInferredYet; 31 AccessorState state = AccessorState.NotInferredYet;
32 32
33 /// If [state] is [FieldState.Inferring], and type inference for this field 33 /// If [state] is [AccessorState.Inferring], and type inference for this
34 /// is waiting on type inference of some other field, the field that is being 34 /// accessor is waiting on type inference of some other accessor, the accessor
35 /// waited on. 35 /// that is being waited on.
36 /// 36 ///
37 /// Otherwise `null`. 37 /// Otherwise `null`.
38 FieldNode currentDependency; 38 AccessorNode currentDependency;
39 39
40 final overrides = <Member>[]; 40 final overrides = <Member>[];
41 41
42 FieldNode(this._typeInferenceEngine, this.member); 42 AccessorNode(this._typeInferenceEngine, this.member);
43 43
44 @override 44 @override
45 bool get isEvaluated => state == FieldState.Inferred; 45 bool get isEvaluated => state == AccessorState.Inferred;
46 46
47 @override 47 @override
48 List<FieldNode> computeDependencies() { 48 List<AccessorNode> computeDependencies() {
49 return _typeInferenceEngine.computeFieldDependencies(this); 49 return _typeInferenceEngine.computeAccessorDependencies(this);
50 } 50 }
51 51
52 @override 52 @override
53 String toString() => member.toString(); 53 String toString() => member.toString();
54 } 54 }
55 55
56 /// Enum tracking the type inference state of a field. 56 /// Enum tracking the type inference state of an accessor.
57 enum FieldState { 57 enum AccessorState {
58 /// The field's type has not been inferred yet. 58 /// The accessor's type has not been inferred yet.
59 NotInferredYet, 59 NotInferredYet,
60 60
61 /// Type inference is in progress for the field. 61 /// Type inference is in progress for the accessor.
62 /// 62 ///
63 /// This means that code is currently on the stack which is attempting to 63 /// This means that code is currently on the stack which is attempting to
64 /// determine the type of the field. 64 /// determine the type of the accessor.
65 Inferring, 65 Inferring,
66 66
67 /// The field's type has been inferred. 67 /// The accessor's type has been inferred.
68 Inferred 68 Inferred
69 } 69 }
70 70
71 /// Keeps track of the global state for the type inference that occurs outside 71 /// Keeps track of the global state for the type inference that occurs outside
72 /// of method bodies and initalizers. 72 /// of method bodies and initalizers.
73 /// 73 ///
74 /// This class describes the interface for use by clients of type inference 74 /// This class describes the interface for use by clients of type inference
75 /// (e.g. DietListener). Derived classes should derive from 75 /// (e.g. DietListener). Derived classes should derive from
76 /// [TypeInferenceEngineImpl]. 76 /// [TypeInferenceEngineImpl].
77 abstract class TypeInferenceEngine { 77 abstract class TypeInferenceEngine {
78 ClassHierarchy get classHierarchy; 78 ClassHierarchy get classHierarchy;
79 79
80 CoreTypes get coreTypes; 80 CoreTypes get coreTypes;
81 81
82 /// Creates a type inferrer for use inside of a method body declared in a file 82 /// Creates a type inferrer for use inside of a method body declared in a file
83 /// with the given [uri]. 83 /// with the given [uri].
84 TypeInferrer createLocalTypeInferrer( 84 TypeInferrer createLocalTypeInferrer(
85 Uri uri, TypeInferenceListener listener, InterfaceType thisType); 85 Uri uri, TypeInferenceListener listener, InterfaceType thisType);
86 86
87 /// Creates a [TypeInferrer] object which is ready to perform type inference 87 /// Creates a [TypeInferrer] object which is ready to perform type inference
88 /// on the given [field]. 88 /// on the given [field].
89 TypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener, 89 TypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener,
90 InterfaceType thisType, KernelMember member); 90 InterfaceType thisType, KernelMember member);
91 91
92 /// Performs the second phase of top level initializer inference, which is to 92 /// Performs the second phase of top level initializer inference, which is to
93 /// visit all fields and top level variables that were passed to [recordField] 93 /// visit all accessors and top level variables that were passed to
94 /// in topologically-sorted order and assign their types. 94 /// [recordAccessor] in topologically-sorted order and assign their types.
95 void finishTopLevel(); 95 void finishTopLevel();
96 96
97 /// Gets ready to do top level type inference for the program having the given 97 /// Gets ready to do top level type inference for the program having the given
98 /// [hierarchy], using the given [coreTypes]. 98 /// [hierarchy], using the given [coreTypes].
99 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy); 99 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy);
100 100
101 /// Records that the given initializing [formal] will need top level type 101 /// Records that the given initializing [formal] will need top level type
102 /// inference. 102 /// inference.
103 void recordInitializingFormal(KernelVariableDeclaration formal); 103 void recordInitializingFormal(KernelVariableDeclaration formal);
104 104
(...skipping 28 matching lines...) Expand all
133 /// field's inferred type to depend on the type of an instance field (provided 133 /// field's inferred type to depend on the type of an instance field (provided
134 /// there are no circular dependencies). 134 /// there are no circular dependencies).
135 /// 135 ///
136 /// Requires [fusedTopLevelInference] to be `true`. 136 /// Requires [fusedTopLevelInference] to be `true`.
137 static const bool fullTopLevelInference = true; 137 static const bool fullTopLevelInference = true;
138 138
139 final Instrumentation instrumentation; 139 final Instrumentation instrumentation;
140 140
141 final bool strongMode; 141 final bool strongMode;
142 142
143 final fieldNodes = <FieldNode>[]; 143 final accessorNodes = <AccessorNode>[];
144 144
145 final initializingFormals = <KernelVariableDeclaration>[]; 145 final initializingFormals = <KernelVariableDeclaration>[];
146 146
147 @override 147 @override
148 CoreTypes coreTypes; 148 CoreTypes coreTypes;
149 149
150 @override 150 @override
151 ClassHierarchy classHierarchy; 151 ClassHierarchy classHierarchy;
152 152
153 TypeSchemaEnvironment typeSchemaEnvironment; 153 TypeSchemaEnvironment typeSchemaEnvironment;
154 154
155 TypeInferenceEngineImpl(this.instrumentation, this.strongMode); 155 TypeInferenceEngineImpl(this.instrumentation, this.strongMode);
156 156
157 /// Computes type inference dependencies for the given [field]. 157 /// Computes type inference dependencies for the given [accessorNode].
158 List<FieldNode> computeFieldDependencies(FieldNode fieldNode) { 158 List<AccessorNode> computeAccessorDependencies(AccessorNode accessorNode) {
159 // If the field's type is going to be determined by inheritance, then its 159 // If the accessor's type is going to be determined by inheritance, then its
160 // dependencies are determined by inheritance too. 160 // dependencies are determined by inheritance too.
161 if (fieldNode.overrides.isNotEmpty) { 161 if (accessorNode.overrides.isNotEmpty) {
162 var dependencies = <FieldNode>[]; 162 var dependencies = <AccessorNode>[];
163 for (var override in fieldNode.overrides) { 163 for (var override in accessorNode.overrides) {
164 // TODO(paulberry): support dependencies on getters/setters too. 164 // TODO(paulberry): support dependencies on getters/setters too.
165 var dep = KernelMember.getFieldNode(override); 165 var dep = KernelMember.getAccessorNode(override);
166 if (dep != null) dependencies.add(dep); 166 if (dep != null) dependencies.add(dep);
167 } 167 }
168 fieldNode.isImmediatelyEvident = true; 168 accessorNode.isImmediatelyEvident = true;
169 return dependencies; 169 return dependencies;
170 } 170 }
171 171
172 // Otherwise its dependencies are based on the initializer expression. 172 // Otherwise its dependencies are based on the initializer expression.
173 var member = fieldNode.member; 173 var member = accessorNode.member;
174 if (member is KernelField) { 174 if (member is KernelField) {
175 if (expandedTopLevelInference) { 175 if (expandedTopLevelInference) {
176 // In expanded top level inference, we determine the dependencies by 176 // In expanded top level inference, we determine the dependencies by
177 // doing a "dry run" of top level inference and recording which static 177 // doing a "dry run" of top level inference and recording which static
178 // fields were accessed. 178 // fields were accessed.
179 var typeInferrer = getFieldTypeInferrer(member); 179 var typeInferrer = getMemberTypeInferrer(member);
180 if (typeInferrer == null) { 180 if (typeInferrer == null) {
181 // This can happen when there are errors in the field declaration. 181 // This can happen when there are errors in the field declaration.
182 return const []; 182 return const [];
183 } else { 183 } else {
184 typeInferrer.startDryRun(); 184 typeInferrer.startDryRun();
185 typeInferrer.listener.dryRunEnter(member.initializer); 185 typeInferrer.listener.dryRunEnter(member.initializer);
186 typeInferrer.inferFieldTopLevel(member, null, true); 186 typeInferrer.inferFieldTopLevel(member, null, true);
187 typeInferrer.listener.dryRunExit(member.initializer); 187 typeInferrer.listener.dryRunExit(member.initializer);
188 fieldNode.isImmediatelyEvident = true; 188 accessorNode.isImmediatelyEvident = true;
189 return typeInferrer.finishDryRun(); 189 return typeInferrer.finishDryRun();
190 } 190 }
191 } else { 191 } else {
192 // In non-expanded top level inference, we determine the dependencies by 192 // In non-expanded top level inference, we determine the dependencies by
193 // calling `collectDependencies`; as a side effect this flags any 193 // calling `collectDependencies`; as a side effect this flags any
194 // expressions that are not "immediately evident". 194 // expressions that are not "immediately evident".
195 // TODO(paulberry): get rid of this mode once we are sure we no longer 195 // TODO(paulberry): get rid of this mode once we are sure we no longer
196 // need it. 196 // need it.
197 var collector = new KernelDependencyCollector(); 197 var collector = new KernelDependencyCollector();
198 collector.collectDependencies(member.initializer); 198 collector.collectDependencies(member.initializer);
199 fieldNode.isImmediatelyEvident = collector.isImmediatelyEvident; 199 accessorNode.isImmediatelyEvident = collector.isImmediatelyEvident;
200 return collector.dependencies; 200 return collector.dependencies;
201 } 201 }
202 } else { 202 } else {
203 // Member is a getter/setter that doesn't override anything, so we can't 203 // Member is a getter/setter that doesn't override anything, so we can't
204 // infer a type for it; therefore it has no dependencies. 204 // infer a type for it; therefore it has no dependencies.
205 return const []; 205 return const [];
206 } 206 }
207 } 207 }
208 208
209 /// Creates a [FieldNode] to track dependencies of the given [field]. 209 /// Creates an [AccessorNode] to track dependencies of the given [member].
210 FieldNode createFieldNode(KernelField field); 210 AccessorNode createAccessorNode(KernelMember member);
211 211
212 @override 212 @override
213 void finishTopLevel() { 213 void finishTopLevel() {
214 for (var fieldNode in fieldNodes) { 214 for (var accessorNode in accessorNodes) {
215 if (fusedTopLevelInference) { 215 if (fusedTopLevelInference) {
216 assert(expandedTopLevelInference); 216 assert(expandedTopLevelInference);
217 inferFieldFused(fieldNode, null); 217 inferAccessorFused(accessorNode, null);
218 } else { 218 } else {
219 if (fieldNode.isEvaluated) continue; 219 if (accessorNode.isEvaluated) continue;
220 new _FieldWalker().walk(fieldNode); 220 new _AccessorWalker().walk(accessorNode);
221 } 221 }
222 } 222 }
223 for (var formal in initializingFormals) { 223 for (var formal in initializingFormals) {
224 formal.type = _inferInitializingFormalType(formal); 224 formal.type = _inferInitializingFormalType(formal);
225 } 225 }
226 } 226 }
227 227
228 /// Retrieve the [TypeInferrer] for the given [member], which was created by 228 /// Retrieve the [TypeInferrer] for the given [member], which was created by
229 /// a previous call to [createTopLevelTypeInferrer]. 229 /// a previous call to [createTopLevelTypeInferrer].
230 TypeInferrerImpl getFieldTypeInferrer(KernelMember member); 230 TypeInferrerImpl getMemberTypeInferrer(KernelMember member);
231 231
232 /// Performs type inference on the given [field]. 232 /// Performs type inference on the given [accessorNode].
233 void inferField(FieldNode fieldNode) { 233 void inferAccessor(AccessorNode accessorNode) {
234 assert(fieldNode.state == FieldState.NotInferredYet); 234 assert(accessorNode.state == AccessorState.NotInferredYet);
235 fieldNode.state = FieldState.Inferring; 235 accessorNode.state = AccessorState.Inferring;
236 var member = fieldNode.member; 236 var member = accessorNode.member;
237 if (strongMode) { 237 if (strongMode) {
238 var inferredType = tryInferFieldByInheritance(fieldNode); 238 var inferredType = tryInferAccessorByInheritance(accessorNode);
239 var typeInferrer = getFieldTypeInferrer(member); 239 var typeInferrer = getMemberTypeInferrer(member);
240 if (inferredType == null) { 240 if (inferredType == null) {
241 if (member is KernelField) { 241 if (member is KernelField) {
242 typeInferrer.isImmediatelyEvident = true; 242 typeInferrer.isImmediatelyEvident = true;
243 inferredType = fieldNode.isImmediatelyEvident 243 inferredType = accessorNode.isImmediatelyEvident
244 ? typeInferrer.inferDeclarationType( 244 ? typeInferrer.inferDeclarationType(
245 typeInferrer.inferFieldTopLevel(member, null, true)) 245 typeInferrer.inferFieldTopLevel(member, null, true))
246 : const DynamicType(); 246 : const DynamicType();
247 if (!typeInferrer.isImmediatelyEvident) { 247 if (!typeInferrer.isImmediatelyEvident) {
248 inferredType = const DynamicType(); 248 inferredType = const DynamicType();
249 } 249 }
250 } else { 250 } else {
251 inferredType = const DynamicType(); 251 inferredType = const DynamicType();
252 } 252 }
253 } 253 }
254 if (fieldNode.state == FieldState.Inferred) { 254 if (accessorNode.state == AccessorState.Inferred) {
255 // A circularity must have been detected; at the time it was detected, 255 // A circularity must have been detected; at the time it was detected,
256 // inference for this node was completed. 256 // inference for this node was completed.
257 return; 257 return;
258 } 258 }
259 member.setInferredType(this, typeInferrer.uri, inferredType); 259 member.setInferredType(this, typeInferrer.uri, inferredType);
260 } 260 }
261 fieldNode.state = FieldState.Inferred; 261 accessorNode.state = AccessorState.Inferred;
262 // TODO(paulberry): if type != null, then check that the type of the 262 // TODO(paulberry): if type != null, then check that the type of the
263 // initializer is assignable to it. 263 // initializer is assignable to it.
264 // TODO(paulberry): the following is a hack so that outlines don't contain 264 // TODO(paulberry): the following is a hack so that outlines don't contain
265 // initializers. But it means that we rebuild the initializers when doing 265 // initializers. But it means that we rebuild the initializers when doing
266 // a full compile. There should be a better way. 266 // a full compile. There should be a better way.
267 if (member is KernelField) { 267 if (member is KernelField) {
268 member.initializer = null; 268 member.initializer = null;
269 } 269 }
270 } 270 }
271 271
272 /// Makes a note that the given [field] is part of a circularity, so its type 272 /// Makes a note that the given [accessorNode] is part of a circularity, so
273 /// can't be inferred. 273 /// its type can't be inferred.
274 void inferFieldCircular(FieldNode fieldNode) { 274 void inferAccessorCircular(AccessorNode accessorNode) {
275 var member = fieldNode.member; 275 var member = accessorNode.member;
276 // TODO(paulberry): report the appropriate error. 276 // TODO(paulberry): report the appropriate error.
277 var uri = getFieldTypeInferrer(member).uri; 277 var uri = getMemberTypeInferrer(member).uri;
278 fieldNode.state = FieldState.Inferred; 278 accessorNode.state = AccessorState.Inferred;
279 member.setInferredType(this, uri, const DynamicType()); 279 member.setInferredType(this, uri, const DynamicType());
280 // TODO(paulberry): the following is a hack so that outlines don't contain 280 // TODO(paulberry): the following is a hack so that outlines don't contain
281 // initializers. But it means that we rebuild the initializers when doing 281 // initializers. But it means that we rebuild the initializers when doing
282 // a full compile. There should be a better way. 282 // a full compile. There should be a better way.
283 if (member is KernelField) { 283 if (member is KernelField) {
284 member.initializer = null; 284 member.initializer = null;
285 } 285 }
286 } 286 }
287 287
288 /// Performs fused type inference on the given [field]. 288 /// Performs fused type inference on the given [accessorNode].
289 void inferFieldFused(FieldNode fieldNode, FieldNode dependant) { 289 void inferAccessorFused(AccessorNode accessorNode, AccessorNode dependant) {
290 switch (fieldNode.state) { 290 switch (accessorNode.state) {
291 case FieldState.Inferred: 291 case AccessorState.Inferred:
292 // Already inferred. Nothing to do. 292 // Already inferred. Nothing to do.
293 break; 293 break;
294 case FieldState.Inferring: 294 case AccessorState.Inferring:
295 // A field depends on itself (possibly by way of intermediate fields). 295 // An accessor depends on itself (possibly by way of intermediate
296 // Mark all fields involved as circular and infer a type of `dynamic` 296 // accessors). Mark all accessors involved as circular and infer a type
297 // for them. 297 // of `dynamic` for them.
298 var node = fieldNode; 298 var node = accessorNode;
299 while (node != null) { 299 while (node != null) {
300 var nextNode = node.currentDependency; 300 var nextNode = node.currentDependency;
301 inferFieldCircular(node); 301 inferAccessorCircular(node);
302 node.currentDependency = null; 302 node.currentDependency = null;
303 node = nextNode; 303 node = nextNode;
304 } 304 }
305 break; 305 break;
306 case FieldState.NotInferredYet: 306 case AccessorState.NotInferredYet:
307 // Mark the "dependant" field (if any) as depending on this one, and 307 // Mark the "dependant" accessor (if any) as depending on this one, and
308 // invoke field inference for this node. 308 // invoke accessor inference for this node.
309 dependant?.currentDependency = fieldNode; 309 dependant?.currentDependency = accessorNode;
310 // All fields are "immediately evident" when doing fused inference. 310 // All accessors are "immediately evident" when doing fused inference.
311 fieldNode.isImmediatelyEvident = true; 311 accessorNode.isImmediatelyEvident = true;
312 inferField(fieldNode); 312 inferAccessor(accessorNode);
313 dependant?.currentDependency = null; 313 dependant?.currentDependency = null;
314 break; 314 break;
315 } 315 }
316 } 316 }
317 317
318 @override 318 @override
319 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) { 319 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) {
320 this.coreTypes = coreTypes; 320 this.coreTypes = coreTypes;
321 this.classHierarchy = hierarchy; 321 this.classHierarchy = hierarchy;
322 this.typeSchemaEnvironment = 322 this.typeSchemaEnvironment =
323 new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode); 323 new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode);
324 } 324 }
325 325
326 @override 326 @override
327 void recordInitializingFormal(KernelVariableDeclaration formal) { 327 void recordInitializingFormal(KernelVariableDeclaration formal) {
328 initializingFormals.add(formal); 328 initializingFormals.add(formal);
329 } 329 }
330 330
331 @override 331 @override
332 void recordMember(KernelMember member) { 332 void recordMember(KernelMember member) {
333 fieldNodes.add(createFieldNode(member)); 333 accessorNodes.add(createAccessorNode(member));
334 } 334 }
335 335
336 DartType tryInferFieldByInheritance(FieldNode fieldNode) { 336 DartType tryInferAccessorByInheritance(AccessorNode accessorNode) {
337 DartType inferredType; 337 DartType inferredType;
338 for (var override in fieldNode.overrides) { 338 for (var override in accessorNode.overrides) {
339 var nextInferredType = _computeOverriddenFieldType(override, fieldNode); 339 var nextInferredType =
340 _computeOverriddenAccessorType(override, accessorNode);
340 if (inferredType == null) { 341 if (inferredType == null) {
341 inferredType = nextInferredType; 342 inferredType = nextInferredType;
342 } else if (inferredType != nextInferredType) { 343 } else if (inferredType != nextInferredType) {
343 // Overrides don't have matching types. 344 // Overrides don't have matching types.
344 // TODO(paulberry): report an error 345 // TODO(paulberry): report an error
345 return const DynamicType(); 346 return const DynamicType();
346 } 347 }
347 } 348 }
348 return inferredType; 349 return inferredType;
349 } 350 }
350 351
351 DartType _computeOverriddenFieldType(Member override, FieldNode fieldNode) { 352 DartType _computeOverriddenAccessorType(
353 Member override, AccessorNode accessorNode) {
352 if (fusedTopLevelInference) { 354 if (fusedTopLevelInference) {
353 FieldNode dependency = KernelMember.getFieldNode(override); 355 AccessorNode dependency = KernelMember.getAccessorNode(override);
354 if (dependency != null) { 356 if (dependency != null) {
355 inferFieldFused(dependency, fieldNode); 357 inferAccessorFused(dependency, accessorNode);
356 } 358 }
357 } 359 }
358 DartType overriddenType; 360 DartType overriddenType;
359 if (override is Field) { 361 if (override is Field) {
360 overriddenType = override.type; 362 overriddenType = override.type;
361 } else if (override is Procedure) { 363 } else if (override is Procedure) {
362 // TODO(paulberry): handle the case where override needs its type 364 // TODO(paulberry): handle the case where override needs its type
363 // inferred first. 365 // inferred first.
364 if (override.isGetter) { 366 if (override.isGetter) {
365 overriddenType = override.getterType; 367 overriddenType = override.getterType;
366 } else { 368 } else {
367 overriddenType = override.setterType; 369 overriddenType = override.setterType;
368 } 370 }
369 } else { 371 } else {
370 throw internalError( 372 throw internalError(
371 'Unexpected overridden member type: ${override.runtimeType}'); 373 'Unexpected overridden member type: ${override.runtimeType}');
372 } 374 }
373 var superclass = override.enclosingClass; 375 var superclass = override.enclosingClass;
374 if (superclass.typeParameters.isEmpty) return overriddenType; 376 if (superclass.typeParameters.isEmpty) return overriddenType;
375 var thisClass = fieldNode.member.enclosingClass; 377 var thisClass = accessorNode.member.enclosingClass;
376 var superclassInstantiation = classHierarchy 378 var superclassInstantiation = classHierarchy
377 .getClassAsInstanceOf(thisClass, superclass) 379 .getClassAsInstanceOf(thisClass, superclass)
378 .asInterfaceType; 380 .asInterfaceType;
379 return Substitution 381 return Substitution
380 .fromInterfaceType(superclassInstantiation) 382 .fromInterfaceType(superclassInstantiation)
381 .substituteType(overriddenType); 383 .substituteType(overriddenType);
382 } 384 }
383 385
384 DartType _inferInitializingFormalType(KernelVariableDeclaration formal) { 386 DartType _inferInitializingFormalType(KernelVariableDeclaration formal) {
385 assert(KernelVariableDeclaration.isImplicitlyTyped(formal)); 387 assert(KernelVariableDeclaration.isImplicitlyTyped(formal));
386 Class enclosingClass = formal.parent.parent.parent; 388 Class enclosingClass = formal.parent.parent.parent;
387 for (var field in enclosingClass.fields) { 389 for (var field in enclosingClass.fields) {
388 if (field.name.name == formal.name) { 390 if (field.name.name == formal.name) {
389 return field.type; 391 return field.type;
390 } 392 }
391 } 393 }
392 // No matching field. The error should be reported elsewhere. 394 // No matching field. The error should be reported elsewhere.
393 return const DynamicType(); 395 return const DynamicType();
394 } 396 }
395 } 397 }
396 398
397 /// Subtype of [dependencyWalker.DependencyWalker] which is specialized to 399 /// Subtype of [dependencyWalker.DependencyWalker] which is specialized to
398 /// perform top level type inference. 400 /// perform top level type inference.
399 class _FieldWalker extends dependencyWalker.DependencyWalker<FieldNode> { 401 class _AccessorWalker extends dependencyWalker.DependencyWalker<AccessorNode> {
400 _FieldWalker(); 402 _AccessorWalker();
401 403
402 @override 404 @override
403 void evaluate(FieldNode f) { 405 void evaluate(AccessorNode f) {
404 f._typeInferenceEngine.inferField(f); 406 f._typeInferenceEngine.inferAccessor(f);
405 } 407 }
406 408
407 @override 409 @override
408 void evaluateScc(List<FieldNode> scc) { 410 void evaluateScc(List<AccessorNode> scc) {
409 // Mark every field as part of a circularity. 411 // Mark every accessor as part of a circularity.
410 for (var f in scc) { 412 for (var f in scc) {
411 f._typeInferenceEngine.inferFieldCircular(f); 413 f._typeInferenceEngine.inferAccessorCircular(f);
412 } 414 }
413 } 415 }
414 } 416 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698