fix #27411, avoid capture for instance creation

R=leafp@google.com

Review URL: https://codereview.chromium.org/2363503003 .
This commit is contained in:
John Messerly 2016-09-21 16:19:36 -07:00
parent a22b3b6205
commit 738b481052
2 changed files with 40 additions and 2 deletions

View file

@ -1602,10 +1602,37 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return type;
}
FunctionElementImpl function = new FunctionElementImpl("", -1);
// TODO(jmesserly): feels like we should be able to do this with less code.
// Create fresh type formals. This avoids capture if we're inferring the
// constructor to the class from inside it.
// We build up a substitution for the type parameters,
// {variablesFresh/variables} then apply it.
var typeVars = <DartType>[];
var freshTypeVars = <DartType>[];
var freshVarElements = <TypeParameterElement>[];
for (int i = 0; i < cls.typeParameters.length; i++) {
var typeParamElement = cls.typeParameters[i];
var freshElement =
new TypeParameterElementImpl.synthetic(typeParamElement.name);
var freshTypeVar = new TypeParameterTypeImpl(freshElement);
freshElement.type = freshTypeVar;
typeVars.add(typeParamElement.type);
freshTypeVars.add(freshTypeVar);
freshVarElements.add(freshElement);
var bound = typeParamElement.bound ?? DynamicTypeImpl.instance;
freshElement.bound = bound.substitute2(freshTypeVars, typeVars);
}
type = type.substitute2(freshTypeVars, typeVars);
var function = new FunctionElementImpl("", -1);
function.synthetic = true;
function.returnType = type.returnType;
function.shareTypeParameters(cls.typeParameters);
function.typeParameters = freshVarElements;
function.shareParameters(type.parameters);
return function.type = new FunctionTypeImpl(function);
}

View file

@ -700,6 +700,17 @@ main() {
expect(unit.topLevelVariables[0].type.toString(), 'C<int>');
}
void test_constructors_inferFromArguments_factory_callsConstructor() {
checkFile(r'''
class A<T> {
A<T> f = /*info:INFERRED_TYPE_ALLOCATION*/new A();
A();
factory A.factory() => /*info:INFERRED_TYPE_ALLOCATION*/new A();
A<T> m() => /*info:INFERRED_TYPE_ALLOCATION*/new A();
}
''');
}
void test_constructors_inferFromArguments_named() {
var unit = checkFile('''
class C<T> {