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

Side by Side Diff: pkg/compiler/lib/src/typechecker.dart

Issue 2603263002: Prefix resolution_types with Resolution. (Closed)
Patch Set: Rebased Created 3 years, 11 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 library dart2js.typechecker; 5 library dart2js.typechecker;
6 6
7 import 'common/names.dart' show Identifiers; 7 import 'common/names.dart' show Identifiers;
8 import 'common/resolution.dart' show Resolution; 8 import 'common/resolution.dart' show Resolution;
9 import 'common/tasks.dart' show CompilerTask; 9 import 'common/tasks.dart' show CompilerTask;
10 import 'common.dart'; 10 import 'common.dart';
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 void check(AstElement element) { 57 void check(AstElement element) {
58 if (element.isClass) return; 58 if (element.isClass) return;
59 if (element.isTypedef) return; 59 if (element.isTypedef) return;
60 ResolvedAst resolvedAst = element.resolvedAst; 60 ResolvedAst resolvedAst = element.resolvedAst;
61 reporter.withCurrentElement(element.implementation, () { 61 reporter.withCurrentElement(element.implementation, () {
62 measure(() { 62 measure(() {
63 TypeCheckerVisitor visitor = new TypeCheckerVisitor( 63 TypeCheckerVisitor visitor = new TypeCheckerVisitor(
64 compiler, resolvedAst.elements, compiler.types); 64 compiler, resolvedAst.elements, compiler.types);
65 if (element.isField) { 65 if (element.isField) {
66 visitor.analyzingInitializer = true; 66 visitor.analyzingInitializer = true;
67 DartType type = 67 ResolutionDartType type =
68 visitor.analyzeVariableTypeAnnotation(resolvedAst.node); 68 visitor.analyzeVariableTypeAnnotation(resolvedAst.node);
69 visitor.analyzeVariableInitializer(element, type, resolvedAst.body); 69 visitor.analyzeVariableInitializer(element, type, resolvedAst.body);
70 } else { 70 } else {
71 resolvedAst.node.accept(visitor); 71 resolvedAst.node.accept(visitor);
72 } 72 }
73 }); 73 });
74 }); 74 });
75 } 75 }
76 } 76 }
77 77
(...skipping 15 matching lines...) Expand all
93 93
94 /** 94 /**
95 * [ElementAccess] represents the access of [element], either as a property 95 * [ElementAccess] represents the access of [element], either as a property
96 * access or invocation. 96 * access or invocation.
97 */ 97 */
98 abstract class ElementAccess { 98 abstract class ElementAccess {
99 Element get element; 99 Element get element;
100 100
101 String get name => element.name; 101 String get name => element.name;
102 102
103 DartType computeType(Resolution resolution); 103 ResolutionDartType computeType(Resolution resolution);
104 104
105 /// Returns [: true :] if the element can be access as an invocation. 105 /// Returns [: true :] if the element can be access as an invocation.
106 bool isCallable(Compiler compiler) { 106 bool isCallable(Compiler compiler) {
107 if (element != null && element.isAbstractField) { 107 if (element != null && element.isAbstractField) {
108 AbstractFieldElement abstractFieldElement = element; 108 AbstractFieldElement abstractFieldElement = element;
109 if (abstractFieldElement.getter == null) { 109 if (abstractFieldElement.getter == null) {
110 // Setters cannot be invoked as function invocations. 110 // Setters cannot be invoked as function invocations.
111 return false; 111 return false;
112 } 112 }
113 } 113 }
114 return compiler.types.isAssignable( 114 return compiler.types.isAssignable(
115 computeType(compiler.resolution), compiler.commonElements.functionType); 115 computeType(compiler.resolution), compiler.commonElements.functionType);
116 } 116 }
117 } 117 }
118 118
119 /// An access of a instance member. 119 /// An access of a instance member.
120 class MemberAccess extends ElementAccess { 120 class MemberAccess extends ElementAccess {
121 final MemberSignature member; 121 final MemberSignature member;
122 122
123 MemberAccess(MemberSignature this.member); 123 MemberAccess(MemberSignature this.member);
124 124
125 Element get element => member.declarations.first.element; 125 Element get element => member.declarations.first.element;
126 126
127 DartType computeType(Resolution resolution) => member.type; 127 ResolutionDartType computeType(Resolution resolution) => member.type;
128 128
129 String toString() => 'MemberAccess($member)'; 129 String toString() => 'MemberAccess($member)';
130 } 130 }
131 131
132 /// An access of an unresolved element. 132 /// An access of an unresolved element.
133 class DynamicAccess implements ElementAccess { 133 class DynamicAccess implements ElementAccess {
134 const DynamicAccess(); 134 const DynamicAccess();
135 135
136 Element get element => null; 136 Element get element => null;
137 137
138 String get name => 'dynamic'; 138 String get name => 'dynamic';
139 139
140 DartType computeType(Resolution resolution) => const DynamicType(); 140 ResolutionDartType computeType(Resolution resolution) =>
141 const ResolutionDynamicType();
141 142
142 bool isCallable(Compiler compiler) => true; 143 bool isCallable(Compiler compiler) => true;
143 144
144 String toString() => 'DynamicAccess'; 145 String toString() => 'DynamicAccess';
145 } 146 }
146 147
147 /** 148 /**
148 * An access of a resolved top-level or static property or function, or an 149 * An access of a resolved top-level or static property or function, or an
149 * access of a resolved element through [:this:]. 150 * access of a resolved element through [:this:].
150 */ 151 */
151 class ResolvedAccess extends ElementAccess { 152 class ResolvedAccess extends ElementAccess {
152 final Element element; 153 final Element element;
153 154
154 ResolvedAccess(Element this.element) { 155 ResolvedAccess(Element this.element) {
155 assert(element != null); 156 assert(element != null);
156 } 157 }
157 158
158 DartType computeType(Resolution resolution) { 159 ResolutionDartType computeType(Resolution resolution) {
159 if (element.isGetter) { 160 if (element.isGetter) {
160 GetterElement getter = element; 161 GetterElement getter = element;
161 FunctionType functionType = getter.computeType(resolution); 162 ResolutionFunctionType functionType = getter.computeType(resolution);
162 return functionType.returnType; 163 return functionType.returnType;
163 } else if (element.isSetter) { 164 } else if (element.isSetter) {
164 SetterElement setter = element; 165 SetterElement setter = element;
165 FunctionType functionType = setter.computeType(resolution); 166 ResolutionFunctionType functionType = setter.computeType(resolution);
166 if (functionType.parameterTypes.length != 1) { 167 if (functionType.parameterTypes.length != 1) {
167 // TODO(johnniwinther,karlklose): this happens for malformed static 168 // TODO(johnniwinther,karlklose): this happens for malformed static
168 // setters. Treat them the same as instance members. 169 // setters. Treat them the same as instance members.
169 return const DynamicType(); 170 return const ResolutionDynamicType();
170 } 171 }
171 return functionType.parameterTypes.first; 172 return functionType.parameterTypes.first;
172 } else if (element.isTypedef || element.isClass) { 173 } else if (element.isTypedef || element.isClass) {
173 TypeDeclarationElement typeDeclaration = element; 174 TypeDeclarationElement typeDeclaration = element;
174 typeDeclaration.computeType(resolution); 175 typeDeclaration.computeType(resolution);
175 return typeDeclaration.thisType; 176 return typeDeclaration.thisType;
176 } else { 177 } else {
177 TypedElement typedElement = element; 178 TypedElement typedElement = element;
178 typedElement.computeType(resolution); 179 typedElement.computeType(resolution);
179 return typedElement.type; 180 return typedElement.type;
180 } 181 }
181 } 182 }
182 183
183 String toString() => 'ResolvedAccess($element)'; 184 String toString() => 'ResolvedAccess($element)';
184 } 185 }
185 186
186 /// An access to a promoted variable. 187 /// An access to a promoted variable.
187 class PromotedAccess extends ElementAccess { 188 class PromotedAccess extends ElementAccess {
188 final VariableElement element; 189 final VariableElement element;
189 final DartType type; 190 final ResolutionDartType type;
190 191
191 PromotedAccess(VariableElement this.element, DartType this.type) { 192 PromotedAccess(VariableElement this.element, ResolutionDartType this.type) {
192 assert(element != null); 193 assert(element != null);
193 assert(type != null); 194 assert(type != null);
194 } 195 }
195 196
196 DartType computeType(Resolution resolution) => type; 197 ResolutionDartType computeType(Resolution resolution) => type;
197 198
198 String toString() => 'PromotedAccess($element,$type)'; 199 String toString() => 'PromotedAccess($element,$type)';
199 } 200 }
200 201
201 /** 202 /**
202 * An access of a resolved top-level or static property or function, or an 203 * An access of a resolved top-level or static property or function, or an
203 * access of a resolved element through [:this:]. 204 * access of a resolved element through [:this:].
204 */ 205 */
205 class TypeAccess extends ElementAccess { 206 class TypeAccess extends ElementAccess {
206 final DartType type; 207 final ResolutionDartType type;
207 TypeAccess(DartType this.type) { 208 TypeAccess(ResolutionDartType this.type) {
208 assert(type != null); 209 assert(type != null);
209 } 210 }
210 211
211 Element get element => type.element; 212 Element get element => type.element;
212 213
213 DartType computeType(Resolution resolution) => type; 214 ResolutionDartType computeType(Resolution resolution) => type;
214 215
215 String toString() => 'TypeAccess($type)'; 216 String toString() => 'TypeAccess($type)';
216 } 217 }
217 218
218 /** 219 /**
219 * An access of a type literal. 220 * An access of a type literal.
220 */ 221 */
221 class TypeLiteralAccess extends ElementAccess { 222 class TypeLiteralAccess extends ElementAccess {
222 final DartType type; 223 final ResolutionDartType type;
223 224
224 TypeLiteralAccess(this.type) { 225 TypeLiteralAccess(this.type) {
225 assert(type != null); 226 assert(type != null);
226 } 227 }
227 228
228 Element get element => type.element; 229 Element get element => type.element;
229 230
230 String get name => type.name; 231 String get name => type.name;
231 232
232 DartType computeType(Resolution resolution) => 233 ResolutionDartType computeType(Resolution resolution) =>
233 resolution.commonElements.typeType; 234 resolution.commonElements.typeType;
234 235
235 String toString() => 'TypeLiteralAccess($type)'; 236 String toString() => 'TypeLiteralAccess($type)';
236 } 237 }
237 238
238 /// An access to the 'call' method of a function type. 239 /// An access to the 'call' method of a function type.
239 class FunctionCallAccess implements ElementAccess { 240 class FunctionCallAccess implements ElementAccess {
240 final Element element; 241 final Element element;
241 final DartType type; 242 final ResolutionDartType type;
242 243
243 const FunctionCallAccess(this.element, this.type); 244 const FunctionCallAccess(this.element, this.type);
244 245
245 String get name => 'call'; 246 String get name => 'call';
246 247
247 DartType computeType(Resolution resolution) => type; 248 ResolutionDartType computeType(Resolution resolution) => type;
248 249
249 bool isCallable(Compiler compiler) => true; 250 bool isCallable(Compiler compiler) => true;
250 251
251 String toString() => 'FunctionAccess($element, $type)'; 252 String toString() => 'FunctionAccess($element, $type)';
252 } 253 }
253 254
254 /// An is-expression that potentially promotes a variable. 255 /// An is-expression that potentially promotes a variable.
255 class TypePromotion { 256 class TypePromotion {
256 final Send node; 257 final Send node;
257 final VariableElement variable; 258 final VariableElement variable;
258 final DartType type; 259 final ResolutionDartType type;
259 final List<TypePromotionMessage> messages = <TypePromotionMessage>[]; 260 final List<TypePromotionMessage> messages = <TypePromotionMessage>[];
260 261
261 TypePromotion(this.node, this.variable, this.type); 262 TypePromotion(this.node, this.variable, this.type);
262 263
263 bool get isValid => messages.isEmpty; 264 bool get isValid => messages.isEmpty;
264 265
265 TypePromotion copy() { 266 TypePromotion copy() {
266 return new TypePromotion(node, variable, type)..messages.addAll(messages); 267 return new TypePromotion(node, variable, type)..messages.addAll(messages);
267 } 268 }
268 269
269 void addHint(DiagnosticMessage hint, 270 void addHint(DiagnosticMessage hint,
270 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { 271 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
271 messages.add(new TypePromotionMessage(hint, infos)); 272 messages.add(new TypePromotionMessage(hint, infos));
272 } 273 }
273 274
274 String toString() { 275 String toString() {
275 return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}'; 276 return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}';
276 } 277 }
277 } 278 }
278 279
279 /// A hint or info message attached to a type promotion. 280 /// A hint or info message attached to a type promotion.
280 class TypePromotionMessage { 281 class TypePromotionMessage {
281 DiagnosticMessage hint; 282 DiagnosticMessage hint;
282 List<DiagnosticMessage> infos; 283 List<DiagnosticMessage> infos;
283 284
284 TypePromotionMessage(this.hint, this.infos); 285 TypePromotionMessage(this.hint, this.infos);
285 } 286 }
286 287
287 class TypeCheckerVisitor extends Visitor<DartType> { 288 class TypeCheckerVisitor extends Visitor<ResolutionDartType> {
288 final Compiler compiler; 289 final Compiler compiler;
289 final TreeElements elements; 290 final TreeElements elements;
290 final Types types; 291 final Types types;
291 292
292 Node lastSeenNode; 293 Node lastSeenNode;
293 DartType expectedReturnType; 294 ResolutionDartType expectedReturnType;
294 AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; 295 AsyncMarker currentAsyncMarker = AsyncMarker.SYNC;
295 296
296 final ClassElement currentClass; 297 final ClassElement currentClass;
297 298
298 /// The immediately enclosing field, method or constructor being analyzed. 299 /// The immediately enclosing field, method or constructor being analyzed.
299 ExecutableElement executableContext; 300 ExecutableElement executableContext;
300 301
301 CommonElements get commonElements => compiler.commonElements; 302 CommonElements get commonElements => compiler.commonElements;
302 303
303 DiagnosticReporter get reporter => compiler.reporter; 304 DiagnosticReporter get reporter => compiler.reporter;
304 305
305 Resolution get resolution => compiler.resolution; 306 Resolution get resolution => compiler.resolution;
306 307
307 InterfaceType get intType => commonElements.intType; 308 ResolutionInterfaceType get intType => commonElements.intType;
308 InterfaceType get doubleType => commonElements.doubleType; 309 ResolutionInterfaceType get doubleType => commonElements.doubleType;
309 InterfaceType get boolType => commonElements.boolType; 310 ResolutionInterfaceType get boolType => commonElements.boolType;
310 InterfaceType get stringType => commonElements.stringType; 311 ResolutionInterfaceType get stringType => commonElements.stringType;
311 312
312 DartType thisType; 313 ResolutionDartType thisType;
313 DartType superType; 314 ResolutionDartType superType;
314 315
315 Link<DartType> cascadeTypes = const Link<DartType>(); 316 Link<ResolutionDartType> cascadeTypes = const Link<ResolutionDartType>();
316 317
317 bool analyzingInitializer = false; 318 bool analyzingInitializer = false;
318 319
319 Map<Node, List<TypePromotion>> shownTypePromotionsMap = 320 Map<Node, List<TypePromotion>> shownTypePromotionsMap =
320 new Map<Node, List<TypePromotion>>(); 321 new Map<Node, List<TypePromotion>>();
321 322
322 Map<VariableElement, Link<TypePromotion>> typePromotionsMap = 323 Map<VariableElement, Link<TypePromotion>> typePromotionsMap =
323 new Map<VariableElement, Link<TypePromotion>>(); 324 new Map<VariableElement, Link<TypePromotion>>();
324 325
325 Set<TypePromotion> reportedTypePromotions = new Set<TypePromotion>(); 326 Set<TypePromotion> reportedTypePromotions = new Set<TypePromotion>();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 TypePromotion typePromotion = promotions.head; 360 TypePromotion typePromotion = promotions.head;
360 if (typePromotion.isValid) { 361 if (typePromotion.isValid) {
361 return typePromotion; 362 return typePromotion;
362 } 363 }
363 promotions = promotions.tail; 364 promotions = promotions.tail;
364 } 365 }
365 } 366 }
366 return null; 367 return null;
367 } 368 }
368 369
369 DartType getKnownType(VariableElement element) { 370 ResolutionDartType getKnownType(VariableElement element) {
370 TypePromotion typePromotion = getKnownTypePromotion(element); 371 TypePromotion typePromotion = getKnownTypePromotion(element);
371 if (typePromotion != null) return typePromotion.type; 372 if (typePromotion != null) return typePromotion.type;
372 return element.type; 373 return element.type;
373 } 374 }
374 375
375 TypeCheckerVisitor(this.compiler, TreeElements elements, this.types) 376 TypeCheckerVisitor(this.compiler, TreeElements elements, this.types)
376 : this.elements = elements, 377 : this.elements = elements,
377 this.executableContext = elements.analyzedElement, 378 this.executableContext = elements.analyzedElement,
378 this.currentClass = elements.analyzedElement != null 379 this.currentClass = elements.analyzedElement != null
379 ? elements.analyzedElement.enclosingClass 380 ? elements.analyzedElement.enclosingClass
380 : null { 381 : null {
381 if (currentClass != null) { 382 if (currentClass != null) {
382 thisType = currentClass.thisType; 383 thisType = currentClass.thisType;
383 superType = currentClass.supertype; 384 superType = currentClass.supertype;
384 } else { 385 } else {
385 // If these are used, an error should have been reported by the resolver. 386 // If these are used, an error should have been reported by the resolver.
386 thisType = const DynamicType(); 387 thisType = const ResolutionDynamicType();
387 superType = const DynamicType(); 388 superType = const ResolutionDynamicType();
388 } 389 }
389 } 390 }
390 391
391 LibraryElement get currentLibrary => elements.analyzedElement.library; 392 LibraryElement get currentLibrary => elements.analyzedElement.library;
392 393
393 reportTypeWarning(Spannable spannable, MessageKind kind, 394 reportTypeWarning(Spannable spannable, MessageKind kind,
394 [Map arguments = const {}]) { 395 [Map arguments = const {}]) {
395 reporter.reportWarningMessage(spannable, kind, arguments); 396 reporter.reportWarningMessage(spannable, kind, arguments);
396 } 397 }
397 398
398 reportMessage(Spannable spannable, MessageKind kind, Map arguments, 399 reportMessage(Spannable spannable, MessageKind kind, Map arguments,
399 {bool isHint: false}) { 400 {bool isHint: false}) {
400 if (isHint) { 401 if (isHint) {
401 reporter.reportHintMessage(spannable, kind, arguments); 402 reporter.reportHintMessage(spannable, kind, arguments);
402 } else { 403 } else {
403 reporter.reportWarningMessage(spannable, kind, arguments); 404 reporter.reportWarningMessage(spannable, kind, arguments);
404 } 405 }
405 } 406 }
406 407
407 reportTypePromotionHint(TypePromotion typePromotion) { 408 reportTypePromotionHint(TypePromotion typePromotion) {
408 if (!reportedTypePromotions.contains(typePromotion)) { 409 if (!reportedTypePromotions.contains(typePromotion)) {
409 reportedTypePromotions.add(typePromotion); 410 reportedTypePromotions.add(typePromotion);
410 for (TypePromotionMessage message in typePromotion.messages) { 411 for (TypePromotionMessage message in typePromotion.messages) {
411 reporter.reportHint(message.hint, message.infos); 412 reporter.reportHint(message.hint, message.infos);
412 } 413 }
413 } 414 }
414 } 415 }
415 416
416 // TODO(karlklose): remove these functions. 417 // TODO(karlklose): remove these functions.
417 DartType unhandledExpression() => const DynamicType(); 418 ResolutionDartType unhandledExpression() => const ResolutionDynamicType();
418 419
419 DartType analyzeNonVoid(Node node) { 420 ResolutionDartType analyzeNonVoid(Node node) {
420 DartType type = analyze(node); 421 ResolutionDartType type = analyze(node);
421 if (type.isVoid) { 422 if (type.isVoid) {
422 reportTypeWarning(node, MessageKind.VOID_EXPRESSION); 423 reportTypeWarning(node, MessageKind.VOID_EXPRESSION);
423 } 424 }
424 return type; 425 return type;
425 } 426 }
426 427
427 DartType analyzeWithDefault(Node node, DartType defaultValue) { 428 ResolutionDartType analyzeWithDefault(
429 Node node, ResolutionDartType defaultValue) {
428 return node != null ? analyze(node) : defaultValue; 430 return node != null ? analyze(node) : defaultValue;
429 } 431 }
430 432
431 /// If [inInitializer] is true, assignment should be interpreted as write to 433 /// If [inInitializer] is true, assignment should be interpreted as write to
432 /// a field and not to a setter. 434 /// a field and not to a setter.
433 DartType analyze(Node node, 435 ResolutionDartType analyze(Node node,
434 {bool inInitializer: false, bool mustHaveType: true}) { 436 {bool inInitializer: false, bool mustHaveType: true}) {
435 if (node == null) { 437 if (node == null) {
436 final String error = 'Unexpected node: null'; 438 final String error = 'Unexpected node: null';
437 if (lastSeenNode != null) { 439 if (lastSeenNode != null) {
438 reporter.internalError(lastSeenNode, error); 440 reporter.internalError(lastSeenNode, error);
439 } else { 441 } else {
440 reporter.internalError(executableContext, error); 442 reporter.internalError(executableContext, error);
441 } 443 }
442 } else { 444 } else {
443 lastSeenNode = node; 445 lastSeenNode = node;
444 } 446 }
445 bool previouslyInitializer = analyzingInitializer; 447 bool previouslyInitializer = analyzingInitializer;
446 analyzingInitializer = inInitializer; 448 analyzingInitializer = inInitializer;
447 DartType result = node.accept(this); 449 ResolutionDartType result = node.accept(this);
448 analyzingInitializer = previouslyInitializer; 450 analyzingInitializer = previouslyInitializer;
449 if (result == null && mustHaveType) { 451 if (result == null && mustHaveType) {
450 reporter.internalError(node, 'Type is null.'); 452 reporter.internalError(node, 'Type is null.');
451 } 453 }
452 return result; 454 return result;
453 } 455 }
454 456
455 void analyzeUntyped(Node node, {bool inInitializer: false}) { 457 void analyzeUntyped(Node node, {bool inInitializer: false}) {
456 if (node != null) { 458 if (node != null) {
457 analyze(node, inInitializer: inInitializer, mustHaveType: false); 459 analyze(node, inInitializer: inInitializer, mustHaveType: false);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 } 532 }
531 533
532 for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) { 534 for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) {
533 typePromotion = typePromotion.copy(); 535 typePromotion = typePromotion.copy();
534 checkTypePromotion(right, typePromotion); 536 checkTypePromotion(right, typePromotion);
535 showTypePromotion(node, typePromotion); 537 showTypePromotion(node, typePromotion);
536 } 538 }
537 } 539 }
538 540
539 /// Analyze [node] in the context of the known types shown in [context]. 541 /// Analyze [node] in the context of the known types shown in [context].
540 DartType analyzeInPromotedContext(Node context, Node node, 542 ResolutionDartType analyzeInPromotedContext(Node context, Node node,
541 {bool mustHaveType: true}) { 543 {bool mustHaveType: true}) {
542 Link<TypePromotion> knownForNode = const Link<TypePromotion>(); 544 Link<TypePromotion> knownForNode = const Link<TypePromotion>();
543 for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) { 545 for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) {
544 typePromotion = typePromotion.copy(); 546 typePromotion = typePromotion.copy();
545 checkTypePromotion(node, typePromotion, checkAccesses: true); 547 checkTypePromotion(node, typePromotion, checkAccesses: true);
546 knownForNode = knownForNode.prepend(typePromotion); 548 knownForNode = knownForNode.prepend(typePromotion);
547 registerKnownTypePromotion(typePromotion); 549 registerKnownTypePromotion(typePromotion);
548 } 550 }
549 551
550 final DartType type = analyze(node, mustHaveType: mustHaveType); 552 final ResolutionDartType type = analyze(node, mustHaveType: mustHaveType);
551 553
552 while (!knownForNode.isEmpty) { 554 while (!knownForNode.isEmpty) {
553 unregisterKnownTypePromotion(knownForNode.head); 555 unregisterKnownTypePromotion(knownForNode.head);
554 knownForNode = knownForNode.tail; 556 knownForNode = knownForNode.tail;
555 } 557 }
556 558
557 return type; 559 return type;
558 } 560 }
559 561
560 /** 562 /**
561 * Check if a value of type [from] can be assigned to a variable, parameter or 563 * Check if a value of type [from] can be assigned to a variable, parameter or
562 * return value of type [to]. If `isConst == true`, an error is emitted in 564 * return value of type [to]. If `isConst == true`, an error is emitted in
563 * checked mode, otherwise a warning is issued. 565 * checked mode, otherwise a warning is issued.
564 */ 566 */
565 bool checkAssignable(Spannable spannable, DartType from, DartType to, 567 bool checkAssignable(
568 Spannable spannable, ResolutionDartType from, ResolutionDartType to,
566 {bool isConst: false}) { 569 {bool isConst: false}) {
567 if (!types.isAssignable(from, to)) { 570 if (!types.isAssignable(from, to)) {
568 if (compiler.options.enableTypeAssertions && isConst) { 571 if (compiler.options.enableTypeAssertions && isConst) {
569 reporter.reportErrorMessage(spannable, MessageKind.NOT_ASSIGNABLE, 572 reporter.reportErrorMessage(spannable, MessageKind.NOT_ASSIGNABLE,
570 {'fromType': from, 'toType': to}); 573 {'fromType': from, 'toType': to});
571 } else { 574 } else {
572 reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE, 575 reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE,
573 {'fromType': from, 'toType': to}); 576 {'fromType': from, 'toType': to});
574 } 577 }
575 return false; 578 return false;
576 } 579 }
577 return true; 580 return true;
578 } 581 }
579 582
580 checkCondition(Expression condition) { 583 checkCondition(Expression condition) {
581 checkAssignable(condition, analyze(condition), boolType); 584 checkAssignable(condition, analyze(condition), boolType);
582 } 585 }
583 586
584 void pushCascadeType(DartType type) { 587 void pushCascadeType(ResolutionDartType type) {
585 cascadeTypes = cascadeTypes.prepend(type); 588 cascadeTypes = cascadeTypes.prepend(type);
586 } 589 }
587 590
588 DartType popCascadeType() { 591 ResolutionDartType popCascadeType() {
589 DartType type = cascadeTypes.head; 592 ResolutionDartType type = cascadeTypes.head;
590 cascadeTypes = cascadeTypes.tail; 593 cascadeTypes = cascadeTypes.tail;
591 return type; 594 return type;
592 } 595 }
593 596
594 visitAssert(Assert node) { 597 visitAssert(Assert node) {
595 analyze(node.condition); 598 analyze(node.condition);
596 if (node.hasMessage) analyze(node.message); 599 if (node.hasMessage) analyze(node.message);
597 } 600 }
598 601
599 visitBlock(Block node) { 602 visitBlock(Block node) {
600 analyzeUntyped(node.statements); 603 analyzeUntyped(node.statements);
601 } 604 }
602 605
603 DartType visitCascade(Cascade node) { 606 ResolutionDartType visitCascade(Cascade node) {
604 analyze(node.expression); 607 analyze(node.expression);
605 return popCascadeType(); 608 return popCascadeType();
606 } 609 }
607 610
608 DartType visitCascadeReceiver(CascadeReceiver node) { 611 ResolutionDartType visitCascadeReceiver(CascadeReceiver node) {
609 DartType type = analyze(node.expression); 612 ResolutionDartType type = analyze(node.expression);
610 pushCascadeType(type); 613 pushCascadeType(type);
611 return type; 614 return type;
612 } 615 }
613 616
614 visitDoWhile(DoWhile node) { 617 visitDoWhile(DoWhile node) {
615 analyzeUntyped(node.body); 618 analyzeUntyped(node.body);
616 checkCondition(node.condition); 619 checkCondition(node.condition);
617 } 620 }
618 621
619 visitExpressionStatement(ExpressionStatement node) { 622 visitExpressionStatement(ExpressionStatement node) {
(...skipping 12 matching lines...) Expand all
632 if (node.update != null) { 635 if (node.update != null) {
633 analyzeUntyped(node.update); 636 analyzeUntyped(node.update);
634 } 637 }
635 analyzeUntyped(node.body); 638 analyzeUntyped(node.body);
636 } 639 }
637 640
638 visitFunctionDeclaration(FunctionDeclaration node) { 641 visitFunctionDeclaration(FunctionDeclaration node) {
639 analyze(node.function); 642 analyze(node.function);
640 } 643 }
641 644
642 DartType visitFunctionExpression(FunctionExpression node) { 645 ResolutionDartType visitFunctionExpression(FunctionExpression node) {
643 DartType type; 646 ResolutionDartType type;
644 DartType returnType; 647 ResolutionDartType returnType;
645 final FunctionElement element = elements.getFunctionDefinition(node); 648 final FunctionElement element = elements.getFunctionDefinition(node);
646 assert(invariant(node, element != null, 649 assert(invariant(node, element != null,
647 message: 'FunctionExpression with no element')); 650 message: 'FunctionExpression with no element'));
648 if (Elements.isUnresolved(element)) return const DynamicType(); 651 if (Elements.isUnresolved(element)) return const ResolutionDynamicType();
649 if (element.isGenerativeConstructor) { 652 if (element.isGenerativeConstructor) {
650 type = const DynamicType(); 653 type = const ResolutionDynamicType();
651 returnType = const VoidType(); 654 returnType = const ResolutionVoidType();
652 655
653 element.functionSignature.forEachParameter((ParameterElement parameter) { 656 element.functionSignature.forEachParameter((ParameterElement parameter) {
654 if (parameter.isInitializingFormal) { 657 if (parameter.isInitializingFormal) {
655 InitializingFormalElement fieldParameter = parameter; 658 InitializingFormalElement fieldParameter = parameter;
656 checkAssignable(parameter, parameter.type, 659 checkAssignable(parameter, parameter.type,
657 fieldParameter.fieldElement.computeType(resolution)); 660 fieldParameter.fieldElement.computeType(resolution));
658 } 661 }
659 }); 662 });
660 if (node.initializers != null) { 663 if (node.initializers != null) {
661 analyzeUntyped(node.initializers, inInitializer: true); 664 analyzeUntyped(node.initializers, inInitializer: true);
662 } 665 }
663 } else { 666 } else {
664 FunctionType functionType = element.computeType(resolution); 667 ResolutionFunctionType functionType = element.computeType(resolution);
665 returnType = functionType.returnType; 668 returnType = functionType.returnType;
666 type = functionType; 669 type = functionType;
667 } 670 }
668 ExecutableElement previousExecutableContext = executableContext; 671 ExecutableElement previousExecutableContext = executableContext;
669 DartType previousReturnType = expectedReturnType; 672 ResolutionDartType previousReturnType = expectedReturnType;
670 expectedReturnType = returnType; 673 expectedReturnType = returnType;
671 AsyncMarker previousAsyncMarker = currentAsyncMarker; 674 AsyncMarker previousAsyncMarker = currentAsyncMarker;
672 675
673 executableContext = element; 676 executableContext = element;
674 currentAsyncMarker = element.asyncMarker; 677 currentAsyncMarker = element.asyncMarker;
675 analyzeUntyped(node.body); 678 analyzeUntyped(node.body);
676 679
677 executableContext = previousExecutableContext; 680 executableContext = previousExecutableContext;
678 expectedReturnType = previousReturnType; 681 expectedReturnType = previousReturnType;
679 currentAsyncMarker = previousAsyncMarker; 682 currentAsyncMarker = previousAsyncMarker;
680 return type; 683 return type;
681 } 684 }
682 685
683 DartType visitIdentifier(Identifier node) { 686 ResolutionDartType visitIdentifier(Identifier node) {
684 if (node.isThis()) { 687 if (node.isThis()) {
685 return thisType; 688 return thisType;
686 } else if (node.isSuper()) { 689 } else if (node.isSuper()) {
687 return superType; 690 return superType;
688 } else { 691 } else {
689 TypedElement element = elements[node]; 692 TypedElement element = elements[node];
690 assert(invariant(node, element != null, 693 assert(invariant(node, element != null,
691 message: 'Missing element for identifier')); 694 message: 'Missing element for identifier'));
692 assert(invariant( 695 assert(invariant(
693 node, element.isVariable || element.isParameter || element.isField, 696 node, element.isVariable || element.isParameter || element.isField,
(...skipping 15 matching lines...) Expand all
709 712
710 void checkPrivateAccess(Node node, Element element, String name) { 713 void checkPrivateAccess(Node node, Element element, String name) {
711 if (name != null && 714 if (name != null &&
712 Name.isPrivateName(name) && 715 Name.isPrivateName(name) &&
713 element.library != currentLibrary) { 716 element.library != currentLibrary) {
714 reportTypeWarning(node, MessageKind.PRIVATE_ACCESS, 717 reportTypeWarning(node, MessageKind.PRIVATE_ACCESS,
715 {'name': name, 'libraryName': element.library.libraryOrScriptName}); 718 {'name': name, 'libraryName': element.library.libraryOrScriptName});
716 } 719 }
717 } 720 }
718 721
719 ElementAccess lookupMember(Node node, DartType receiverType, String name, 722 ElementAccess lookupMember(Node node, ResolutionDartType receiverType,
720 MemberKind memberKind, Element receiverElement, 723 String name, MemberKind memberKind, Element receiverElement,
721 {bool lookupClassMember: false, bool isHint: false}) { 724 {bool lookupClassMember: false, bool isHint: false}) {
722 if (receiverType.treatAsDynamic) { 725 if (receiverType.treatAsDynamic) {
723 return const DynamicAccess(); 726 return const DynamicAccess();
724 } 727 }
725 728
726 Name memberName = new Name(name, currentLibrary, 729 Name memberName = new Name(name, currentLibrary,
727 isSetter: memberKind == MemberKind.SETTER); 730 isSetter: memberKind == MemberKind.SETTER);
728 731
729 // Lookup the class or interface member [name] in [interface]. 732 // Lookup the class or interface member [name] in [interface].
730 MemberSignature lookupMemberSignature(Name name, InterfaceType interface) { 733 MemberSignature lookupMemberSignature(
734 Name name, ResolutionInterfaceType interface) {
731 MembersCreator.computeClassMembersByName( 735 MembersCreator.computeClassMembersByName(
732 resolution, interface.element, name.text); 736 resolution, interface.element, name.text);
733 return lookupClassMember || analyzingInitializer 737 return lookupClassMember || analyzingInitializer
734 ? interface.lookupClassMember(name) 738 ? interface.lookupClassMember(name)
735 : interface.lookupInterfaceMember(name); 739 : interface.lookupInterfaceMember(name);
736 } 740 }
737 741
738 // Compute the access of [name] on [type]. This function takes the special 742 // Compute the access of [name] on [type]. This function takes the special
739 // 'call' method into account. 743 // 'call' method into account.
740 ElementAccess getAccess( 744 ElementAccess getAccess(Name name, ResolutionDartType unaliasedBound,
741 Name name, DartType unaliasedBound, InterfaceType interface) { 745 ResolutionInterfaceType interface) {
742 MemberSignature member = lookupMemberSignature(memberName, interface); 746 MemberSignature member = lookupMemberSignature(memberName, interface);
743 if (member != null) { 747 if (member != null) {
744 if (member is ErroneousMember) { 748 if (member is ErroneousMember) {
745 return const DynamicAccess(); 749 return const DynamicAccess();
746 } else { 750 } else {
747 return new MemberAccess(member); 751 return new MemberAccess(member);
748 } 752 }
749 } 753 }
750 if (name == const PublicName('call')) { 754 if (name == const PublicName('call')) {
751 if (unaliasedBound.isFunctionType) { 755 if (unaliasedBound.isFunctionType) {
752 // This is an access the implicit 'call' method of a function type. 756 // This is an access the implicit 'call' method of a function type.
753 return new FunctionCallAccess(receiverElement, unaliasedBound); 757 return new FunctionCallAccess(receiverElement, unaliasedBound);
754 } 758 }
755 if (types.isSubtype(interface, commonElements.functionType)) { 759 if (types.isSubtype(interface, commonElements.functionType)) {
756 // This is an access of the special 'call' method implicitly defined 760 // This is an access of the special 'call' method implicitly defined
757 // on 'Function'. This method can be called with any arguments, which 761 // on 'Function'. This method can be called with any arguments, which
758 // we ensure by giving it the type 'dynamic'. 762 // we ensure by giving it the type 'dynamic'.
759 return new FunctionCallAccess(null, const DynamicType()); 763 return new FunctionCallAccess(null, const ResolutionDynamicType());
760 } 764 }
761 } 765 }
762 return null; 766 return null;
763 } 767 }
764 768
765 DartType unaliasedBound = 769 ResolutionDartType unaliasedBound =
766 Types.computeUnaliasedBound(resolution, receiverType); 770 Types.computeUnaliasedBound(resolution, receiverType);
767 if (unaliasedBound.treatAsDynamic) { 771 if (unaliasedBound.treatAsDynamic) {
768 return new DynamicAccess(); 772 return new DynamicAccess();
769 } 773 }
770 InterfaceType interface = 774 ResolutionInterfaceType interface =
771 Types.computeInterfaceType(resolution, unaliasedBound); 775 Types.computeInterfaceType(resolution, unaliasedBound);
772 ElementAccess access = getAccess(memberName, unaliasedBound, interface); 776 ElementAccess access = getAccess(memberName, unaliasedBound, interface);
773 if (access != null) { 777 if (access != null) {
774 return access; 778 return access;
775 } 779 }
776 if (receiverElement != null && 780 if (receiverElement != null &&
777 (receiverElement.isVariable || receiverElement.isParameter)) { 781 (receiverElement.isVariable || receiverElement.isParameter)) {
778 Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement]; 782 Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
779 if (typePromotions != null) { 783 if (typePromotions != null) {
780 while (!typePromotions.isEmpty) { 784 while (!typePromotions.isEmpty) {
781 TypePromotion typePromotion = typePromotions.head; 785 TypePromotion typePromotion = typePromotions.head;
782 if (!typePromotion.isValid) { 786 if (!typePromotion.isValid) {
783 DartType unaliasedBound = 787 ResolutionDartType unaliasedBound =
784 Types.computeUnaliasedBound(resolution, typePromotion.type); 788 Types.computeUnaliasedBound(resolution, typePromotion.type);
785 if (!unaliasedBound.treatAsDynamic) { 789 if (!unaliasedBound.treatAsDynamic) {
786 InterfaceType interface = 790 ResolutionInterfaceType interface =
787 Types.computeInterfaceType(resolution, unaliasedBound); 791 Types.computeInterfaceType(resolution, unaliasedBound);
788 if (getAccess(memberName, unaliasedBound, interface) != null) { 792 if (getAccess(memberName, unaliasedBound, interface) != null) {
789 reportTypePromotionHint(typePromotion); 793 reportTypePromotionHint(typePromotion);
790 } 794 }
791 } 795 }
792 } 796 }
793 typePromotions = typePromotions.tail; 797 typePromotions = typePromotions.tail;
794 } 798 }
795 } 799 }
796 } 800 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 reportMessage(node, MessageKind.UNDEFINED_SETTER, 870 reportMessage(node, MessageKind.UNDEFINED_SETTER,
867 {'className': receiverType.name, 'memberName': name}, 871 {'className': receiverType.name, 'memberName': name},
868 isHint: isHint); 872 isHint: isHint);
869 break; 873 break;
870 } 874 }
871 } 875 }
872 } 876 }
873 return const DynamicAccess(); 877 return const DynamicAccess();
874 } 878 }
875 879
876 DartType lookupMemberType( 880 ResolutionDartType lookupMemberType(
877 Node node, DartType type, String name, MemberKind memberKind, 881 Node node, ResolutionDartType type, String name, MemberKind memberKind,
878 {bool isHint: false}) { 882 {bool isHint: false}) {
879 return lookupMember(node, type, name, memberKind, null, isHint: isHint) 883 return lookupMember(node, type, name, memberKind, null, isHint: isHint)
880 .computeType(resolution); 884 .computeType(resolution);
881 } 885 }
882 886
883 void analyzeArguments(Send send, Element element, DartType type, 887 void analyzeArguments(Send send, Element element, ResolutionDartType type,
884 [LinkBuilder<DartType> argumentTypes]) { 888 [LinkBuilder<ResolutionDartType> argumentTypes]) {
885 Link<Node> arguments = send.arguments; 889 Link<Node> arguments = send.arguments;
886 type.computeUnaliased(resolution); 890 type.computeUnaliased(resolution);
887 DartType unaliasedType = type.unaliased; 891 ResolutionDartType unaliasedType = type.unaliased;
888 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { 892 if (identical(unaliasedType.kind, ResolutionTypeKind.FUNCTION)) {
889 /// Report [warning] including info(s) about the declaration of [element] 893 /// Report [warning] including info(s) about the declaration of [element]
890 /// or [type]. 894 /// or [type].
891 void reportWarning(DiagnosticMessage warning) { 895 void reportWarning(DiagnosticMessage warning) {
892 // TODO(johnniwinther): Support pointing to individual parameters on 896 // TODO(johnniwinther): Support pointing to individual parameters on
893 // assignability warnings. 897 // assignability warnings.
894 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; 898 List<DiagnosticMessage> infos = <DiagnosticMessage>[];
895 Element declaration = element; 899 Element declaration = element;
896 if (declaration == null) { 900 if (declaration == null) {
897 declaration = type.element; 901 declaration = type.element;
898 } else if (type.isTypedef) { 902 } else if (type.isTypedef) {
899 infos.add(reporter.createMessage(declaration, 903 infos.add(reporter.createMessage(declaration,
900 MessageKind.THIS_IS_THE_DECLARATION, {'name': element.name})); 904 MessageKind.THIS_IS_THE_DECLARATION, {'name': element.name}));
901 declaration = type.element; 905 declaration = type.element;
902 } 906 }
903 if (declaration != null) { 907 if (declaration != null) {
904 infos.add(reporter.createMessage( 908 infos.add(reporter.createMessage(
905 declaration, MessageKind.THIS_IS_THE_METHOD)); 909 declaration, MessageKind.THIS_IS_THE_METHOD));
906 } 910 }
907 reporter.reportWarning(warning, infos); 911 reporter.reportWarning(warning, infos);
908 } 912 }
909 913
910 /// Report a warning on [node] if [argumentType] is not assignable to 914 /// Report a warning on [node] if [argumentType] is not assignable to
911 /// [parameterType]. 915 /// [parameterType].
912 void checkAssignable( 916 void checkAssignable(Spannable node, ResolutionDartType argumentType,
913 Spannable node, DartType argumentType, DartType parameterType) { 917 ResolutionDartType parameterType) {
914 if (!types.isAssignable(argumentType, parameterType)) { 918 if (!types.isAssignable(argumentType, parameterType)) {
915 reportWarning(reporter.createMessage(node, MessageKind.NOT_ASSIGNABLE, 919 reportWarning(reporter.createMessage(node, MessageKind.NOT_ASSIGNABLE,
916 {'fromType': argumentType, 'toType': parameterType})); 920 {'fromType': argumentType, 'toType': parameterType}));
917 } 921 }
918 } 922 }
919 923
920 FunctionType funType = unaliasedType; 924 ResolutionFunctionType funType = unaliasedType;
921 Iterator<DartType> parameterTypes = funType.parameterTypes.iterator; 925 Iterator<ResolutionDartType> parameterTypes =
922 Iterator<DartType> optionalParameterTypes = 926 funType.parameterTypes.iterator;
927 Iterator<ResolutionDartType> optionalParameterTypes =
923 funType.optionalParameterTypes.iterator; 928 funType.optionalParameterTypes.iterator;
924 while (!arguments.isEmpty) { 929 while (!arguments.isEmpty) {
925 Node argument = arguments.head; 930 Node argument = arguments.head;
926 NamedArgument namedArgument = argument.asNamedArgument(); 931 NamedArgument namedArgument = argument.asNamedArgument();
927 if (namedArgument != null) { 932 if (namedArgument != null) {
928 argument = namedArgument.expression; 933 argument = namedArgument.expression;
929 String argumentName = namedArgument.name.source; 934 String argumentName = namedArgument.name.source;
930 DartType namedParameterType = 935 ResolutionDartType namedParameterType =
931 funType.getNamedParameterType(argumentName); 936 funType.getNamedParameterType(argumentName);
932 if (namedParameterType == null) { 937 if (namedParameterType == null) {
933 // TODO(johnniwinther): Provide better information on the called 938 // TODO(johnniwinther): Provide better information on the called
934 // function. 939 // function.
935 reportWarning(reporter.createMessage( 940 reportWarning(reporter.createMessage(
936 argument, 941 argument,
937 MessageKind.NAMED_ARGUMENT_NOT_FOUND, 942 MessageKind.NAMED_ARGUMENT_NOT_FOUND,
938 {'argumentName': argumentName})); 943 {'argumentName': argumentName}));
939 944
940 DartType argumentType = analyze(argument); 945 ResolutionDartType argumentType = analyze(argument);
941 if (argumentTypes != null) argumentTypes.addLast(argumentType); 946 if (argumentTypes != null) argumentTypes.addLast(argumentType);
942 } else { 947 } else {
943 DartType argumentType = analyze(argument); 948 ResolutionDartType argumentType = analyze(argument);
944 if (argumentTypes != null) argumentTypes.addLast(argumentType); 949 if (argumentTypes != null) argumentTypes.addLast(argumentType);
945 checkAssignable(argument, argumentType, namedParameterType); 950 checkAssignable(argument, argumentType, namedParameterType);
946 } 951 }
947 } else { 952 } else {
948 if (!parameterTypes.moveNext()) { 953 if (!parameterTypes.moveNext()) {
949 if (!optionalParameterTypes.moveNext()) { 954 if (!optionalParameterTypes.moveNext()) {
950 // TODO(johnniwinther): Provide better information on the 955 // TODO(johnniwinther): Provide better information on the
951 // called function. 956 // called function.
952 reportWarning(reporter.createMessage( 957 reportWarning(reporter.createMessage(
953 argument, MessageKind.ADDITIONAL_ARGUMENT)); 958 argument, MessageKind.ADDITIONAL_ARGUMENT));
954 959
955 DartType argumentType = analyze(argument); 960 ResolutionDartType argumentType = analyze(argument);
956 if (argumentTypes != null) argumentTypes.addLast(argumentType); 961 if (argumentTypes != null) argumentTypes.addLast(argumentType);
957 } else { 962 } else {
958 DartType argumentType = analyze(argument); 963 ResolutionDartType argumentType = analyze(argument);
959 if (argumentTypes != null) argumentTypes.addLast(argumentType); 964 if (argumentTypes != null) argumentTypes.addLast(argumentType);
960 checkAssignable( 965 checkAssignable(
961 argument, argumentType, optionalParameterTypes.current); 966 argument, argumentType, optionalParameterTypes.current);
962 } 967 }
963 } else { 968 } else {
964 DartType argumentType = analyze(argument); 969 ResolutionDartType argumentType = analyze(argument);
965 if (argumentTypes != null) argumentTypes.addLast(argumentType); 970 if (argumentTypes != null) argumentTypes.addLast(argumentType);
966 checkAssignable(argument, argumentType, parameterTypes.current); 971 checkAssignable(argument, argumentType, parameterTypes.current);
967 } 972 }
968 } 973 }
969 arguments = arguments.tail; 974 arguments = arguments.tail;
970 } 975 }
971 if (parameterTypes.moveNext()) { 976 if (parameterTypes.moveNext()) {
972 // TODO(johnniwinther): Provide better information on the called 977 // TODO(johnniwinther): Provide better information on the called
973 // function. 978 // function.
974 reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT, 979 reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT,
975 {'argumentType': parameterTypes.current})); 980 {'argumentType': parameterTypes.current}));
976 } 981 }
977 } else { 982 } else {
978 while (!arguments.isEmpty) { 983 while (!arguments.isEmpty) {
979 DartType argumentType = analyze(arguments.head); 984 ResolutionDartType argumentType = analyze(arguments.head);
980 if (argumentTypes != null) argumentTypes.addLast(argumentType); 985 if (argumentTypes != null) argumentTypes.addLast(argumentType);
981 arguments = arguments.tail; 986 arguments = arguments.tail;
982 } 987 }
983 } 988 }
984 } 989 }
985 990
986 // Analyze the invocation [node] of [elementAccess]. 991 // Analyze the invocation [node] of [elementAccess].
987 // 992 //
988 // If provided [argumentTypes] is filled with the argument types during 993 // If provided [argumentTypes] is filled with the argument types during
989 // analysis. 994 // analysis.
990 DartType analyzeInvocation(Send node, ElementAccess elementAccess, 995 ResolutionDartType analyzeInvocation(Send node, ElementAccess elementAccess,
991 [LinkBuilder<DartType> argumentTypes]) { 996 [LinkBuilder<ResolutionDartType> argumentTypes]) {
992 DartType type = elementAccess.computeType(resolution); 997 ResolutionDartType type = elementAccess.computeType(resolution);
993 if (elementAccess.isCallable(compiler)) { 998 if (elementAccess.isCallable(compiler)) {
994 analyzeArguments(node, elementAccess.element, type, argumentTypes); 999 analyzeArguments(node, elementAccess.element, type, argumentTypes);
995 } else { 1000 } else {
996 reportTypeWarning( 1001 reportTypeWarning(
997 node, MessageKind.NOT_CALLABLE, {'elementName': elementAccess.name}); 1002 node, MessageKind.NOT_CALLABLE, {'elementName': elementAccess.name});
998 analyzeArguments( 1003 analyzeArguments(node, elementAccess.element,
999 node, elementAccess.element, const DynamicType(), argumentTypes); 1004 const ResolutionDynamicType(), argumentTypes);
1000 } 1005 }
1001 type.computeUnaliased(resolution); 1006 type.computeUnaliased(resolution);
1002 type = type.unaliased; 1007 type = type.unaliased;
1003 if (type.isFunctionType) { 1008 if (type.isFunctionType) {
1004 FunctionType funType = type; 1009 ResolutionFunctionType funType = type;
1005 return funType.returnType; 1010 return funType.returnType;
1006 } else { 1011 } else {
1007 return const DynamicType(); 1012 return const ResolutionDynamicType();
1008 } 1013 }
1009 } 1014 }
1010 1015
1011 /** 1016 /**
1012 * Computes the [ElementAccess] for [name] on the [node] possibly using the 1017 * Computes the [ElementAccess] for [name] on the [node] possibly using the
1013 * [element] provided for [node] by the resolver. 1018 * [element] provided for [node] by the resolver.
1014 */ 1019 */
1015 ElementAccess computeAccess( 1020 ElementAccess computeAccess(
1016 Send node, String name, Element element, MemberKind memberKind, 1021 Send node, String name, Element element, MemberKind memberKind,
1017 {bool lookupClassMember: false}) { 1022 {bool lookupClassMember: false}) {
1018 if (Elements.isMalformed(element)) { 1023 if (Elements.isMalformed(element)) {
1019 return const DynamicAccess(); 1024 return const DynamicAccess();
1020 } 1025 }
1021 if (node.receiver != null) { 1026 if (node.receiver != null) {
1022 Element receiverElement = elements[node.receiver]; 1027 Element receiverElement = elements[node.receiver];
1023 if (receiverElement != null) { 1028 if (receiverElement != null) {
1024 if (receiverElement.isPrefix) { 1029 if (receiverElement.isPrefix) {
1025 if (node.isConditional) { 1030 if (node.isConditional) {
1026 // Skip cases like `prefix?.topLevel`. 1031 // Skip cases like `prefix?.topLevel`.
1027 return const DynamicAccess(); 1032 return const DynamicAccess();
1028 } 1033 }
1029 assert(invariant(node, element != null, 1034 assert(invariant(node, element != null,
1030 message: 'Prefixed node has no element.')); 1035 message: 'Prefixed node has no element.'));
1031 return computeResolvedAccess(node, name, element, memberKind); 1036 return computeResolvedAccess(node, name, element, memberKind);
1032 } 1037 }
1033 } 1038 }
1034 // e.foo() for some expression e. 1039 // e.foo() for some expression e.
1035 DartType receiverType = analyze(node.receiver); 1040 ResolutionDartType receiverType = analyze(node.receiver);
1036 if (receiverType.treatAsDynamic || receiverType.isVoid) { 1041 if (receiverType.treatAsDynamic || receiverType.isVoid) {
1037 return const DynamicAccess(); 1042 return const DynamicAccess();
1038 } 1043 }
1039 return lookupMember( 1044 return lookupMember(
1040 node, receiverType, name, memberKind, elements[node.receiver], 1045 node, receiverType, name, memberKind, elements[node.receiver],
1041 lookupClassMember: 1046 lookupClassMember:
1042 lookupClassMember || element != null && element.isStatic); 1047 lookupClassMember || element != null && element.isStatic);
1043 } else { 1048 } else {
1044 return computeResolvedAccess(node, name, element, memberKind); 1049 return computeResolvedAccess(node, name, element, memberKind);
1045 } 1050 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 return new PromotedAccess(element, typePromotion.type); 1102 return new PromotedAccess(element, typePromotion.type);
1098 } 1103 }
1099 } 1104 }
1100 return new ResolvedAccess(element); 1105 return new ResolvedAccess(element);
1101 } 1106 }
1102 1107
1103 /** 1108 /**
1104 * Computes the type of the access of [name] on the [node] possibly using the 1109 * Computes the type of the access of [name] on the [node] possibly using the
1105 * [element] provided for [node] by the resolver. 1110 * [element] provided for [node] by the resolver.
1106 */ 1111 */
1107 DartType computeAccessType( 1112 ResolutionDartType computeAccessType(
1108 Send node, String name, Element element, MemberKind memberKind, 1113 Send node, String name, Element element, MemberKind memberKind,
1109 {bool lookupClassMember: false}) { 1114 {bool lookupClassMember: false}) {
1110 DartType type = computeAccess(node, name, element, memberKind, 1115 ResolutionDartType type = computeAccess(node, name, element, memberKind,
1111 lookupClassMember: lookupClassMember) 1116 lookupClassMember: lookupClassMember)
1112 .computeType(resolution); 1117 .computeType(resolution);
1113 if (type == null) { 1118 if (type == null) {
1114 reporter.internalError(node, 'Type is null on access of $name on $node.'); 1119 reporter.internalError(node, 'Type is null on access of $name on $node.');
1115 } 1120 }
1116 return type; 1121 return type;
1117 } 1122 }
1118 1123
1119 /// Compute a version of [shownType] that is more specific that [knownType]. 1124 /// Compute a version of [shownType] that is more specific that [knownType].
1120 /// This is used to provided better hints when trying to promote a supertype 1125 /// This is used to provided better hints when trying to promote a supertype
1121 /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List` 1126 /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List`
1122 /// we suggest the use of `List<int>`, which would make promotion valid. 1127 /// we suggest the use of `List<int>`, which would make promotion valid.
1123 DartType computeMoreSpecificType(DartType shownType, DartType knownType) { 1128 ResolutionDartType computeMoreSpecificType(
1129 ResolutionDartType shownType, ResolutionDartType knownType) {
1124 if (knownType.isInterfaceType && 1130 if (knownType.isInterfaceType &&
1125 shownType.isInterfaceType && 1131 shownType.isInterfaceType &&
1126 types.isSubtype(shownType.asRaw(), knownType)) { 1132 types.isSubtype(shownType.asRaw(), knownType)) {
1127 // For the comments in the block, assume the hierarchy: 1133 // For the comments in the block, assume the hierarchy:
1128 // class A<T, V> {} 1134 // class A<T, V> {}
1129 // class B<S, U> extends A<S, int> {} 1135 // class B<S, U> extends A<S, int> {}
1130 // and a promotion from a [knownType] of `A<double, int>` to a 1136 // and a promotion from a [knownType] of `A<double, int>` to a
1131 // [shownType] of `B`. 1137 // [shownType] of `B`.
1132 InterfaceType knownInterfaceType = knownType; 1138 ResolutionInterfaceType knownInterfaceType = knownType;
1133 ClassElement shownClass = shownType.element; 1139 ClassElement shownClass = shownType.element;
1134 1140
1135 // Compute `B<double, dynamic>` as the subtype of `A<double, int>` using 1141 // Compute `B<double, dynamic>` as the subtype of `A<double, int>` using
1136 // the relation between `A<S, int>` and `A<double, int>`. 1142 // the relation between `A<S, int>` and `A<double, int>`.
1137 MoreSpecificSubtypeVisitor visitor = 1143 MoreSpecificSubtypeVisitor visitor =
1138 new MoreSpecificSubtypeVisitor(types); 1144 new MoreSpecificSubtypeVisitor(types);
1139 InterfaceType shownTypeGeneric = 1145 ResolutionInterfaceType shownTypeGeneric =
1140 visitor.computeMoreSpecific(shownClass, knownInterfaceType); 1146 visitor.computeMoreSpecific(shownClass, knownInterfaceType);
1141 1147
1142 if (shownTypeGeneric != null && 1148 if (shownTypeGeneric != null &&
1143 types.isMoreSpecific(shownTypeGeneric, knownType)) { 1149 types.isMoreSpecific(shownTypeGeneric, knownType)) {
1144 // This should be the case but we double-check. 1150 // This should be the case but we double-check.
1145 // TODO(johnniwinther): Ensure that we don't suggest malbounded types. 1151 // TODO(johnniwinther): Ensure that we don't suggest malbounded types.
1146 return shownTypeGeneric; 1152 return shownTypeGeneric;
1147 } 1153 }
1148 } 1154 }
1149 return null; 1155 return null;
1150 } 1156 }
1151 1157
1152 DartType visitSend(Send node) { 1158 ResolutionDartType visitSend(Send node) {
1153 Element element = elements[node]; 1159 Element element = elements[node];
1154 1160
1155 if (element != null && element.isConstructor) { 1161 if (element != null && element.isConstructor) {
1156 DartType receiverType; 1162 ResolutionDartType receiverType;
1157 if (node.receiver != null) { 1163 if (node.receiver != null) {
1158 receiverType = analyze(node.receiver); 1164 receiverType = analyze(node.receiver);
1159 } else if (node.selector.isSuper()) { 1165 } else if (node.selector.isSuper()) {
1160 // TODO(johnniwinther): Lookup super-member in class members. 1166 // TODO(johnniwinther): Lookup super-member in class members.
1161 receiverType = superType; 1167 receiverType = superType;
1162 } else { 1168 } else {
1163 assert(node.selector.isThis()); 1169 assert(node.selector.isThis());
1164 receiverType = thisType; 1170 receiverType = thisType;
1165 } 1171 }
1166 DartType constructorType = computeConstructorType(element, receiverType); 1172 ResolutionDartType constructorType =
1173 computeConstructorType(element, receiverType);
1167 analyzeArguments(node, element, constructorType); 1174 analyzeArguments(node, element, constructorType);
1168 return const DynamicType(); 1175 return const ResolutionDynamicType();
1169 } 1176 }
1170 1177
1171 Identifier selector = node.selector.asIdentifier(); 1178 Identifier selector = node.selector.asIdentifier();
1172 if (Elements.isClosureSend(node, element)) { 1179 if (Elements.isClosureSend(node, element)) {
1173 if (element != null) { 1180 if (element != null) {
1174 if (element.isError) { 1181 if (element.isError) {
1175 // foo() where foo is erroneous 1182 // foo() where foo is erroneous
1176 return analyzeInvocation(node, const DynamicAccess()); 1183 return analyzeInvocation(node, const DynamicAccess());
1177 } else { 1184 } else {
1178 assert(invariant(node, element.isLocal, 1185 assert(invariant(node, element.isLocal,
1179 message: "Unexpected element $element in closure send.")); 1186 message: "Unexpected element $element in closure send."));
1180 // foo() where foo is a local or a parameter. 1187 // foo() where foo is a local or a parameter.
1181 return analyzeInvocation(node, createPromotedAccess(element)); 1188 return analyzeInvocation(node, createPromotedAccess(element));
1182 } 1189 }
1183 } else { 1190 } else {
1184 // exp() where exp is some complex expression like (o) or foo(). 1191 // exp() where exp is some complex expression like (o) or foo().
1185 DartType type = analyze(node.selector); 1192 ResolutionDartType type = analyze(node.selector);
1186 return analyzeInvocation(node, new TypeAccess(type)); 1193 return analyzeInvocation(node, new TypeAccess(type));
1187 } 1194 }
1188 } else if (Elements.isMalformed(element) && selector == null) { 1195 } else if (Elements.isMalformed(element) && selector == null) {
1189 // exp() where exp is an erroneous construct like `new Unresolved()`. 1196 // exp() where exp is an erroneous construct like `new Unresolved()`.
1190 DartType type = analyze(node.selector); 1197 ResolutionDartType type = analyze(node.selector);
1191 return analyzeInvocation(node, new TypeAccess(type)); 1198 return analyzeInvocation(node, new TypeAccess(type));
1192 } 1199 }
1193 1200
1194 String name = selector.source; 1201 String name = selector.source;
1195 1202
1196 if (node.isOperator && identical(name, 'is')) { 1203 if (node.isOperator && identical(name, 'is')) {
1197 analyze(node.receiver); 1204 analyze(node.receiver);
1198 if (!node.isIsNotCheck) { 1205 if (!node.isIsNotCheck) {
1199 Element variable = elements[node.receiver]; 1206 Element variable = elements[node.receiver];
1200 if (variable == null) { 1207 if (variable == null) {
1201 // Look for the variable element within parenthesized expressions. 1208 // Look for the variable element within parenthesized expressions.
1202 ParenthesizedExpression parentheses = 1209 ParenthesizedExpression parentheses =
1203 node.receiver.asParenthesizedExpression(); 1210 node.receiver.asParenthesizedExpression();
1204 while (parentheses != null) { 1211 while (parentheses != null) {
1205 variable = elements[parentheses.expression]; 1212 variable = elements[parentheses.expression];
1206 if (variable != null) break; 1213 if (variable != null) break;
1207 parentheses = parentheses.expression.asParenthesizedExpression(); 1214 parentheses = parentheses.expression.asParenthesizedExpression();
1208 } 1215 }
1209 } 1216 }
1210 1217
1211 if (variable != null && (variable.isVariable || variable.isParameter)) { 1218 if (variable != null && (variable.isVariable || variable.isParameter)) {
1212 DartType knownType = getKnownType(variable); 1219 ResolutionDartType knownType = getKnownType(variable);
1213 if (!knownType.isDynamic) { 1220 if (!knownType.isDynamic) {
1214 DartType shownType = elements.getType(node.arguments.head); 1221 ResolutionDartType shownType =
1222 elements.getType(node.arguments.head);
1215 TypePromotion typePromotion = 1223 TypePromotion typePromotion =
1216 new TypePromotion(node, variable, shownType); 1224 new TypePromotion(node, variable, shownType);
1217 if (!types.isMoreSpecific(shownType, knownType)) { 1225 if (!types.isMoreSpecific(shownType, knownType)) {
1218 String variableName = variable.name; 1226 String variableName = variable.name;
1219 if (!types.isSubtype(shownType, knownType)) { 1227 if (!types.isSubtype(shownType, knownType)) {
1220 typePromotion.addHint(reporter.createMessage( 1228 typePromotion.addHint(reporter.createMessage(
1221 node, MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, { 1229 node, MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, {
1222 'variableName': variableName, 1230 'variableName': variableName,
1223 'shownType': shownType, 1231 'shownType': shownType,
1224 'knownType': knownType 1232 'knownType': knownType
1225 })); 1233 }));
1226 } else { 1234 } else {
1227 DartType shownTypeSuggestion = 1235 ResolutionDartType shownTypeSuggestion =
1228 computeMoreSpecificType(shownType, knownType); 1236 computeMoreSpecificType(shownType, knownType);
1229 if (shownTypeSuggestion != null) { 1237 if (shownTypeSuggestion != null) {
1230 typePromotion.addHint(reporter.createMessage( 1238 typePromotion.addHint(reporter.createMessage(
1231 node, MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, { 1239 node, MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, {
1232 'variableName': variableName, 1240 'variableName': variableName,
1233 'shownType': shownType, 1241 'shownType': shownType,
1234 'shownTypeSuggestion': shownTypeSuggestion, 1242 'shownTypeSuggestion': shownTypeSuggestion,
1235 'knownType': knownType 1243 'knownType': knownType
1236 })); 1244 }));
1237 } else { 1245 } else {
(...skipping 10 matching lines...) Expand all
1248 } 1256 }
1249 } 1257 }
1250 } 1258 }
1251 return boolType; 1259 return boolType;
1252 } 1260 }
1253 if (node.isOperator && identical(name, 'as')) { 1261 if (node.isOperator && identical(name, 'as')) {
1254 analyze(node.receiver); 1262 analyze(node.receiver);
1255 return elements.getType(node.arguments.head); 1263 return elements.getType(node.arguments.head);
1256 } else if (node.isOperator) { 1264 } else if (node.isOperator) {
1257 final Node receiver = node.receiver; 1265 final Node receiver = node.receiver;
1258 final DartType receiverType = analyze(receiver); 1266 final ResolutionDartType receiverType = analyze(receiver);
1259 if (identical(name, '==') || 1267 if (identical(name, '==') ||
1260 identical(name, '!=') 1268 identical(name, '!=')
1261 // TODO(johnniwinther): Remove these. 1269 // TODO(johnniwinther): Remove these.
1262 || 1270 ||
1263 identical(name, '===') || 1271 identical(name, '===') ||
1264 identical(name, '!==')) { 1272 identical(name, '!==')) {
1265 // Analyze argument. 1273 // Analyze argument.
1266 analyze(node.arguments.head); 1274 analyze(node.arguments.head);
1267 return boolType; 1275 return boolType;
1268 } else if (identical(name, '||')) { 1276 } else if (identical(name, '||')) {
1269 checkAssignable(receiver, receiverType, boolType); 1277 checkAssignable(receiver, receiverType, boolType);
1270 final Node argument = node.arguments.head; 1278 final Node argument = node.arguments.head;
1271 final DartType argumentType = analyze(argument); 1279 final ResolutionDartType argumentType = analyze(argument);
1272 checkAssignable(argument, argumentType, boolType); 1280 checkAssignable(argument, argumentType, boolType);
1273 return boolType; 1281 return boolType;
1274 } else if (identical(name, '&&')) { 1282 } else if (identical(name, '&&')) {
1275 checkAssignable(receiver, receiverType, boolType); 1283 checkAssignable(receiver, receiverType, boolType);
1276 final Node argument = node.arguments.head; 1284 final Node argument = node.arguments.head;
1277 1285
1278 final DartType argumentType = 1286 final ResolutionDartType argumentType =
1279 analyzeInPromotedContext(receiver, argument); 1287 analyzeInPromotedContext(receiver, argument);
1280 1288
1281 reshowTypePromotions(node, receiver, argument); 1289 reshowTypePromotions(node, receiver, argument);
1282 1290
1283 checkAssignable(argument, argumentType, boolType); 1291 checkAssignable(argument, argumentType, boolType);
1284 return boolType; 1292 return boolType;
1285 } else if (identical(name, '!')) { 1293 } else if (identical(name, '!')) {
1286 checkAssignable(receiver, receiverType, boolType); 1294 checkAssignable(receiver, receiverType, boolType);
1287 return boolType; 1295 return boolType;
1288 } else if (identical(name, '?')) { 1296 } else if (identical(name, '?')) {
1289 return boolType; 1297 return boolType;
1290 } else if (identical(name, '??')) { 1298 } else if (identical(name, '??')) {
1291 final Node argument = node.arguments.head; 1299 final Node argument = node.arguments.head;
1292 final DartType argumentType = analyze(argument); 1300 final ResolutionDartType argumentType = analyze(argument);
1293 return types.computeLeastUpperBound(receiverType, argumentType); 1301 return types.computeLeastUpperBound(receiverType, argumentType);
1294 } 1302 }
1295 String operatorName = selector.source; 1303 String operatorName = selector.source;
1296 if (identical(name, '-') && node.arguments.isEmpty) { 1304 if (identical(name, '-') && node.arguments.isEmpty) {
1297 operatorName = 'unary-'; 1305 operatorName = 'unary-';
1298 } 1306 }
1299 assert(invariant( 1307 assert(invariant(
1300 node, 1308 node,
1301 identical(name, '+') || 1309 identical(name, '+') ||
1302 identical(name, '=') || 1310 identical(name, '=') ||
(...skipping 14 matching lines...) Expand all
1317 identical(name, '>=') || 1325 identical(name, '>=') ||
1318 identical(name, '[]'), 1326 identical(name, '[]'),
1319 message: 'Unexpected operator $name')); 1327 message: 'Unexpected operator $name'));
1320 1328
1321 // TODO(karlklose): handle `void` in expression context by calling 1329 // TODO(karlklose): handle `void` in expression context by calling
1322 // [analyzeNonVoid] instead of [analyze]. 1330 // [analyzeNonVoid] instead of [analyze].
1323 ElementAccess access = receiverType.isVoid 1331 ElementAccess access = receiverType.isVoid
1324 ? const DynamicAccess() 1332 ? const DynamicAccess()
1325 : lookupMember( 1333 : lookupMember(
1326 node, receiverType, operatorName, MemberKind.OPERATOR, null); 1334 node, receiverType, operatorName, MemberKind.OPERATOR, null);
1327 LinkBuilder<DartType> argumentTypesBuilder = new LinkBuilder<DartType>(); 1335 LinkBuilder<ResolutionDartType> argumentTypesBuilder =
1328 DartType resultType = 1336 new LinkBuilder<ResolutionDartType>();
1337 ResolutionDartType resultType =
1329 analyzeInvocation(node, access, argumentTypesBuilder); 1338 analyzeInvocation(node, access, argumentTypesBuilder);
1330 if (receiverType == intType) { 1339 if (receiverType == intType) {
1331 if (identical(name, '+') || 1340 if (identical(name, '+') ||
1332 identical(operatorName, '-') || 1341 identical(operatorName, '-') ||
1333 identical(name, '*') || 1342 identical(name, '*') ||
1334 identical(name, '%')) { 1343 identical(name, '%')) {
1335 DartType argumentType = argumentTypesBuilder.toLink().head; 1344 ResolutionDartType argumentType = argumentTypesBuilder.toLink().head;
1336 if (argumentType == intType) { 1345 if (argumentType == intType) {
1337 return intType; 1346 return intType;
1338 } else if (argumentType == doubleType) { 1347 } else if (argumentType == doubleType) {
1339 return doubleType; 1348 return doubleType;
1340 } 1349 }
1341 } 1350 }
1342 } 1351 }
1343 return resultType; 1352 return resultType;
1344 } else if (node.isPropertyAccess) { 1353 } else if (node.isPropertyAccess) {
1345 ElementAccess access = 1354 ElementAccess access =
1346 computeAccess(node, selector.source, element, MemberKind.GETTER); 1355 computeAccess(node, selector.source, element, MemberKind.GETTER);
1347 return access.computeType(resolution); 1356 return access.computeType(resolution);
1348 } else if (node.isFunctionObjectInvocation) { 1357 } else if (node.isFunctionObjectInvocation) {
1349 return unhandledExpression(); 1358 return unhandledExpression();
1350 } else { 1359 } else {
1351 ElementAccess access = 1360 ElementAccess access =
1352 computeAccess(node, selector.source, element, MemberKind.METHOD); 1361 computeAccess(node, selector.source, element, MemberKind.METHOD);
1353 return analyzeInvocation(node, access); 1362 return analyzeInvocation(node, access);
1354 } 1363 }
1355 } 1364 }
1356 1365
1357 /// Returns the first type in the list or [:dynamic:] if the list is empty. 1366 /// Returns the first type in the list or [:dynamic:] if the list is empty.
1358 DartType firstType(List<DartType> list) { 1367 ResolutionDartType firstType(List<ResolutionDartType> list) {
1359 return list.isEmpty ? const DynamicType() : list.first; 1368 return list.isEmpty ? const ResolutionDynamicType() : list.first;
1360 } 1369 }
1361 1370
1362 /** 1371 /**
1363 * Returns the second type in the list or [:dynamic:] if the list is too 1372 * Returns the second type in the list or [:dynamic:] if the list is too
1364 * short. 1373 * short.
1365 */ 1374 */
1366 DartType secondType(List<DartType> list) { 1375 ResolutionDartType secondType(List<ResolutionDartType> list) {
1367 return list.length < 2 ? const DynamicType() : list[1]; 1376 return list.length < 2 ? const ResolutionDynamicType() : list[1];
1368 } 1377 }
1369 1378
1370 /** 1379 /**
1371 * Checks [: target o= value :] for some operator o, and returns the type 1380 * Checks [: target o= value :] for some operator o, and returns the type
1372 * of the result. This method also handles increment/decrement expressions 1381 * of the result. This method also handles increment/decrement expressions
1373 * like [: target++ :]. 1382 * like [: target++ :].
1374 */ 1383 */
1375 DartType checkAssignmentOperator( 1384 ResolutionDartType checkAssignmentOperator(SendSet node, String operatorName,
1376 SendSet node, String operatorName, Node valueNode, DartType value) { 1385 Node valueNode, ResolutionDartType value) {
1377 assert(invariant(node, !node.isIndex)); 1386 assert(invariant(node, !node.isIndex));
1378 Element setterElement = elements[node]; 1387 Element setterElement = elements[node];
1379 Element getterElement = elements[node.selector]; 1388 Element getterElement = elements[node.selector];
1380 Identifier selector = node.selector; 1389 Identifier selector = node.selector;
1381 DartType getter = computeAccessType( 1390 ResolutionDartType getter = computeAccessType(
1382 node, selector.source, getterElement, MemberKind.GETTER); 1391 node, selector.source, getterElement, MemberKind.GETTER);
1383 DartType setter = computeAccessType( 1392 ResolutionDartType setter = computeAccessType(
1384 node, selector.source, setterElement, MemberKind.SETTER); 1393 node, selector.source, setterElement, MemberKind.SETTER);
1385 // [operator] is the type of operator+ or operator- on [target]. 1394 // [operator] is the type of operator+ or operator- on [target].
1386 DartType operator = 1395 ResolutionDartType operator =
1387 lookupMemberType(node, getter, operatorName, MemberKind.OPERATOR); 1396 lookupMemberType(node, getter, operatorName, MemberKind.OPERATOR);
1388 if (operator is FunctionType) { 1397 if (operator is ResolutionFunctionType) {
1389 FunctionType operatorType = operator; 1398 ResolutionFunctionType operatorType = operator;
1390 // [result] is the type of target o value. 1399 // [result] is the type of target o value.
1391 DartType result = operatorType.returnType; 1400 ResolutionDartType result = operatorType.returnType;
1392 DartType operatorArgument = firstType(operatorType.parameterTypes); 1401 ResolutionDartType operatorArgument =
1402 firstType(operatorType.parameterTypes);
1393 // Check target o value. 1403 // Check target o value.
1394 bool validValue = checkAssignable(valueNode, value, operatorArgument); 1404 bool validValue = checkAssignable(valueNode, value, operatorArgument);
1395 if (validValue || !(node.isPrefix || node.isPostfix)) { 1405 if (validValue || !(node.isPrefix || node.isPostfix)) {
1396 // Check target = result. 1406 // Check target = result.
1397 checkAssignable(node.assignmentOperator, result, setter); 1407 checkAssignable(node.assignmentOperator, result, setter);
1398 } 1408 }
1399 return node.isPostfix ? getter : result; 1409 return node.isPostfix ? getter : result;
1400 } 1410 }
1401 return const DynamicType(); 1411 return const ResolutionDynamicType();
1402 } 1412 }
1403 1413
1404 /** 1414 /**
1405 * Checks [: base[key] o= value :] for some operator o, and returns the type 1415 * Checks [: base[key] o= value :] for some operator o, and returns the type
1406 * of the result. This method also handles increment/decrement expressions 1416 * of the result. This method also handles increment/decrement expressions
1407 * like [: base[key]++ :]. 1417 * like [: base[key]++ :].
1408 */ 1418 */
1409 DartType checkIndexAssignmentOperator( 1419 ResolutionDartType checkIndexAssignmentOperator(SendSet node,
1410 SendSet node, String operatorName, Node valueNode, DartType value) { 1420 String operatorName, Node valueNode, ResolutionDartType value) {
1411 assert(invariant(node, node.isIndex)); 1421 assert(invariant(node, node.isIndex));
1412 final DartType base = analyze(node.receiver); 1422 final ResolutionDartType base = analyze(node.receiver);
1413 final Node keyNode = node.arguments.head; 1423 final Node keyNode = node.arguments.head;
1414 final DartType key = analyze(keyNode); 1424 final ResolutionDartType key = analyze(keyNode);
1415 1425
1416 // [indexGet] is the type of operator[] on [base]. 1426 // [indexGet] is the type of operator[] on [base].
1417 DartType indexGet = lookupMemberType(node, base, '[]', MemberKind.OPERATOR); 1427 ResolutionDartType indexGet =
1418 if (indexGet is FunctionType) { 1428 lookupMemberType(node, base, '[]', MemberKind.OPERATOR);
1419 FunctionType indexGetType = indexGet; 1429 if (indexGet is ResolutionFunctionType) {
1420 DartType indexGetKey = firstType(indexGetType.parameterTypes); 1430 ResolutionFunctionType indexGetType = indexGet;
1431 ResolutionDartType indexGetKey = firstType(indexGetType.parameterTypes);
1421 // Check base[key]. 1432 // Check base[key].
1422 bool validKey = checkAssignable(keyNode, key, indexGetKey); 1433 bool validKey = checkAssignable(keyNode, key, indexGetKey);
1423 1434
1424 // [element] is the type of base[key]. 1435 // [element] is the type of base[key].
1425 DartType element = indexGetType.returnType; 1436 ResolutionDartType element = indexGetType.returnType;
1426 // [operator] is the type of operator o on [element]. 1437 // [operator] is the type of operator o on [element].
1427 DartType operator = 1438 ResolutionDartType operator =
1428 lookupMemberType(node, element, operatorName, MemberKind.OPERATOR); 1439 lookupMemberType(node, element, operatorName, MemberKind.OPERATOR);
1429 if (operator is FunctionType) { 1440 if (operator is ResolutionFunctionType) {
1430 FunctionType operatorType = operator; 1441 ResolutionFunctionType operatorType = operator;
1431 1442
1432 // Check base[key] o value. 1443 // Check base[key] o value.
1433 DartType operatorArgument = firstType(operatorType.parameterTypes); 1444 ResolutionDartType operatorArgument =
1445 firstType(operatorType.parameterTypes);
1434 bool validValue = checkAssignable(valueNode, value, operatorArgument); 1446 bool validValue = checkAssignable(valueNode, value, operatorArgument);
1435 1447
1436 // [result] is the type of base[key] o value. 1448 // [result] is the type of base[key] o value.
1437 DartType result = operatorType.returnType; 1449 ResolutionDartType result = operatorType.returnType;
1438 1450
1439 // [indexSet] is the type of operator[]= on [base]. 1451 // [indexSet] is the type of operator[]= on [base].
1440 DartType indexSet = 1452 ResolutionDartType indexSet =
1441 lookupMemberType(node, base, '[]=', MemberKind.OPERATOR); 1453 lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
1442 if (indexSet is FunctionType) { 1454 if (indexSet is ResolutionFunctionType) {
1443 FunctionType indexSetType = indexSet; 1455 ResolutionFunctionType indexSetType = indexSet;
1444 DartType indexSetKey = firstType(indexSetType.parameterTypes); 1456 ResolutionDartType indexSetKey =
1445 DartType indexSetValue = secondType(indexSetType.parameterTypes); 1457 firstType(indexSetType.parameterTypes);
1458 ResolutionDartType indexSetValue =
1459 secondType(indexSetType.parameterTypes);
1446 1460
1447 if (validKey || indexGetKey != indexSetKey) { 1461 if (validKey || indexGetKey != indexSetKey) {
1448 // Only check base[key] on []= if base[key] was valid for [] or 1462 // Only check base[key] on []= if base[key] was valid for [] or
1449 // if the key types differ. 1463 // if the key types differ.
1450 checkAssignable(keyNode, key, indexSetKey); 1464 checkAssignable(keyNode, key, indexSetKey);
1451 } 1465 }
1452 // Check base[key] = result 1466 // Check base[key] = result
1453 if (validValue || !(node.isPrefix || node.isPostfix)) { 1467 if (validValue || !(node.isPrefix || node.isPostfix)) {
1454 checkAssignable(node.assignmentOperator, result, indexSetValue); 1468 checkAssignable(node.assignmentOperator, result, indexSetValue);
1455 } 1469 }
1456 } 1470 }
1457 return node.isPostfix ? element : result; 1471 return node.isPostfix ? element : result;
1458 } 1472 }
1459 } 1473 }
1460 return const DynamicType(); 1474 return const ResolutionDynamicType();
1461 } 1475 }
1462 1476
1463 visitSendSet(SendSet node) { 1477 visitSendSet(SendSet node) {
1464 Element element = elements[node]; 1478 Element element = elements[node];
1465 Identifier selector = node.selector; 1479 Identifier selector = node.selector;
1466 final name = node.assignmentOperator.source; 1480 final name = node.assignmentOperator.source;
1467 if (identical(name, '=') || identical(name, '??=')) { 1481 if (identical(name, '=') || identical(name, '??=')) {
1468 // e1 = value 1482 // e1 = value
1469 if (node.isIndex) { 1483 if (node.isIndex) {
1470 // base[key] = value 1484 // base[key] = value
1471 final DartType base = analyze(node.receiver); 1485 final ResolutionDartType base = analyze(node.receiver);
1472 final Node keyNode = node.arguments.head; 1486 final Node keyNode = node.arguments.head;
1473 final DartType key = analyze(keyNode); 1487 final ResolutionDartType key = analyze(keyNode);
1474 final Node valueNode = node.arguments.tail.head; 1488 final Node valueNode = node.arguments.tail.head;
1475 final DartType value = analyze(valueNode); 1489 final ResolutionDartType value = analyze(valueNode);
1476 DartType indexSet = 1490 ResolutionDartType indexSet =
1477 lookupMemberType(node, base, '[]=', MemberKind.OPERATOR); 1491 lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
1478 DartType indexSetValue = const DynamicType(); 1492 ResolutionDartType indexSetValue = const ResolutionDynamicType();
1479 if (indexSet is FunctionType) { 1493 if (indexSet is ResolutionFunctionType) {
1480 FunctionType indexSetType = indexSet; 1494 ResolutionFunctionType indexSetType = indexSet;
1481 DartType indexSetKey = firstType(indexSetType.parameterTypes); 1495 ResolutionDartType indexSetKey =
1496 firstType(indexSetType.parameterTypes);
1482 checkAssignable(keyNode, key, indexSetKey); 1497 checkAssignable(keyNode, key, indexSetKey);
1483 indexSetValue = secondType(indexSetType.parameterTypes); 1498 indexSetValue = secondType(indexSetType.parameterTypes);
1484 checkAssignable(node.assignmentOperator, value, indexSetValue); 1499 checkAssignable(node.assignmentOperator, value, indexSetValue);
1485 } 1500 }
1486 return identical(name, '=') 1501 return identical(name, '=')
1487 ? value 1502 ? value
1488 : types.computeLeastUpperBound(value, indexSetValue); 1503 : types.computeLeastUpperBound(value, indexSetValue);
1489 } else { 1504 } else {
1490 // target = value 1505 // target = value
1491 DartType target; 1506 ResolutionDartType target;
1492 if (analyzingInitializer) { 1507 if (analyzingInitializer) {
1493 // Field declaration `Foo target = value;` or initializer 1508 // Field declaration `Foo target = value;` or initializer
1494 // `this.target = value`. Lookup the getter `target` in the class 1509 // `this.target = value`. Lookup the getter `target` in the class
1495 // members. 1510 // members.
1496 target = computeAccessType( 1511 target = computeAccessType(
1497 node, selector.source, element, MemberKind.GETTER, 1512 node, selector.source, element, MemberKind.GETTER,
1498 lookupClassMember: true); 1513 lookupClassMember: true);
1499 } else { 1514 } else {
1500 // Normal assignment `target = value`. 1515 // Normal assignment `target = value`.
1501 target = computeAccessType( 1516 target = computeAccessType(
1502 node, selector.source, element, MemberKind.SETTER); 1517 node, selector.source, element, MemberKind.SETTER);
1503 } 1518 }
1504 final Node valueNode = node.arguments.head; 1519 final Node valueNode = node.arguments.head;
1505 final DartType value = analyze(valueNode); 1520 final ResolutionDartType value = analyze(valueNode);
1506 checkAssignable(node.assignmentOperator, value, target); 1521 checkAssignable(node.assignmentOperator, value, target);
1507 return identical(name, '=') 1522 return identical(name, '=')
1508 ? value 1523 ? value
1509 : types.computeLeastUpperBound(value, target); 1524 : types.computeLeastUpperBound(value, target);
1510 } 1525 }
1511 } else if (identical(name, '++') || identical(name, '--')) { 1526 } else if (identical(name, '++') || identical(name, '--')) {
1512 // e++ or e-- 1527 // e++ or e--
1513 String operatorName = identical(name, '++') ? '+' : '-'; 1528 String operatorName = identical(name, '++') ? '+' : '-';
1514 if (node.isIndex) { 1529 if (node.isIndex) {
1515 // base[key]++, base[key]--, ++base[key], or --base[key] 1530 // base[key]++, base[key]--, ++base[key], or --base[key]
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 break; 1571 break;
1557 case '>>=': 1572 case '>>=':
1558 operatorName = '>>'; 1573 operatorName = '>>';
1559 break; 1574 break;
1560 default: 1575 default:
1561 reporter.internalError(node, 'Unexpected assignment operator $name.'); 1576 reporter.internalError(node, 'Unexpected assignment operator $name.');
1562 } 1577 }
1563 if (node.isIndex) { 1578 if (node.isIndex) {
1564 // base[key] o= value for some operator o. 1579 // base[key] o= value for some operator o.
1565 final Node valueNode = node.arguments.tail.head; 1580 final Node valueNode = node.arguments.tail.head;
1566 final DartType value = analyze(valueNode); 1581 final ResolutionDartType value = analyze(valueNode);
1567 return checkIndexAssignmentOperator( 1582 return checkIndexAssignmentOperator(
1568 node, operatorName, valueNode, value); 1583 node, operatorName, valueNode, value);
1569 } else { 1584 } else {
1570 // target o= value for some operator o. 1585 // target o= value for some operator o.
1571 final Node valueNode = node.arguments.head; 1586 final Node valueNode = node.arguments.head;
1572 final DartType value = analyze(valueNode); 1587 final ResolutionDartType value = analyze(valueNode);
1573 return checkAssignmentOperator(node, operatorName, valueNode, value); 1588 return checkAssignmentOperator(node, operatorName, valueNode, value);
1574 } 1589 }
1575 } 1590 }
1576 } 1591 }
1577 1592
1578 DartType visitLiteralInt(LiteralInt node) { 1593 ResolutionDartType visitLiteralInt(LiteralInt node) {
1579 return intType; 1594 return intType;
1580 } 1595 }
1581 1596
1582 DartType visitLiteralDouble(LiteralDouble node) { 1597 ResolutionDartType visitLiteralDouble(LiteralDouble node) {
1583 return doubleType; 1598 return doubleType;
1584 } 1599 }
1585 1600
1586 DartType visitLiteralBool(LiteralBool node) { 1601 ResolutionDartType visitLiteralBool(LiteralBool node) {
1587 return boolType; 1602 return boolType;
1588 } 1603 }
1589 1604
1590 DartType visitLiteralString(LiteralString node) { 1605 ResolutionDartType visitLiteralString(LiteralString node) {
1591 return stringType; 1606 return stringType;
1592 } 1607 }
1593 1608
1594 DartType visitStringJuxtaposition(StringJuxtaposition node) { 1609 ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) {
1595 analyze(node.first); 1610 analyze(node.first);
1596 analyze(node.second); 1611 analyze(node.second);
1597 return stringType; 1612 return stringType;
1598 } 1613 }
1599 1614
1600 DartType visitLiteralNull(LiteralNull node) { 1615 ResolutionDartType visitLiteralNull(LiteralNull node) {
1601 return const DynamicType(); 1616 return const ResolutionDynamicType();
1602 } 1617 }
1603 1618
1604 DartType visitLiteralSymbol(LiteralSymbol node) { 1619 ResolutionDartType visitLiteralSymbol(LiteralSymbol node) {
1605 return commonElements.symbolType; 1620 return commonElements.symbolType;
1606 } 1621 }
1607 1622
1608 DartType computeConstructorType( 1623 ResolutionDartType computeConstructorType(
1609 ConstructorElement constructor, DartType type) { 1624 ConstructorElement constructor, ResolutionDartType type) {
1610 if (Elements.isUnresolved(constructor)) return const DynamicType(); 1625 if (Elements.isUnresolved(constructor))
1611 DartType constructorType = constructor.computeType(resolution); 1626 return const ResolutionDynamicType();
1612 if (identical(type.kind, TypeKind.INTERFACE)) { 1627 ResolutionDartType constructorType = constructor.computeType(resolution);
1628 if (identical(type.kind, ResolutionTypeKind.INTERFACE)) {
1613 if (constructor.isSynthesized) { 1629 if (constructor.isSynthesized) {
1614 // TODO(johnniwinther): Remove this when synthesized constructors handle 1630 // TODO(johnniwinther): Remove this when synthesized constructors handle
1615 // type variables correctly. 1631 // type variables correctly.
1616 InterfaceType interfaceType = type; 1632 ResolutionInterfaceType interfaceType = type;
1617 ClassElement receiverElement = interfaceType.element; 1633 ClassElement receiverElement = interfaceType.element;
1618 while (receiverElement.isMixinApplication) { 1634 while (receiverElement.isMixinApplication) {
1619 receiverElement = receiverElement.supertype.element; 1635 receiverElement = receiverElement.supertype.element;
1620 } 1636 }
1621 constructorType = constructorType 1637 constructorType = constructorType
1622 .substByContext(interfaceType.asInstanceOf(receiverElement)); 1638 .substByContext(interfaceType.asInstanceOf(receiverElement));
1623 } else { 1639 } else {
1624 constructorType = constructorType.substByContext(type); 1640 constructorType = constructorType.substByContext(type);
1625 } 1641 }
1626 } 1642 }
1627 return constructorType; 1643 return constructorType;
1628 } 1644 }
1629 1645
1630 DartType visitNewExpression(NewExpression node) { 1646 ResolutionDartType visitNewExpression(NewExpression node) {
1631 Element element = elements[node.send]; 1647 Element element = elements[node.send];
1632 if (Elements.isUnresolved(element)) return const DynamicType(); 1648 if (Elements.isUnresolved(element)) return const ResolutionDynamicType();
1633 1649
1634 checkPrivateAccess(node, element, element.name); 1650 checkPrivateAccess(node, element, element.name);
1635 1651
1636 DartType newType = elements.getType(node); 1652 ResolutionDartType newType = elements.getType(node);
1637 assert(invariant(node, newType != null, 1653 assert(invariant(node, newType != null,
1638 message: "No new type registered in $elements.")); 1654 message: "No new type registered in $elements."));
1639 DartType constructorType = computeConstructorType(element, newType); 1655 ResolutionDartType constructorType =
1656 computeConstructorType(element, newType);
1640 analyzeArguments(node.send, element, constructorType); 1657 analyzeArguments(node.send, element, constructorType);
1641 return newType; 1658 return newType;
1642 } 1659 }
1643 1660
1644 DartType visitLiteralList(LiteralList node) { 1661 ResolutionDartType visitLiteralList(LiteralList node) {
1645 InterfaceType listType = elements.getType(node); 1662 ResolutionInterfaceType listType = elements.getType(node);
1646 DartType listElementType = firstType(listType.typeArguments); 1663 ResolutionDartType listElementType = firstType(listType.typeArguments);
1647 for (Link<Node> link = node.elements.nodes; 1664 for (Link<Node> link = node.elements.nodes;
1648 !link.isEmpty; 1665 !link.isEmpty;
1649 link = link.tail) { 1666 link = link.tail) {
1650 Node element = link.head; 1667 Node element = link.head;
1651 DartType elementType = analyze(element); 1668 ResolutionDartType elementType = analyze(element);
1652 checkAssignable(element, elementType, listElementType, 1669 checkAssignable(element, elementType, listElementType,
1653 isConst: node.isConst); 1670 isConst: node.isConst);
1654 } 1671 }
1655 return listType; 1672 return listType;
1656 } 1673 }
1657 1674
1658 visitNodeList(NodeList node) { 1675 visitNodeList(NodeList node) {
1659 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { 1676 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
1660 analyzeUntyped(link.head, inInitializer: analyzingInitializer); 1677 analyzeUntyped(link.head, inInitializer: analyzingInitializer);
1661 } 1678 }
(...skipping 13 matching lines...) Expand all
1675 if (identical(node.beginToken.stringValue, 'native')) { 1692 if (identical(node.beginToken.stringValue, 'native')) {
1676 return; 1693 return;
1677 } 1694 }
1678 1695
1679 final Node expression = node.expression; 1696 final Node expression = node.expression;
1680 1697
1681 // Executing a return statement return e; [...] It is a static type warning 1698 // Executing a return statement return e; [...] It is a static type warning
1682 // if the type of e may not be assigned to the declared return type of the 1699 // if the type of e may not be assigned to the declared return type of the
1683 // immediately enclosing function. 1700 // immediately enclosing function.
1684 if (expression != null) { 1701 if (expression != null) {
1685 DartType expressionType = analyze(expression); 1702 ResolutionDartType expressionType = analyze(expression);
1686 if (executableContext.isGenerativeConstructor) { 1703 if (executableContext.isGenerativeConstructor) {
1687 // The resolver already emitted an error for this expression. 1704 // The resolver already emitted an error for this expression.
1688 } else { 1705 } else {
1689 if (currentAsyncMarker == AsyncMarker.ASYNC) { 1706 if (currentAsyncMarker == AsyncMarker.ASYNC) {
1690 expressionType = 1707 expressionType =
1691 commonElements.futureType(types.flatten(expressionType)); 1708 commonElements.futureType(types.flatten(expressionType));
1692 } 1709 }
1693 if (expectedReturnType.isVoid && 1710 if (expectedReturnType.isVoid &&
1694 !types.isAssignable(expressionType, const VoidType())) { 1711 !types.isAssignable(expressionType, const ResolutionVoidType())) {
1695 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); 1712 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID);
1696 } else { 1713 } else {
1697 checkAssignable(expression, expressionType, expectedReturnType); 1714 checkAssignable(expression, expressionType, expectedReturnType);
1698 } 1715 }
1699 } 1716 }
1700 } else if (currentAsyncMarker != AsyncMarker.SYNC) { 1717 } else if (currentAsyncMarker != AsyncMarker.SYNC) {
1701 // `return;` is allowed. 1718 // `return;` is allowed.
1702 } else if (!types.isAssignable(expectedReturnType, const VoidType())) { 1719 } else if (!types.isAssignable(
1720 expectedReturnType, const ResolutionVoidType())) {
1703 // Let f be the function immediately enclosing a return statement of the 1721 // Let f be the function immediately enclosing a return statement of the
1704 // form 'return;' It is a static warning if both of the following 1722 // form 'return;' It is a static warning if both of the following
1705 // conditions hold: 1723 // conditions hold:
1706 // - f is not a generative constructor. 1724 // - f is not a generative constructor.
1707 // - The return type of f may not be assigned to void. 1725 // - The return type of f may not be assigned to void.
1708 reportTypeWarning( 1726 reportTypeWarning(
1709 node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType}); 1727 node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType});
1710 } 1728 }
1711 } 1729 }
1712 1730
1713 DartType visitThrow(Throw node) { 1731 ResolutionDartType visitThrow(Throw node) {
1714 // TODO(johnniwinther): Handle reachability. 1732 // TODO(johnniwinther): Handle reachability.
1715 analyze(node.expression); 1733 analyze(node.expression);
1716 return const DynamicType(); 1734 return const ResolutionDynamicType();
1717 } 1735 }
1718 1736
1719 DartType visitAwait(Await node) { 1737 ResolutionDartType visitAwait(Await node) {
1720 DartType expressionType = analyze(node.expression); 1738 ResolutionDartType expressionType = analyze(node.expression);
1721 if (resolution.target.supportsAsyncAwait) { 1739 if (resolution.target.supportsAsyncAwait) {
1722 return types.flatten(expressionType); 1740 return types.flatten(expressionType);
1723 } else { 1741 } else {
1724 return const DynamicType(); 1742 return const ResolutionDynamicType();
1725 } 1743 }
1726 } 1744 }
1727 1745
1728 DartType visitYield(Yield node) { 1746 ResolutionDartType visitYield(Yield node) {
1729 DartType resultType = analyze(node.expression); 1747 ResolutionDartType resultType = analyze(node.expression);
1730 if (!node.hasStar) { 1748 if (!node.hasStar) {
1731 if (currentAsyncMarker.isAsync) { 1749 if (currentAsyncMarker.isAsync) {
1732 resultType = commonElements.streamType(resultType); 1750 resultType = commonElements.streamType(resultType);
1733 } else { 1751 } else {
1734 resultType = commonElements.iterableType(resultType); 1752 resultType = commonElements.iterableType(resultType);
1735 } 1753 }
1736 } else { 1754 } else {
1737 if (currentAsyncMarker.isAsync) { 1755 if (currentAsyncMarker.isAsync) {
1738 // The static type of expression must be assignable to Stream. 1756 // The static type of expression must be assignable to Stream.
1739 checkAssignable(node, resultType, commonElements.streamType()); 1757 checkAssignable(node, resultType, commonElements.streamType());
1740 } else { 1758 } else {
1741 // The static type of expression must be assignable to Iterable. 1759 // The static type of expression must be assignable to Iterable.
1742 checkAssignable(node, resultType, commonElements.iterableType()); 1760 checkAssignable(node, resultType, commonElements.iterableType());
1743 } 1761 }
1744 } 1762 }
1745 // The static type of the result must be assignable to the declared type. 1763 // The static type of the result must be assignable to the declared type.
1746 checkAssignable(node, resultType, expectedReturnType); 1764 checkAssignable(node, resultType, expectedReturnType);
1747 } 1765 }
1748 1766
1749 DartType visitTypeAnnotation(TypeAnnotation node) { 1767 ResolutionDartType visitTypeAnnotation(TypeAnnotation node) {
1750 return elements.getType(node); 1768 return elements.getType(node);
1751 } 1769 }
1752 1770
1753 DartType analyzeVariableTypeAnnotation(VariableDefinitions node) { 1771 ResolutionDartType analyzeVariableTypeAnnotation(VariableDefinitions node) {
1754 DartType type = analyzeWithDefault(node.type, const DynamicType()); 1772 ResolutionDartType type =
1773 analyzeWithDefault(node.type, const ResolutionDynamicType());
1755 if (type.isVoid) { 1774 if (type.isVoid) {
1756 reportTypeWarning(node.type, MessageKind.VOID_VARIABLE); 1775 reportTypeWarning(node.type, MessageKind.VOID_VARIABLE);
1757 type = const DynamicType(); 1776 type = const ResolutionDynamicType();
1758 } 1777 }
1759 return type; 1778 return type;
1760 } 1779 }
1761 1780
1762 void analyzeVariableInitializer( 1781 void analyzeVariableInitializer(
1763 Spannable spannable, DartType declaredType, Node initializer) { 1782 Spannable spannable, ResolutionDartType declaredType, Node initializer) {
1764 if (initializer == null) return; 1783 if (initializer == null) return;
1765 1784
1766 DartType expressionType = analyzeNonVoid(initializer); 1785 ResolutionDartType expressionType = analyzeNonVoid(initializer);
1767 checkAssignable(spannable, expressionType, declaredType); 1786 checkAssignable(spannable, expressionType, declaredType);
1768 } 1787 }
1769 1788
1770 visitVariableDefinitions(VariableDefinitions node) { 1789 visitVariableDefinitions(VariableDefinitions node) {
1771 DartType type = analyzeVariableTypeAnnotation(node); 1790 ResolutionDartType type = analyzeVariableTypeAnnotation(node);
1772 for (Link<Node> link = node.definitions.nodes; 1791 for (Link<Node> link = node.definitions.nodes;
1773 !link.isEmpty; 1792 !link.isEmpty;
1774 link = link.tail) { 1793 link = link.tail) {
1775 Node definition = link.head; 1794 Node definition = link.head;
1776 invariant(definition, definition is Identifier || definition is SendSet, 1795 invariant(definition, definition is Identifier || definition is SendSet,
1777 message: 'expected identifier or initialization'); 1796 message: 'expected identifier or initialization');
1778 if (definition is SendSet) { 1797 if (definition is SendSet) {
1779 SendSet initialization = definition; 1798 SendSet initialization = definition;
1780 analyzeVariableInitializer(initialization.assignmentOperator, type, 1799 analyzeVariableInitializer(initialization.assignmentOperator, type,
1781 initialization.arguments.head); 1800 initialization.arguments.head);
(...skipping 10 matching lines...) Expand all
1792 // } 1811 // }
1793 } 1812 }
1794 } 1813 }
1795 } 1814 }
1796 1815
1797 visitWhile(While node) { 1816 visitWhile(While node) {
1798 checkCondition(node.condition); 1817 checkCondition(node.condition);
1799 analyzeUntyped(node.body); 1818 analyzeUntyped(node.body);
1800 } 1819 }
1801 1820
1802 DartType visitParenthesizedExpression(ParenthesizedExpression node) { 1821 ResolutionDartType visitParenthesizedExpression(
1822 ParenthesizedExpression node) {
1803 Expression expression = node.expression; 1823 Expression expression = node.expression;
1804 DartType type = analyze(expression); 1824 ResolutionDartType type = analyze(expression);
1805 for (TypePromotion typePromotion in getShownTypePromotionsFor(expression)) { 1825 for (TypePromotion typePromotion in getShownTypePromotionsFor(expression)) {
1806 showTypePromotion(node, typePromotion); 1826 showTypePromotion(node, typePromotion);
1807 } 1827 }
1808 return type; 1828 return type;
1809 } 1829 }
1810 1830
1811 DartType visitConditional(Conditional node) { 1831 ResolutionDartType visitConditional(Conditional node) {
1812 Expression condition = node.condition; 1832 Expression condition = node.condition;
1813 Expression thenExpression = node.thenExpression; 1833 Expression thenExpression = node.thenExpression;
1814 1834
1815 checkCondition(condition); 1835 checkCondition(condition);
1816 1836
1817 DartType thenType = analyzeInPromotedContext(condition, thenExpression); 1837 ResolutionDartType thenType =
1838 analyzeInPromotedContext(condition, thenExpression);
1818 1839
1819 DartType elseType = analyze(node.elseExpression); 1840 ResolutionDartType elseType = analyze(node.elseExpression);
1820 return types.computeLeastUpperBound(thenType, elseType); 1841 return types.computeLeastUpperBound(thenType, elseType);
1821 } 1842 }
1822 1843
1823 visitStringInterpolation(StringInterpolation node) { 1844 visitStringInterpolation(StringInterpolation node) {
1824 node.visitChildren(this); 1845 node.visitChildren(this);
1825 return stringType; 1846 return stringType;
1826 } 1847 }
1827 1848
1828 visitStringInterpolationPart(StringInterpolationPart node) { 1849 visitStringInterpolationPart(StringInterpolationPart node) {
1829 node.visitChildren(this); 1850 node.visitChildren(this);
1830 return stringType; 1851 return stringType;
1831 } 1852 }
1832 1853
1833 visitEmptyStatement(EmptyStatement node) { 1854 visitEmptyStatement(EmptyStatement node) {
1834 // Nothing to do here. 1855 // Nothing to do here.
1835 } 1856 }
1836 1857
1837 visitBreakStatement(BreakStatement node) { 1858 visitBreakStatement(BreakStatement node) {
1838 // Nothing to do here. 1859 // Nothing to do here.
1839 } 1860 }
1840 1861
1841 visitContinueStatement(ContinueStatement node) { 1862 visitContinueStatement(ContinueStatement node) {
1842 // Nothing to do here. 1863 // Nothing to do here.
1843 } 1864 }
1844 1865
1845 DartType computeForInElementType(ForIn node) { 1866 ResolutionDartType computeForInElementType(ForIn node) {
1846 VariableDefinitions declaredIdentifier = 1867 VariableDefinitions declaredIdentifier =
1847 node.declaredIdentifier.asVariableDefinitions(); 1868 node.declaredIdentifier.asVariableDefinitions();
1848 if (declaredIdentifier != null) { 1869 if (declaredIdentifier != null) {
1849 return analyzeWithDefault(declaredIdentifier.type, const DynamicType()); 1870 return analyzeWithDefault(
1871 declaredIdentifier.type, const ResolutionDynamicType());
1850 } else { 1872 } else {
1851 return analyze(node.declaredIdentifier); 1873 return analyze(node.declaredIdentifier);
1852 } 1874 }
1853 } 1875 }
1854 1876
1855 visitAsyncForIn(AsyncForIn node) { 1877 visitAsyncForIn(AsyncForIn node) {
1856 DartType elementType = computeForInElementType(node); 1878 ResolutionDartType elementType = computeForInElementType(node);
1857 DartType expressionType = analyze(node.expression); 1879 ResolutionDartType expressionType = analyze(node.expression);
1858 if (resolution.target.supportsAsyncAwait) { 1880 if (resolution.target.supportsAsyncAwait) {
1859 DartType streamOfDynamic = commonElements.streamType(); 1881 ResolutionDartType streamOfDynamic = commonElements.streamType();
1860 if (!types.isAssignable(expressionType, streamOfDynamic)) { 1882 if (!types.isAssignable(expressionType, streamOfDynamic)) {
1861 reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE, 1883 reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE,
1862 {'fromType': expressionType, 'toType': streamOfDynamic}, 1884 {'fromType': expressionType, 'toType': streamOfDynamic},
1863 isHint: true); 1885 isHint: true);
1864 } else { 1886 } else {
1865 InterfaceType interfaceType = 1887 ResolutionInterfaceType interfaceType =
1866 Types.computeInterfaceType(resolution, expressionType); 1888 Types.computeInterfaceType(resolution, expressionType);
1867 if (interfaceType != null) { 1889 if (interfaceType != null) {
1868 InterfaceType streamType = 1890 ResolutionInterfaceType streamType =
1869 interfaceType.asInstanceOf(streamOfDynamic.element); 1891 interfaceType.asInstanceOf(streamOfDynamic.element);
1870 if (streamType != null) { 1892 if (streamType != null) {
1871 DartType streamElementType = streamType.typeArguments.first; 1893 ResolutionDartType streamElementType =
1894 streamType.typeArguments.first;
1872 if (!types.isAssignable(streamElementType, elementType)) { 1895 if (!types.isAssignable(streamElementType, elementType)) {
1873 reportMessage( 1896 reportMessage(
1874 node.expression, 1897 node.expression,
1875 MessageKind.FORIN_NOT_ASSIGNABLE, 1898 MessageKind.FORIN_NOT_ASSIGNABLE,
1876 { 1899 {
1877 'currentType': streamElementType, 1900 'currentType': streamElementType,
1878 'expressionType': expressionType, 1901 'expressionType': expressionType,
1879 'elementType': elementType 1902 'elementType': elementType
1880 }, 1903 },
1881 isHint: true); 1904 isHint: true);
1882 } 1905 }
1883 } 1906 }
1884 } 1907 }
1885 } 1908 }
1886 } 1909 }
1887 analyzeUntyped(node.body); 1910 analyzeUntyped(node.body);
1888 } 1911 }
1889 1912
1890 visitSyncForIn(SyncForIn node) { 1913 visitSyncForIn(SyncForIn node) {
1891 DartType elementType = computeForInElementType(node); 1914 ResolutionDartType elementType = computeForInElementType(node);
1892 DartType expressionType = analyze(node.expression); 1915 ResolutionDartType expressionType = analyze(node.expression);
1893 DartType iteratorType = lookupMemberType(node.expression, expressionType, 1916 ResolutionDartType iteratorType = lookupMemberType(node.expression,
1894 Identifiers.iterator, MemberKind.GETTER); 1917 expressionType, Identifiers.iterator, MemberKind.GETTER);
1895 DartType currentType = lookupMemberType( 1918 ResolutionDartType currentType = lookupMemberType(
1896 node.expression, iteratorType, Identifiers.current, MemberKind.GETTER, 1919 node.expression, iteratorType, Identifiers.current, MemberKind.GETTER,
1897 isHint: true); 1920 isHint: true);
1898 if (!types.isAssignable(currentType, elementType)) { 1921 if (!types.isAssignable(currentType, elementType)) {
1899 reportMessage( 1922 reportMessage(
1900 node.expression, 1923 node.expression,
1901 MessageKind.FORIN_NOT_ASSIGNABLE, 1924 MessageKind.FORIN_NOT_ASSIGNABLE,
1902 { 1925 {
1903 'currentType': currentType, 1926 'currentType': currentType,
1904 'expressionType': expressionType, 1927 'expressionType': expressionType,
1905 'elementType': elementType 1928 'elementType': elementType
1906 }, 1929 },
1907 isHint: true); 1930 isHint: true);
1908 } 1931 }
1909 analyzeUntyped(node.body); 1932 analyzeUntyped(node.body);
1910 } 1933 }
1911 1934
1912 visitLabeledStatement(LabeledStatement node) { 1935 visitLabeledStatement(LabeledStatement node) {
1913 analyzeUntyped(node.statement); 1936 analyzeUntyped(node.statement);
1914 } 1937 }
1915 1938
1916 visitLiteralMap(LiteralMap node) { 1939 visitLiteralMap(LiteralMap node) {
1917 InterfaceType mapType = elements.getType(node); 1940 ResolutionInterfaceType mapType = elements.getType(node);
1918 DartType mapKeyType = firstType(mapType.typeArguments); 1941 ResolutionDartType mapKeyType = firstType(mapType.typeArguments);
1919 DartType mapValueType = secondType(mapType.typeArguments); 1942 ResolutionDartType mapValueType = secondType(mapType.typeArguments);
1920 bool isConst = node.isConst; 1943 bool isConst = node.isConst;
1921 for (Link<Node> link = node.entries.nodes; 1944 for (Link<Node> link = node.entries.nodes;
1922 !link.isEmpty; 1945 !link.isEmpty;
1923 link = link.tail) { 1946 link = link.tail) {
1924 LiteralMapEntry entry = link.head; 1947 LiteralMapEntry entry = link.head;
1925 DartType keyType = analyze(entry.key); 1948 ResolutionDartType keyType = analyze(entry.key);
1926 checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst); 1949 checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst);
1927 DartType valueType = analyze(entry.value); 1950 ResolutionDartType valueType = analyze(entry.value);
1928 checkAssignable(entry.value, valueType, mapValueType, isConst: isConst); 1951 checkAssignable(entry.value, valueType, mapValueType, isConst: isConst);
1929 } 1952 }
1930 return mapType; 1953 return mapType;
1931 } 1954 }
1932 1955
1933 visitNamedArgument(NamedArgument node) { 1956 visitNamedArgument(NamedArgument node) {
1934 // Named arguments are visited as part of analyzing invocations of 1957 // Named arguments are visited as part of analyzing invocations of
1935 // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither 1958 // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither
1936 // found in the enclosing scope nor through lookup on 'this' or 1959 // found in the enclosing scope nor through lookup on 'this' or
1937 // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on 1960 // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on
1938 // the static type of 'x'. 1961 // the static type of 'x'.
1939 return analyze(node.expression); 1962 return analyze(node.expression);
1940 } 1963 }
1941 1964
1942 visitSwitchStatement(SwitchStatement node) { 1965 visitSwitchStatement(SwitchStatement node) {
1943 // TODO(johnniwinther): Handle reachability based on reachability of 1966 // TODO(johnniwinther): Handle reachability based on reachability of
1944 // switch cases. 1967 // switch cases.
1945 // TODO(johnniwinther): Provide hint of duplicate case constants. 1968 // TODO(johnniwinther): Provide hint of duplicate case constants.
1946 1969
1947 DartType expressionType = analyze(node.expression); 1970 ResolutionDartType expressionType = analyze(node.expression);
1948 1971
1949 // Check that all the case expressions are assignable to the expression. 1972 // Check that all the case expressions are assignable to the expression.
1950 bool hasDefaultCase = false; 1973 bool hasDefaultCase = false;
1951 for (SwitchCase switchCase in node.cases) { 1974 for (SwitchCase switchCase in node.cases) {
1952 if (switchCase.isDefaultCase) { 1975 if (switchCase.isDefaultCase) {
1953 hasDefaultCase = true; 1976 hasDefaultCase = true;
1954 } 1977 }
1955 for (Node labelOrCase in switchCase.labelsAndCases) { 1978 for (Node labelOrCase in switchCase.labelsAndCases) {
1956 CaseMatch caseMatch = labelOrCase.asCaseMatch(); 1979 CaseMatch caseMatch = labelOrCase.asCaseMatch();
1957 if (caseMatch == null) continue; 1980 if (caseMatch == null) continue;
1958 1981
1959 DartType caseType = analyze(caseMatch.expression); 1982 ResolutionDartType caseType = analyze(caseMatch.expression);
1960 checkAssignable(caseMatch, expressionType, caseType); 1983 checkAssignable(caseMatch, expressionType, caseType);
1961 } 1984 }
1962 1985
1963 analyzeUntyped(switchCase); 1986 analyzeUntyped(switchCase);
1964 } 1987 }
1965 1988
1966 if (!hasDefaultCase && expressionType.isEnumType) { 1989 if (!hasDefaultCase && expressionType.isEnumType) {
1967 compiler.enqueuer.resolution.addDeferredAction(executableContext, () { 1990 compiler.enqueuer.resolution.addDeferredAction(executableContext, () {
1968 Map<ConstantValue, FieldElement> enumValues = 1991 Map<ConstantValue, FieldElement> enumValues =
1969 <ConstantValue, FieldElement>{}; 1992 <ConstantValue, FieldElement>{};
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2026 2049
2027 visitTypedef(Typedef node) { 2050 visitTypedef(Typedef node) {
2028 // Do not typecheck [Typedef] nodes. 2051 // Do not typecheck [Typedef] nodes.
2029 } 2052 }
2030 2053
2031 visitNode(Node node) { 2054 visitNode(Node node) {
2032 reporter.internalError(node, 2055 reporter.internalError(node,
2033 'Unexpected node ${node.getObjectDescription()} in the type checker.'); 2056 'Unexpected node ${node.getObjectDescription()} in the type checker.');
2034 } 2057 }
2035 } 2058 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/type_builder.dart ('k') | pkg/compiler/lib/src/types/abstract_value_domain.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698