Skip to content

Commit 9f5fa08

Browse files
author
Jennifer Messerly
committed
fix for #27586, rebased against master
1 parent 0f9a78f commit 9f5fa08

File tree

14 files changed

+751
-265
lines changed

14 files changed

+751
-265
lines changed

pkg/analyzer/lib/src/error/codes.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4742,7 +4742,7 @@ class StrongModeCode extends ErrorCode {
47424742
static const StrongModeCode COULD_NOT_INFER = const StrongModeCode(
47434743
ErrorType.COMPILE_TIME_ERROR,
47444744
'COULD_NOT_INFER',
4745-
"Couldn't infer type parameter '{0}'; '{1}' must be of type '{2}'.");
4745+
"Couldn't infer type parameter '{0}'.{1}");
47464746

47474747
static const StrongModeCode INFERRED_TYPE = const StrongModeCode(
47484748
ErrorType.HINT, 'INFERRED_TYPE', _inferredTypeMessage);

pkg/analyzer/lib/src/generated/resolver.dart

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,9 +4318,9 @@ class InferenceContext {
43184318
static DartType getType(AstNode node) {
43194319
DartType t = getContext(node);
43204320
if (t is FutureUnionType) {
4321-
return t.type;
4321+
return _substituteForUnknown(t.type);
43224322
}
4323-
return t;
4323+
return _substituteForUnknown(t);
43244324
}
43254325

43264326
/**
@@ -4331,10 +4331,20 @@ class InferenceContext {
43314331
if (t == null) {
43324332
return DartType.EMPTY_LIST;
43334333
}
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);
43384348
}
43394349

43404350
/**
@@ -5398,7 +5408,7 @@ class ResolverVisitor extends ScopedVisitor {
53985408

53995409
@override
54005410
Object visitArgumentList(ArgumentList node) {
5401-
DartType callerType = InferenceContext.getType(node);
5411+
DartType callerType = InferenceContext.getContext(node);
54025412
if (callerType is FunctionType) {
54035413
Map<String, DartType> namedParameterTypes =
54045414
callerType.namedParameterTypes;
@@ -6155,18 +6165,23 @@ class ResolverVisitor extends ScopedVisitor {
61556165
// check this don't work, since we may have been instantiated
61566166
// to bounds in an earlier phase, and we *do* want to do inference
61576167
// in that case.
6158-
if (classTypeName.typeArguments == null) {
6168+
6169+
if (strongMode && classTypeName.typeArguments == null) {
61596170
// Given a union of context types ` T0 | T1 | ... | Tn`, find the first
61606171
// valid instantiation `new C<Ti>`, if it exists.
61616172
// TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
61626173
// will become a valid possibility. Right now the only allowed union is
61636174
// `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) {
61656180
if (contextType is InterfaceType &&
61666181
contextType.typeArguments != null &&
61676182
contextType.typeArguments.isNotEmpty) {
61686183
// TODO(jmesserly): for generic methods we use the
6169-
// StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
6184+
// StrongTypeSystemImpl.inferGenericFunctionOrType, which appears to
61706185
// be a tad more powerful than matchTypes.
61716186
//
61726187
// For example it can infer this case:
@@ -6177,9 +6192,9 @@ class ResolverVisitor extends ScopedVisitor {
61776192
// See _inferArgumentTypesFromContext in this file for use of it.
61786193
List<DartType> targs =
61796194
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) {
61836198
InterfaceType fullType =
61846199
rawType.substitute2(targs, rawType.typeArguments);
61856200
// The element resolver uses the type on the constructor name, so
@@ -6189,10 +6204,19 @@ class ResolverVisitor extends ScopedVisitor {
61896204
}
61906205
}
61916206
}
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+
}
61926215
}
61936216
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) {
61966220
InferenceContext.setType(node.argumentList, constructorType);
61976221
}
61986222
node.argumentList?.accept(this);
@@ -6209,7 +6233,10 @@ class ResolverVisitor extends ScopedVisitor {
62096233

62106234
@override
62116235
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+
}
62136240
List<DartType> targs = null;
62146241
if (node.typeArguments != null) {
62156242
targs = node.typeArguments.arguments.map((t) => t.type).toList();
@@ -6234,7 +6261,10 @@ class ResolverVisitor extends ScopedVisitor {
62346261

62356262
@override
62366263
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+
}
62386268
List<DartType> targs = null;
62396269
if (node.typeArguments != null) {
62406270
targs = node.typeArguments.arguments.map((t) => t.type).toList();
@@ -6686,18 +6716,18 @@ class ResolverVisitor extends ScopedVisitor {
66866716
DartType originalType = node.function.staticType;
66876717
DartType returnContextType = InferenceContext.getContext(node);
66886718
TypeSystem ts = typeSystem;
6689-
if (returnContextType != null &&
6690-
node.typeArguments == null &&
6719+
if (node.typeArguments == null &&
66916720
originalType is FunctionType &&
66926721
originalType.typeFormals.isNotEmpty &&
66936722
ts is StrongTypeSystemImpl) {
6694-
contextType = ts.inferGenericFunctionCall(
6723+
contextType = ts.inferGenericFunctionOrType/*<FunctionType>*/(
66956724
typeProvider,
66966725
originalType,
6697-
DartType.EMPTY_LIST,
6726+
ParameterElement.EMPTY_LIST,
66986727
DartType.EMPTY_LIST,
66996728
originalType.returnType,
6700-
returnContextType);
6729+
returnContextType,
6730+
downwards: true);
67016731
}
67026732

