Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(428)

Unified Diff: lib/compiler/implementation/closure.dart

Issue 10910098: Re-apply with a few fixes http://codereview.chromium.org/10913081/: Fix resolution of type paramete… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/compiler/implementation/closure.dart
===================================================================
--- lib/compiler/implementation/closure.dart (revision 11962)
+++ lib/compiler/implementation/closure.dart (working copy)
@@ -179,7 +179,9 @@
// non-mutated variables.
Set<Element> mutatedVariables;
+ FunctionElement outermostFunctionElement;
FunctionElement currentFunctionElement;
+
// The closureData of the currentFunctionElement.
ClosureClassMap closureData;
@@ -218,7 +220,8 @@
assert(updatedElement !== null);
if (fromElement == updatedElement) {
assert(freeVariableMapping[fromElement] == updatedElement);
- assert(Elements.isLocal(updatedElement));
+ assert(Elements.isLocal(updatedElement)
+ || updatedElement.isTypeVariable());
// The variable has not been boxed.
fieldCaptures.add(updatedElement);
} else {
@@ -250,16 +253,15 @@
}
void useLocal(Element element) {
- // TODO(floitsch): replace this with a general solution.
- Element functionElement = currentFunctionElement;
- if (functionElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
- ConstructorBodyElement body = functionElement;
- functionElement = body.constructor;
- }
// If the element is not declared in the current function and the element
// is not the closure itself we need to mark the element as free variable.
- if (element.enclosingElement != functionElement &&
- element != functionElement) {
+ // Note that the check on [insideClosure] is not just an
+ // optimization: factories have type parameters as function
+ // parameters, and type parameters are declared in the class, not
+ // the factory.
+ if (insideClosure &&
+ element.enclosingElement != currentFunctionElement &&
+ element != currentFunctionElement) {
assert(closureData.freeVariableMapping[element] == null ||
closureData.freeVariableMapping[element] == element);
closureData.freeVariableMapping[element] = element;
@@ -346,6 +348,9 @@
}
visitNewExpression(NewExpression node) {
+ TypeAnnotation annotation = node.send.getTypeAnnotation();
+ DartType type = elements.getType(annotation);
+
bool hasTypeVariable(DartType type) {
if (type is TypeVariableType) {
return true;
@@ -359,14 +364,25 @@
}
return false;
}
- TypeAnnotation annotation = node.send.getTypeAnnotation();
- DartType type = elements.getType(annotation);
- if (hasTypeVariable(type)) {
- // Factories do not use [this] to get the type variables.
- if (closureData.thisElement !== null) {
- useLocal(closureData.thisElement);
+
+ void analyzeTypeVariables(DartType type) {
+ if (type is TypeVariableType) {
+ useLocal(type.element);
+ } else if (type is InterfaceType) {
+ InterfaceType ifcType = type;
+ for (DartType argument in ifcType.arguments) {
+ analyzeTypeVariables(argument);
+ }
}
}
+
+ if (outermostFunctionElement.isInstanceMember()
+ || outermostFunctionElement.isGenerativeConstructor()) {
+ if (hasTypeVariable(type)) useLocal(closureData.thisElement);
+ } else if (outermostFunctionElement.isFactoryConstructor()) {
+ analyzeTypeVariables(type);
+ }
+
node.visitChildren(this);
}
@@ -495,38 +511,26 @@
visitFunctionExpression(FunctionExpression node) {
Element element = elements[node];
- if (element.kind === ElementKind.PARAMETER) {
+ if (element.isParameter()) {
// TODO(ahe): This is a hack. This method should *not* call
// visitChildren.
return node.name.accept(this);
}
- bool isClosure = (closureData !== null);
- if (isClosure) closures.add(node);
-
bool oldInsideClosure = insideClosure;
FunctionElement oldFunctionElement = currentFunctionElement;
ClosureClassMap oldClosureData = closureData;
- insideClosure = isClosure;
- currentFunctionElement = elements[node];
+ insideClosure = outermostFunctionElement != null;
+ currentFunctionElement = element;
if (insideClosure) {
+ closures.add(node);
closureData = globalizeClosure(node, element);
} else {
+ outermostFunctionElement = element;
Element thisElement = null;
- // TODO(floitsch): we should not need to look for generative constructors.
- // At the moment we store only one ClosureData for both the factory and
- // the body.
- if (element.isInstanceMember() ||
- element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
- // TODO(floitsch): currently all variables are considered to be
- // declared in the GENERATIVE_CONSTRUCTOR. Including the 'this'.
- Element thisEnclosingElement = element;
- if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
- ConstructorBodyElement body = element;
- thisEnclosingElement = body.constructor;
- }
- thisElement = new ThisElement(thisEnclosingElement);
+ if (element.isInstanceMember() || element.isGenerativeConstructor()) {
+ thisElement = new ThisElement(element);
}
closureData = new ClosureClassMap(null, null, null, thisElement);
}
@@ -544,6 +548,15 @@
if (insideClosure) {
declareLocal(element);
}
+
+ if (currentFunctionElement.isFactoryConstructor()) {
+ // Declare the type parameters in the scope. Generative
+ // constructors just use 'this'.
+ ClassElement cls = currentFunctionElement.enclosingElement;
+ cls.typeVariables.forEach((TypeVariableType typeVariable) {
+ declareLocal(typeVariable.element);
+ });
+ }
// TODO(ahe): This is problematic. The backend should not repeat
// the work of the resolver. It is the resolver's job to create
« no previous file with comments | « no previous file | lib/compiler/implementation/elements/elements.dart » ('j') | lib/compiler/implementation/elements/elements.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698