@@ -4318,9 +4318,9 @@ class InferenceContext {
4318
4318
static DartType getType (AstNode node) {
4319
4319
DartType t = getContext (node);
4320
4320
if (t is FutureUnionType ) {
4321
- return t.type;
4321
+ return _substituteForUnknown ( t.type) ;
4322
4322
}
4323
- return t ;
4323
+ return _substituteForUnknown (t) ;
4324
4324
}
4325
4325
4326
4326
/**
@@ -4331,10 +4331,20 @@ class InferenceContext {
4331
4331
if (t == null ) {
4332
4332
return DartType .EMPTY_LIST ;
4333
4333
}
4334
- if (t is FutureUnionType ) {
4335
- return t.types;
4336
- }
4337
- return < DartType > [t];
4334
+ Iterable <DartType > result = t is FutureUnionType ? t.types : [t];
4335
+ return result.map (_substituteForUnknown).where ((t) => t != null );
4336
+ }
4337
+
4338
+ static DartType _substituteForUnknown (DartType t) {
4339
+ if (t == null ) return null ;
4340
+ // Since the type is being used for downwards inference, the expression
4341
+ // type E must be a subtype of the context type T, i.e. T is an upper bound.
4342
+ //
4343
+ // TODO(jmesserly): our downwards inference code is not designed to handle
4344
+ // the bottom type, so we need to prevent it from resulting here.
4345
+ // Instead use `dynamic`.
4346
+ //return UnknownInferredType.upperBoundForType(t);
4347
+ return UnknownInferredType .substituteDynamic (t);
4338
4348
}
4339
4349
4340
4350
/**
@@ -5398,7 +5408,7 @@ class ResolverVisitor extends ScopedVisitor {
5398
5408
5399
5409
@override
5400
5410
Object visitArgumentList (ArgumentList node) {
5401
- DartType callerType = InferenceContext .getType (node);
5411
+ DartType callerType = InferenceContext .getContext (node);
5402
5412
if (callerType is FunctionType ) {
5403
5413
Map <String , DartType > namedParameterTypes =
5404
5414
callerType.namedParameterTypes;
@@ -6155,18 +6165,23 @@ class ResolverVisitor extends ScopedVisitor {
6155
6165
// check this don't work, since we may have been instantiated
6156
6166
// to bounds in an earlier phase, and we *do* want to do inference
6157
6167
// in that case.
6158
- if (classTypeName.typeArguments == null ) {
6168
+
6169
+ if (strongMode && classTypeName.typeArguments == null ) {
6159
6170
// Given a union of context types ` T0 | T1 | ... | Tn`, find the first
6160
6171
// valid instantiation `new C<Ti>`, if it exists.
6161
6172
// TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
6162
6173
// will become a valid possibility. Right now the only allowed union is
6163
6174
// `T | Future<T>` so we can take a simple approach.
6164
- for (var contextType in InferenceContext .getTypes (node)) {
6175
+
6176
+ TypeDefiningElement classElement = classTypeName.type? .element;
6177
+ DartType rawType = classElement? .type;
6178
+ Iterable <DartType > contextTypes = InferenceContext .getTypes (node);
6179
+ for (var contextType in contextTypes) {
6165
6180
if (contextType is InterfaceType &&
6166
6181
contextType.typeArguments != null &&
6167
6182
contextType.typeArguments.isNotEmpty) {
6168
6183
// TODO(jmesserly): for generic methods we use the
6169
- // StrongTypeSystemImpl.inferGenericFunctionCall , which appears to
6184
+ // StrongTypeSystemImpl.inferGenericFunctionOrType , which appears to
6170
6185
// be a tad more powerful than matchTypes.
6171
6186
//
6172
6187
// For example it can infer this case:
@@ -6177,9 +6192,9 @@ class ResolverVisitor extends ScopedVisitor {
6177
6192
// See _inferArgumentTypesFromContext in this file for use of it.
6178
6193
List <DartType > targs =
6179
6194
inferenceContext.matchTypes (classTypeName.type, contextType);
6180
- if (targs != null && targs. any ((t) => ! t.isDynamic)) {
6181
- ClassElement classElement = classTypeName.type.element;
6182
- InterfaceType rawType = classElement.type;
6195
+ if (targs != null &&
6196
+ targs. any ((t) => ! t.isDynamic) &&
6197
+ rawType is InterfaceType ) {
6183
6198
InterfaceType fullType =
6184
6199
rawType.substitute2 (targs, rawType.typeArguments);
6185
6200
// The element resolver uses the type on the constructor name, so
@@ -6189,10 +6204,19 @@ class ResolverVisitor extends ScopedVisitor {
6189
6204
}
6190
6205
}
6191
6206
}
6207
+ if (contextTypes.isEmpty &&
6208
+ rawType is InterfaceType &&
6209
+ rawType.typeArguments.isNotEmpty) {
6210
+ node.constructorName.type.type = rawType.substitute2 (
6211
+ new List .filled (
6212
+ rawType.typeArguments.length, UnknownInferredType .instance),
6213
+ rawType.typeArguments);
6214
+ }
6192
6215
}
6193
6216
node.constructorName? .accept (this );
6194
- FunctionType constructorType = node.constructorName.staticElement? .type;
6195
- if (constructorType != null ) {
6217
+ ConstructorElement constructor = node.constructorName.staticElement;
6218
+ FunctionType constructorType = constructor? .type;
6219
+ if (strongMode && constructorType != null ) {
6196
6220
InferenceContext .setType (node.argumentList, constructorType);
6197
6221
}
6198
6222
node.argumentList? .accept (this );
@@ -6209,7 +6233,10 @@ class ResolverVisitor extends ScopedVisitor {
6209
6233
6210
6234
@override
6211
6235
Object visitListLiteral (ListLiteral node) {
6212
- DartType contextType = InferenceContext .getType (node);
6236
+ DartType contextType = InferenceContext .getContext (node);
6237
+ if (contextType is FutureUnionType ) {
6238
+ contextType = (contextType as FutureUnionType ).type;
6239
+ }
6213
6240
List <DartType > targs = null ;
6214
6241
if (node.typeArguments != null ) {
6215
6242
targs = node.typeArguments.arguments.map ((t) => t.type).toList ();
@@ -6234,7 +6261,10 @@ class ResolverVisitor extends ScopedVisitor {
6234
6261
6235
6262
@override
6236
6263
Object visitMapLiteral (MapLiteral node) {
6237
- DartType contextType = InferenceContext .getType (node);
6264
+ DartType contextType = InferenceContext .getContext (node);
6265
+ if (contextType is FutureUnionType ) {
6266
+ contextType = (contextType as FutureUnionType ).type;
6267
+ }
6238
6268
List <DartType > targs = null ;
6239
6269
if (node.typeArguments != null ) {
6240
6270
targs = node.typeArguments.arguments.map ((t) => t.type).toList ();
@@ -6686,18 +6716,18 @@ class ResolverVisitor extends ScopedVisitor {
6686
6716
DartType originalType = node.function.staticType;
6687
6717
DartType returnContextType = InferenceContext .getContext (node);
6688
6718
TypeSystem ts = typeSystem;
6689
- if (returnContextType != null &&
6690
- node.typeArguments == null &&
6719
+ if (node.typeArguments == null &&
6691
6720
originalType is FunctionType &&
6692
6721
originalType.typeFormals.isNotEmpty &&
6693
6722
ts is StrongTypeSystemImpl ) {
6694
- contextType = ts.inferGenericFunctionCall (
6723
+ contextType = ts.inferGenericFunctionOrType /*<FunctionType>*/ (
6695
6724
typeProvider,
6696
6725
originalType,
6697
- DartType .EMPTY_LIST ,
6726
+ ParameterElement .EMPTY_LIST ,
6698
6727
DartType .EMPTY_LIST ,
6699
6728
originalType.returnType,
6700
- returnContextType);
6729
+ returnContextType,
6730
+ downwards: true );
6701
6731
}
6702
6732
6703
6733
InferenceContext .setType (node.argumentList, contextType);
0 commit comments