Skip to content

Commit 3e6eaaa

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

File tree

15 files changed

+796
-394
lines changed

15 files changed

+796
-394
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: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4299,14 +4299,26 @@ class InferenceContext {
42994299
}
43004300

43014301
/**
4302-
* Look for contextual type information attached to [node]. Returns
4303-
* the type if found, otherwise null.
4302+
* Look for contextual type information attached to [node], and returns
4303+
* the type if found.
43044304
*
4305-
* If [node] has a contextual union type like `T | Future<T>` this will be
4306-
* returned. You can use [getType] if you prefer to only get the `T`.
4305+
* If [node] has a contextual union type like `T | Future<T>` or a type that
4306+
* contains `?` this will be returned. You can use [getValueContext] if you
4307+
* prefer to eliminate the Future union, or [getType] to eliminate both.
43074308
*/
43084309
static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
43094310

4311+
/**
4312+
* Look for contextual type information attached to [node] and returns it,
4313+
* eliminating future unions by choosing `T` from `T | Future<T>`.
4314+
*
4315+
* See also [getContext].
4316+
*/
4317+
static DartType getValueContext(AstNode node) {
4318+
var context = getContext(node);
4319+
return context is FutureUnionType ? context.type : context;
4320+
}
4321+
43104322
/**
43114323
* Look for a single contextual type attached to [node], and returns the type
43124324
* if found, otherwise null.
@@ -4318,9 +4330,9 @@ class InferenceContext {
43184330
static DartType getType(AstNode node) {
43194331
DartType t = getContext(node);
43204332
if (t is FutureUnionType) {
4321-
return t.type;
4333+
return _substituteForUnknown(t.type);
43224334
}
4323-
return t;
4335+
return _substituteForUnknown(t);
43244336
}
43254337

43264338
/**
@@ -4331,10 +4343,19 @@ class InferenceContext {
43314343
if (t == null) {
43324344
return DartType.EMPTY_LIST;
43334345
}
4334-
if (t is FutureUnionType) {
4335-
return t.types;
4336-
}
4337-
return <DartType>[t];
4346+
Iterable<DartType> result = t is FutureUnionType ? t.types : [t];
4347+
return result.map(_substituteForUnknown).where((t) => t != null);
4348+
}
4349+
4350+
static DartType _substituteForUnknown(DartType t) {
4351+
if (t == null) return null;
4352+
// Since the type is being used for downwards inference, the expression
4353+
// type E must be a subtype of the context type T, i.e. T is an upper bound.
4354+
//
4355+
// TODO(jmesserly): our downwards inference code is not designed to handle
4356+
// the bottom type, so we need to prevent it from resulting here.
4357+
// Instead use `dynamic`. See `UnknownInferredType.upperBoundForType`.
4358+
return UnknownInferredType.substituteDynamic(t);
43384359
}
43394360

43404361
/**
@@ -5398,7 +5419,7 @@ class ResolverVisitor extends ScopedVisitor {
53985419

53995420
@override
54005421
Object visitArgumentList(ArgumentList node) {
5401-
DartType callerType = InferenceContext.getType(node);
5422+
DartType callerType = InferenceContext.getContext(node);
54025423
if (callerType is FunctionType) {
54035424
Map<String, DartType> namedParameterTypes =
54045425
callerType.namedParameterTypes;
@@ -6155,18 +6176,26 @@ class ResolverVisitor extends ScopedVisitor {
61556176
// check this don't work, since we may have been instantiated
61566177
// to bounds in an earlier phase, and we *do* want to do inference
61576178
// in that case.
6158-
if (classTypeName.typeArguments == null) {
6179+
6180+
if (strongMode && classTypeName.typeArguments == null) {
61596181
// Given a union of context types ` T0 | T1 | ... | Tn`, find the first
61606182
// valid instantiation `new C<Ti>`, if it exists.
61616183
// TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
61626184
// will become a valid possibility. Right now the only allowed union is
61636185
// `T | Future<T>` so we can take a simple approach.
6164-
for (var contextType in InferenceContext.getTypes(node)) {
6186+
6187+
TypeDefiningElement classElement = classTypeName.type?.element;
6188+
// At this point rawType is the interface type whose class is the class
6189+
// being created, and whose type arguments are the type parameters of the
6190+
// class declaration.
6191+
DartType rawType = classElement?.type;
6192+
Iterable<DartType> contextTypes = InferenceContext.getTypes(node);
6193+
for (var contextType in contextTypes) {
61656194
if (contextType is InterfaceType &&
61666195
contextType.typeArguments != null &&
61676196
contextType.typeArguments.isNotEmpty) {
61686197
// TODO(jmesserly): for generic methods we use the
6169-
// StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
6198+
// StrongTypeSystemImpl.inferGenericFunctionOrType, which appears to
61706199
// be a tad more powerful than matchTypes.
61716200
//
61726201
// For example it can infer this case:
@@ -6175,11 +6204,16 @@ class ResolverVisitor extends ScopedVisitor {
61756204
// A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
61766205
//
61776206
// See _inferArgumentTypesFromContext in this file for use of it.
6207+
6208+
// TODO(jmesserly): classTypeName.type is the default dynamic
6209+
// substitution, this is required by matchTypes implementation.
6210+
// TODO(jmesserly): does this mean we fail when the type has an upper
6211+
// bound?
61786212
List<DartType> targs =
61796213
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;
6214+
if (targs != null &&
6215+
targs.any((t) => !t.isDynamic) &&
6216+
rawType is InterfaceType) {
61836217
InterfaceType fullType =
61846218
rawType.substitute2(targs, rawType.typeArguments);
61856219
// The element resolver uses the type on the constructor name, so
@@ -6191,8 +6225,9 @@ class ResolverVisitor extends ScopedVisitor {
61916225
}
61926226
}
61936227
node.constructorName?.accept(this);
6194-
FunctionType constructorType = node.constructorName.staticElement?.type;
6195-
if (constructorType != null) {
6228+
ConstructorElement constructor = node.constructorName.staticElement;
6229+
FunctionType constructorType = constructor?.type;
6230+
if (strongMode && constructorType != null) {
61966231
InferenceContext.setType(node.argumentList, constructorType);
61976232
}
61986233
node.argumentList?.accept(this);
@@ -6209,7 +6244,7 @@ class ResolverVisitor extends ScopedVisitor {
62096244

62106245
@override
62116246
Object visitListLiteral(ListLiteral node) {
6212-
DartType contextType = InferenceContext.getType(node);
6247+
DartType contextType = InferenceContext.getValueContext(node);
62136248
List<DartType> targs = null;
62146249
if (node.typeArguments != null) {
62156250
targs = node.typeArguments.arguments.map((t) => t.type).toList();
@@ -6234,7 +6269,7 @@ class ResolverVisitor extends ScopedVisitor {
62346269

62356270
@override
62366271
Object visitMapLiteral(MapLiteral node) {
6237-
DartType contextType = InferenceContext.getType(node);
6272+
DartType contextType = InferenceContext.getValueContext(node);
62386273
List<DartType> targs = null;
62396274
if (node.typeArguments != null) {
62406275
targs = node.typeArguments.arguments.map((t) => t.type).toList();
@@ -6686,18 +6721,18 @@ class ResolverVisitor extends ScopedVisitor {
66866721
DartType originalType = node.function.staticType;
66876722
DartType returnContextType = InferenceContext.getContext(node);
66886723
TypeSystem ts = typeSystem;
6689-
if (returnContextType != null &&
6690-
node.typeArguments == null &&
6724+
if (node.typeArguments == null &&
66916725
originalType is FunctionType &&
66926726
originalType.typeFormals.isNotEmpty &&
66936727
ts is StrongTypeSystemImpl) {
6694-
contextType = ts.inferGenericFunctionCall(
6728+
contextType = ts.inferGenericFunctionOrType/*<FunctionType>*/(
66956729
typeProvider,
66966730
originalType,
6697-
DartType.EMPTY_LIST,
6731+
ParameterElement.EMPTY_LIST,
66986732
DartType.EMPTY_LIST,
66996733
originalType.returnType,
6700-
returnContextType);
6734+
returnContextType,
6735+
downwards: true);
67016736
}
67026737

67036738
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)