67036733
InferenceContext.setType(node.argumentList, contextType);

pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
629629
// If there are no type arguments and we are in strong mode, try to infer
630630
// some arguments.
631631
if (_strongMode) {
632-
DartType contextType = InferenceContext.getType(node);
632+
DartType contextType = InferenceContext.getContext(node);
633633

634634
// Use both downwards and upwards information to infer the type.
635635
var ts = _typeSystem as StrongTypeSystemImpl;
@@ -638,11 +638,13 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
638638
.where((t) => t != null)
639639
.toList();
640640
var listTypeParam = _typeProvider.listType.typeParameters[0].type;
641+
var syntheticParamElement = new ParameterElementImpl.synthetic(
642+
'element', listTypeParam, ParameterKind.POSITIONAL);
641643

642-
DartType inferred = ts.inferGenericFunctionCall(
644+
DartType inferred = ts.inferGenericFunctionOrType/*<InterfaceType>*/(
643645
_typeProvider,
644646
_typeProvider.listType,
645-
new List.filled(elementTypes.length, listTypeParam),
647+
new List.filled(elementTypes.length, syntheticParamElement),
646648
elementTypes,
647649
_typeProvider.listType,
648650
contextType,
@@ -711,7 +713,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
711713
// If we have no explicit type arguments, and we are in strong mode
712714
// then try to infer type arguments.
713715
if (_strongMode) {
714-
DartType contextType = InferenceContext.getType(node);
716+
DartType contextType = InferenceContext.getContext(node);
715717

716718
// Use both downwards and upwards information to infer the type.
717719
var ts = _typeSystem as StrongTypeSystemImpl;
@@ -721,13 +723,19 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
721723
node.entries.map((e) => e.value.staticType).where((t) => t != null);
722724
var keyTypeParam = _typeProvider.mapType.typeParameters[0].type;
723725
var valueTypeParam = _typeProvider.mapType.typeParameters[1].type;
726+
var syntheticKeyParameter = new ParameterElementImpl.synthetic(
727+
'key', keyTypeParam, ParameterKind.POSITIONAL);
728+
var syntheticValueParameter = new ParameterElementImpl.synthetic(
729+
'value', valueTypeParam, ParameterKind.POSITIONAL);
724730

725-
DartType inferred = ts.inferGenericFunctionCall(
731+
ParameterizedType inferred = ts.inferGenericFunctionOrType(
726732
_typeProvider,
727733
_typeProvider.mapType,
728-
new List.filled(keyTypes.length, keyTypeParam, growable: true)
729-
..addAll(new List.filled(valueTypes.length, valueTypeParam)),
730-
new List.from(keyTypes)..addAll(valueTypes),
734+
new List.filled(keyTypes.length, syntheticKeyParameter,
735+
growable: true)
736+
..addAll(
737+
new List.filled(valueTypes.length, syntheticValueParameter)),
738+
new List<DartType>.from(keyTypes)..addAll(valueTypes),
731739
_typeProvider.mapType,
732740
contextType,
733741
errorReporter: _resolver.errorReporter,
@@ -1629,7 +1637,11 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
16291637

16301638
type = type.substitute2(freshTypeVars, typeVars);
16311639

1632-
var function = new FunctionElementImpl("", -1);
1640+
var name = cls.name;
1641+
if (constructor.name != null) {
1642+
name += '.' + constructor.name;
1643+
}
1644+
var function = new FunctionElementImpl(name, -1);
16331645
function.isSynthetic = true;
16341646
function.returnType = type.returnType;
16351647
function.typeParameters = freshVarElements;
@@ -1964,12 +1976,12 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
19641976
List<ParameterElement> rawParameters = ResolverVisitor
19651977
.resolveArgumentsToParameters(argumentList, fnType.parameters, null);
19661978

1967-
List<DartType> paramTypes = <DartType>[];
1979+
List<ParameterElement> params = <ParameterElement>[];
19681980
List<DartType> argTypes = <DartType>[];
19691981
for (int i = 0, length = rawParameters.length; i < length; i++) {
19701982
ParameterElement parameter = rawParameters[i];
19711983
if (parameter != null) {
1972-
paramTypes.add(parameter.type);
1984+
params.add(parameter);
19731985
argTypes.add(argumentList.arguments[i].staticType);
19741986
}
19751987
}
@@ -1986,7 +1998,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
19861998
// ... and finish the inference using that.
19871999
if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) {
19882000
var firstArgType = argTypes[0];
1989-
var firstParamType = paramTypes[0] as FunctionType;
2001+
var firstParamType = params[0].type as FunctionType;
19902002
if (firstArgType is FunctionType) {
19912003
var argReturnType = firstArgType.returnType;
19922004
// Skip the inference if we have the top type. It can only lead to
@@ -2007,11 +2019,12 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
20072019
..returnType = paramReturnType;
20082020
function.type = new FunctionTypeImpl(function);
20092021
// Use this as the expected 1st parameter type.
2010-
paramTypes[0] = function.type;
2022+
params[0] = new ParameterElementImpl.synthetic(
2023+
params[0].name, function.type, params[0].parameterKind);
20112024
}
20122025
}
20132026
}
2014-
return ts.inferGenericFunctionCall(_typeProvider, fnType, paramTypes,
2027+
return ts.inferGenericFunctionOrType(_typeProvider, fnType, params,
20152028
argTypes, fnType.returnType, InferenceContext.getContext(node),
20162029
errorReporter: _resolver.errorReporter, errorNode: errorNode);
20172030
}

0 commit comments

Comments
 (0)