@@ -57,8 +57,6 @@ import '../kernel/expression_generator.dart' show buildIsNull;
57
57
58
58
import '../kernel/kernel_shadow_ast.dart'
59
59
show
60
- ShadowTypeInferenceEngine,
61
- ShadowTypeInferrer,
62
60
VariableDeclarationImpl,
63
61
getExplicitTypeArguments,
64
62
getExtensionTypeParameterCount;
@@ -408,18 +406,6 @@ enum MethodContravarianceCheckKind {
408
406
/// This class describes the interface for use by clients of type inference
409
407
/// (e.g. BodyBuilder). Derived classes should derive from [TypeInferrerImpl] .
410
408
abstract class TypeInferrer {
411
- final CoreTypes coreTypes;
412
-
413
- TypeInferrer .private (this .coreTypes);
414
-
415
- factory TypeInferrer (
416
- ShadowTypeInferenceEngine engine,
417
- Uri uri,
418
- bool topLevel,
419
- InterfaceType thisType,
420
- SourceLibraryBuilder library,
421
- InferenceDataForTesting dataForTesting) = ShadowTypeInferrer .private;
422
-
423
409
SourceLibraryBuilder get library;
424
410
425
411
/// Gets the [TypePromoter] that can be used to perform type promotion within
@@ -459,19 +445,21 @@ abstract class TypeInferrer {
459
445
InferenceHelper helper, Expression initializer, DartType declaredType);
460
446
}
461
447
462
- /// Derived class containing generic implementations of [TypeInferrer] .
463
- ///
464
- /// This class contains as much of the implementation of type inference as
465
- /// possible without knowing the identity of the type parameters. It defers to
466
- /// abstract methods for everything else.
467
- abstract class TypeInferrerImpl extends TypeInferrer {
448
+ /// Concrete implementation of [TypeInferrer] specialized to work with kernel
449
+ /// objects.
450
+ class TypeInferrerImpl implements TypeInferrer {
468
451
/// Marker object to indicate that a function takes an unknown number
469
452
/// of arguments.
470
453
static final FunctionType unknownFunction =
471
454
new FunctionType (const [], const DynamicType ());
472
455
473
456
final TypeInferenceEngine engine;
474
457
458
+ @override
459
+ final TypePromoter typePromoter;
460
+
461
+ final InferenceDataForTesting dataForTesting;
462
+
475
463
@override
476
464
final Uri uriForInstrumentation;
477
465
@@ -505,20 +493,34 @@ abstract class TypeInferrerImpl extends TypeInferrer {
505
493
/// if the last invocation didn't require any inference.
506
494
FunctionType lastCalleeType;
507
495
508
- TypeInferrerImpl . private (this .engine, this .uriForInstrumentation,
509
- bool topLevel, this .thisType, this .library)
496
+ TypeInferrerImpl (this .engine, this .uriForInstrumentation, bool topLevel ,
497
+ this .thisType, this .library, this .dataForTesting )
510
498
: assert (library != null ),
511
499
classHierarchy = engine.classHierarchy,
512
500
instrumentation = topLevel ? null : engine.instrumentation,
513
501
typeSchemaEnvironment = engine.typeSchemaEnvironment,
514
502
isTopLevel = topLevel,
515
- super .private (engine.coreTypes);
503
+ typePromoter = new TypePromoter (engine.typeSchemaEnvironment);
504
+
505
+ CoreTypes get coreTypes => engine.coreTypes;
516
506
517
507
bool get isNonNullableByDefault => library.isNonNullableByDefault;
518
508
519
- /// Gets the type promoter that should be used to promote types during
520
- /// inference.
521
- TypePromoter get typePromoter;
509
+ @override
510
+ void inferInitializer (InferenceHelper helper, Initializer initializer) {
511
+ this .helper = helper;
512
+ // Use polymorphic dispatch on [KernelInitializer] to perform whatever
513
+ // kind of type inference is correct for this kind of initializer.
514
+ // TODO(paulberry): experiment to see if dynamic dispatch would be better,
515
+ // so that the type hierarchy will be simpler (which may speed up "is"
516
+ // checks).
517
+ if (initializer is InitializerJudgment ) {
518
+ initializer.acceptInference (new InferenceVisitor (this ));
519
+ } else {
520
+ initializer.accept (new InferenceVisitor (this ));
521
+ }
522
+ this .helper = null ;
523
+ }
522
524
523
525
bool isDoubleContext (DartType typeContext) {
524
526
// A context is a double context if double is assignable to it but int is
@@ -1266,10 +1268,6 @@ abstract class TypeInferrerImpl extends TypeInferrer {
1266
1268
return null ;
1267
1269
}
1268
1270
1269
- /// Gets the initializer for the given [field] , or `null` if there is no
1270
- /// initializer.
1271
- Expression getFieldInitializer (Field field);
1272
-
1273
1271
/// If the [member] is a forwarding stub, return the target it forwards to.
1274
1272
/// Otherwise return the given [member] .
1275
1273
Member getRealTarget (Member member) {
@@ -1424,7 +1422,37 @@ abstract class TypeInferrerImpl extends TypeInferrer {
1424
1422
/// the expression type and calls the appropriate specialized "infer" method.
1425
1423
ExpressionInferenceResult inferExpression (
1426
1424
Expression expression, DartType typeContext, bool typeNeeded,
1427
- {bool isVoidAllowed});
1425
+ {bool isVoidAllowed: false }) {
1426
+ // `null` should never be used as the type context. An instance of
1427
+ // `UnknownType` should be used instead.
1428
+ assert (typeContext != null );
1429
+
1430
+ // For full (non-top level) inference, we need access to the
1431
+ // ExpressionGeneratorHelper so that we can perform error recovery.
1432
+ assert (isTopLevel || helper != null );
1433
+
1434
+ // When doing top level inference, we skip subexpressions whose type isn't
1435
+ // needed so that we don't induce bogus dependencies on fields mentioned in
1436
+ // those subexpressions.
1437
+ if (! typeNeeded) return new ExpressionInferenceResult (null , expression);
1438
+
1439
+ InferenceVisitor visitor = new InferenceVisitor (this );
1440
+ ExpressionInferenceResult result;
1441
+ if (expression is ExpressionJudgment ) {
1442
+ result = expression.acceptInference (visitor, typeContext);
1443
+ } else {
1444
+ result = expression.accept1 (visitor, typeContext);
1445
+ }
1446
+ DartType inferredType = result.inferredType;
1447
+ assert (inferredType != null , "No type inferred for $expression ." );
1448
+ if (inferredType is VoidType && ! isVoidAllowed) {
1449
+ if (expression.parent is ! ArgumentsImpl ) {
1450
+ helper? .addProblem (
1451
+ messageVoidExpression, expression.fileOffset, noLength);
1452
+ }
1453
+ }
1454
+ return result;
1455
+ }
1428
1456
1429
1457
@override
1430
1458
Expression inferFieldInitializer (
@@ -2215,7 +2243,14 @@ abstract class TypeInferrerImpl extends TypeInferrer {
2215
2243
///
2216
2244
/// Derived classes should override this method with logic that dispatches on
2217
2245
/// the statement type and calls the appropriate specialized "infer" method.
2218
- void inferStatement (Statement statement);
2246
+ void inferStatement (Statement statement) {
2247
+ // For full (non-top level) inference, we need access to the
2248
+ // ExpressionGeneratorHelper so that we can perform error recovery.
2249
+ if (! isTopLevel) assert (helper != null );
2250
+ if (statement != null ) {
2251
+ statement.accept (new InferenceVisitor (this ));
2252
+ }
2253
+ }
2219
2254
2220
2255
/// Performs the type inference steps necessary to instantiate a tear-off
2221
2256
/// (if necessary).
0 commit comments