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

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Issue 2902683004: Populate TypeInferrerImpl.closureContext more frequently. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// This file declares a "shadow hierarchy" of concrete classes which extend 5 /// This file declares a "shadow hierarchy" of concrete classes which extend
6 /// the kernel class hierarchy, adding methods and fields needed by the 6 /// the kernel class hierarchy, adding methods and fields needed by the
7 /// BodyBuilder. 7 /// BodyBuilder.
8 /// 8 ///
9 /// Instances of these classes may be created using the factory methods in 9 /// Instances of these classes may be created using the factory methods in
10 /// `ast_factory.dart`. 10 /// `ast_factory.dart`.
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 /// form. 339 /// form.
340 class KernelFunctionDeclaration extends FunctionDeclaration 340 class KernelFunctionDeclaration extends FunctionDeclaration
341 implements KernelStatement { 341 implements KernelStatement {
342 KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function) 342 KernelFunctionDeclaration(VariableDeclaration variable, FunctionNode function)
343 : super(variable, function); 343 : super(variable, function);
344 344
345 @override 345 @override
346 void _inferStatement(KernelTypeInferrer inferrer) { 346 void _inferStatement(KernelTypeInferrer inferrer) {
347 inferrer.listener.functionDeclarationEnter(this); 347 inferrer.listener.functionDeclarationEnter(this);
348 var oldClosureContext = inferrer.closureContext; 348 var oldClosureContext = inferrer.closureContext;
349 inferrer.closureContext = null; 349 inferrer.closureContext =
350 new ClosureContext(inferrer, function.asyncMarker, function.returnType);
350 inferrer.inferStatement(function.body); 351 inferrer.inferStatement(function.body);
351 inferrer.closureContext = oldClosureContext; 352 inferrer.closureContext = oldClosureContext;
352 inferrer.listener.functionDeclarationExit(this); 353 inferrer.listener.functionDeclarationExit(this);
353 } 354 }
354 } 355 }
355 356
356 /// Concrete shadow object representing a function expression in kernel form. 357 /// Concrete shadow object representing a function expression in kernel form.
357 class KernelFunctionExpression extends FunctionExpression 358 class KernelFunctionExpression extends FunctionExpression
358 implements KernelExpression { 359 implements KernelExpression {
359 KernelFunctionExpression(FunctionNode function) : super(function); 360 KernelFunctionExpression(FunctionNode function) : super(function);
360 361
361 @override 362 @override
362 DartType _inferExpression( 363 DartType _inferExpression(
363 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { 364 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
364 var asyncMarker = function.asyncMarker;
365 bool isAsync = asyncMarker == AsyncMarker.Async ||
366 asyncMarker == AsyncMarker.AsyncStar;
367 bool isGenerator = asyncMarker == AsyncMarker.SyncStar ||
368 asyncMarker == AsyncMarker.AsyncStar;
369 typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) || 365 typeNeeded = inferrer.listener.functionExpressionEnter(this, typeContext) ||
370 typeNeeded; 366 typeNeeded;
371 // TODO(paulberry): do we also need to visit default parameter values? 367 // TODO(paulberry): do we also need to visit default parameter values?
372 368
373 // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with 369 // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with
374 // `n`=0 if there are no type parameters). 370 // `n`=0 if there are no type parameters).
375 List<TypeParameter> typeParameters = function.typeParameters; 371 List<TypeParameter> typeParameters = function.typeParameters;
376 372
377 // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure 373 // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure
378 // (including required, positional optional, and named optional parameters). 374 // (including required, positional optional, and named optional parameters).
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 inferrer.instrumentation?.record( 433 inferrer.instrumentation?.record(
438 Uri.parse(inferrer.uri), 434 Uri.parse(inferrer.uri),
439 formal.fileOffset, 435 formal.fileOffset,
440 'type', 436 'type',
441 new InstrumentationValueForType(inferredType)); 437 new InstrumentationValueForType(inferredType));
442 formal.type = inferredType; 438 formal.type = inferredType;
443 } 439 }
444 } 440 }
445 } 441 }
446 442
447 // Let `N` be `N[T/S]`, adjusted accordingly if the closure is declared 443 // Let `N'` be `N[T/S]`. The [ClosureContext] constructor will adjust
448 // with `async`, `async*`, or `sync*`. 444 // accordingly if the closure is declared with `async`, `async*`, or
445 // `sync*`.
449 if (returnContext != null) { 446 if (returnContext != null) {
450 returnContext = substitution.substituteType(returnContext); 447 returnContext = substitution.substituteType(returnContext);
451 } 448 }
452 if (isGenerator) {
453 if (isAsync) {
454 returnContext = inferrer.getTypeArgumentOf(
455 returnContext, inferrer.coreTypes.streamClass);
456 } else {
457 returnContext = inferrer.getTypeArgumentOf(
458 returnContext, inferrer.coreTypes.iterableClass);
459 }
460 } else if (isAsync) {
461 // TODO(paulberry): do we have to handle FutureOr<> here?
462 returnContext = inferrer.getTypeArgumentOf(
463 returnContext, inferrer.coreTypes.futureClass);
464 }
465 449
466 // Apply type inference to `B` in return context `N’`, with any references 450 // Apply type inference to `B` in return context `N’`, with any references
467 // to `xi` in `B` having type `Pi`. This produces `B’`. 451 // to `xi` in `B` having type `Pi`. This produces `B’`.
468 bool isExpressionFunction = function.body is ReturnStatement; 452 bool isExpressionFunction = function.body is ReturnStatement;
469 bool needToSetReturnType = isExpressionFunction || inferrer.strongMode; 453 bool needToSetReturnType = isExpressionFunction || inferrer.strongMode;
470 ClosureContext oldClosureContext = inferrer.closureContext; 454 ClosureContext oldClosureContext = inferrer.closureContext;
471 inferrer.closureContext = 455 ClosureContext closureContext =
472 new ClosureContext(isAsync, isGenerator, returnContext); 456 new ClosureContext(inferrer, function.asyncMarker, returnContext);
457 inferrer.closureContext = closureContext;
473 inferrer.inferStatement(function.body); 458 inferrer.inferStatement(function.body);
474 459
475 // If the closure is declared with `async*` or `sync*`, let `M` be the least 460 // If the closure is declared with `async*` or `sync*`, let `M` be the least
476 // upper bound of the types of the `yield` expressions in `B’`, or `void` if 461 // upper bound of the types of the `yield` expressions in `B’`, or `void` if
477 // `B’` contains no `yield` expressions. Otherwise, let `M` be the least 462 // `B’` contains no `yield` expressions. Otherwise, let `M` be the least
478 // upper bound of the types of the `return` expressions in `B’`, or `void` 463 // upper bound of the types of the `return` expressions in `B’`, or `void`
479 // if `B’` contains no `return` expressions. 464 // if `B’` contains no `return` expressions.
480 DartType inferredReturnType; 465 DartType inferredReturnType;
481 if (needToSetReturnType || typeNeeded) { 466 if (needToSetReturnType || typeNeeded) {
482 inferredReturnType = inferrer.inferReturnType( 467 inferredReturnType =
483 inferrer.closureContext.inferredReturnType, isExpressionFunction); 468 closureContext.inferReturnType(inferrer, isExpressionFunction);
484 if (!isExpressionFunction &&
485 returnContext != null &&
486 (!inferrer.typeSchemaEnvironment
487 .isSubtypeOf(inferredReturnType, returnContext) ||
488 returnContext is VoidType)) {
489 // For block-bodied functions, if the inferred return type isn't a
490 // subtype of the context (or the context is void), we use the context.
491 // TODO(paulberry): this is inherited from analyzer; it's not part of
492 // the spec. See also dartbug.com/29606.
493 inferredReturnType = greatestClosure(inferrer.coreTypes, returnContext);
494 }
495
496 // Let `M’` be `M`, adjusted accordingly if the closure is declared with
497 // `async`, `async*`, or `sync*`.
498 if (isGenerator) {
499 if (isAsync) {
500 inferredReturnType = inferrer.wrapType(
501 inferredReturnType, inferrer.coreTypes.streamClass);
502 } else {
503 inferredReturnType = inferrer.wrapType(
504 inferredReturnType, inferrer.coreTypes.iterableClass);
505 }
506 } else if (isAsync) {
507 inferredReturnType = inferrer.wrapFutureType(inferredReturnType);
508 }
509 } 469 }
510 470
511 // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with 471 // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with
512 // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi` 472 // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi`
513 // denoted as optional or named parameters, if appropriate). 473 // denoted as optional or named parameters, if appropriate).
514 if (needToSetReturnType) { 474 if (needToSetReturnType) {
515 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, 475 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset,
516 'returnType', new InstrumentationValueForType(inferredReturnType)); 476 'returnType', new InstrumentationValueForType(inferredReturnType));
517 function.returnType = inferredReturnType; 477 function.returnType = inferredReturnType;
518 } 478 }
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 } 760 }
801 761
802 /// Concrete shadow object representing a return statement in kernel form. 762 /// Concrete shadow object representing a return statement in kernel form.
803 class KernelReturnStatement extends ReturnStatement implements KernelStatement { 763 class KernelReturnStatement extends ReturnStatement implements KernelStatement {
804 KernelReturnStatement([Expression expression]) : super(expression); 764 KernelReturnStatement([Expression expression]) : super(expression);
805 765
806 @override 766 @override
807 void _inferStatement(KernelTypeInferrer inferrer) { 767 void _inferStatement(KernelTypeInferrer inferrer) {
808 inferrer.listener.returnStatementEnter(this); 768 inferrer.listener.returnStatementEnter(this);
809 var closureContext = inferrer.closureContext; 769 var closureContext = inferrer.closureContext;
810 var typeContext = closureContext != null && !closureContext.isGenerator 770 var typeContext =
811 ? closureContext.returnContext 771 !closureContext.isGenerator ? closureContext.returnContext : null;
812 : null;
813 var inferredType = expression != null 772 var inferredType = expression != null
814 ? inferrer.inferExpression( 773 ? inferrer.inferExpression(expression, typeContext, true)
815 expression, typeContext, closureContext != null)
816 : const VoidType(); 774 : const VoidType();
817 // Analyzer treats bare `return` statements as having no effect on the 775 // Analyzer treats bare `return` statements as having no effect on the
818 // inferred type of the closure. TODO(paulberry): is this what we want 776 // inferred type of the closure. TODO(paulberry): is this what we want
819 // for Fasta? 777 // for Fasta?
820 if (expression != null) { 778 if (expression != null) {
821 closureContext?.handleReturn(inferrer, inferredType); 779 closureContext.handleReturn(inferrer, inferredType);
822 } 780 }
823 inferrer.listener.returnStatementExit(this); 781 inferrer.listener.returnStatementExit(this);
824 } 782 }
825 } 783 }
826 784
827 /// Common base class for shadow objects representing statements in kernel 785 /// Common base class for shadow objects representing statements in kernel
828 /// form. 786 /// form.
829 abstract class KernelStatement extends Statement { 787 abstract class KernelStatement extends Statement {
830 /// Calls back to [inferrer] to perform type inference for whatever concrete 788 /// Calls back to [inferrer] to perform type inference for whatever concrete
831 /// type of [KernelStatement] this is. 789 /// type of [KernelStatement] this is.
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 1305
1348 /// Concrete shadow object representing a yield statement in kernel form. 1306 /// Concrete shadow object representing a yield statement in kernel form.
1349 class KernelYieldStatement extends YieldStatement implements KernelStatement { 1307 class KernelYieldStatement extends YieldStatement implements KernelStatement {
1350 KernelYieldStatement(Expression expression, {bool isYieldStar: false}) 1308 KernelYieldStatement(Expression expression, {bool isYieldStar: false})
1351 : super(expression, isYieldStar: isYieldStar); 1309 : super(expression, isYieldStar: isYieldStar);
1352 1310
1353 @override 1311 @override
1354 void _inferStatement(KernelTypeInferrer inferrer) { 1312 void _inferStatement(KernelTypeInferrer inferrer) {
1355 inferrer.listener.yieldStatementEnter(this); 1313 inferrer.listener.yieldStatementEnter(this);
1356 var closureContext = inferrer.closureContext; 1314 var closureContext = inferrer.closureContext;
1357 var typeContext = closureContext != null && closureContext.isGenerator 1315 var typeContext =
1358 ? closureContext.returnContext 1316 closureContext.isGenerator ? closureContext.returnContext : null;
1359 : null;
1360 if (isYieldStar && typeContext != null) { 1317 if (isYieldStar && typeContext != null) {
1361 if (closureContext == null) { 1318 typeContext = inferrer.wrapType(
1362 typeContext = null; 1319 typeContext,
1363 } else { 1320 closureContext.isAsync
1364 typeContext = inferrer.wrapType( 1321 ? inferrer.coreTypes.streamClass
1365 typeContext, 1322 : inferrer.coreTypes.iterableClass);
1366 closureContext.isAsync
1367 ? inferrer.coreTypes.streamClass
1368 : inferrer.coreTypes.iterableClass);
1369 }
1370 } 1323 }
1371 var inferredType = inferrer.inferExpression( 1324 var inferredType = inferrer.inferExpression(
1372 expression, typeContext, closureContext != null); 1325 expression, typeContext, closureContext != null);
1373 closureContext?.handleYield(inferrer, isYieldStar, inferredType); 1326 closureContext?.handleYield(inferrer, isYieldStar, inferredType);
1374 inferrer.listener.yieldStatementExit(this); 1327 inferrer.listener.yieldStatementExit(this);
1375 } 1328 }
1376 } 1329 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/kernel/body_builder.dart ('k') | pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698