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

Unified Diff: sdk/lib/_internal/compiler/implementation/resolution/members.dart

Issue 12033049: Disallow mixing in classes that use 'super'. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Move mixin uses list to compiler.world. Created 7 years, 11 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: sdk/lib/_internal/compiler/implementation/resolution/members.dart
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 87f1de46a577fde4391e8f9b39c3c278644d0eee..5f705062be4176420f72d5ea86c7935600686734 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -9,18 +9,17 @@ abstract class TreeElements {
Selector getSelector(Send send);
DartType getType(Node node);
bool isParameterChecked(Element element);
+ Set<Node> get superUses;
}
class TreeElementMapping implements TreeElements {
final Element currentElement;
- final Map<Node, Selector> selectors;
- final Map<Node, DartType> types;
- final Set<Element> checkedParameters;
+ final Map<Node, Selector> selectors = new LinkedHashMap<Node, Selector>();
+ final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>();
+ final Set<Element> checkedParameters = new Set<Element>();
+ final Set<Node> superUses = new Set<Node>();
- TreeElementMapping(this.currentElement)
- : selectors = new LinkedHashMap<Node, Selector>(),
- types = new LinkedHashMap<Node, DartType>(),
- checkedParameters = new Set<Element>();
+ TreeElementMapping(this.currentElement);
operator []=(Node node, Element element) {
assert(invariant(node, () {
@@ -268,7 +267,24 @@ class ResolverTask extends CompilerTask {
}
visitBody(visitor, tree.body);
- return visitor.mapping;
+ // Get the resolution tree and check that the resolved
+ // function doesn't use 'super' if it is mixed into another
+ // class. This is the part of the 'super' mixin check that
+ // happens when a function is resolved after the mixin
+ // application has been performed.
+ TreeElements resolutionTree = visitor.mapping;
+ ClassElement enclosingClass = element.getEnclosingClass();
+ if (enclosingClass != null) {
+ Set<MixinApplicationElement> mixinUses =
+ compiler.world.mixinUses[enclosingClass];
+ if (mixinUses != null) {
+ ClassElement mixin = enclosingClass;
+ for (MixinApplicationElement mixinApplication in mixinUses) {
+ checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
+ }
+ }
+ }
+ return resolutionTree;
});
});
}
@@ -522,16 +538,39 @@ class ResolverTask extends CompilerTask {
error, Diagnostic.ERROR);
}
- // Check that the mixed in class doesn't have any constructors.
+ // Check that the mixed in class doesn't have any constructors and
+ // make sure we aren't mixing in methods that use 'super'.
mixin.forEachLocalMember((Element member) {
if (member.isGenerativeConstructor() && !member.isSynthesized) {
CompilationError error = MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR.error();
compiler.reportMessage(compiler.spanFromElement(member),
error, Diagnostic.ERROR);
+ } else {
+ // Get the resolution tree and check that the resolved member
+ // doesn't use 'super'. This is the part of the 'super' mixin
+ // check that happens when a function is resolved before the
+ // mixin application has been performed.
+ checkMixinSuperUses(
+ compiler.enqueuer.resolution.resolvedElements[member],
+ mixinApplication,
+ mixin);
}
});
}
+ void checkMixinSuperUses(TreeElements resolutionTree,
+ MixinApplicationElement mixinApplication,
+ ClassElement mixin) {
+ if (resolutionTree != null) {
+ for (Node use in resolutionTree.superUses) {
+ CompilationError error =
+ MessageKind.ILLEGAL_MIXIN_SUPER_USE.error([mixin.name]);
+ compiler.reportMessage(compiler.spanFromNode(use),
ahe 2013/01/23 12:32:10 I'm not sure this gives the best error message pos
kasperl 2013/01/23 12:41:54 I thought about that too (which is why I'm passing
kasperl 2013/01/23 13:41:25 Done.
+ error, Diagnostic.ERROR);
+ }
+ }
+ }
+
void checkClassMembers(ClassElement cls) {
assert(invariant(cls, cls.isDeclaration));
if (cls.isObject(compiler)) return;
@@ -1772,6 +1811,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
Element resolveSend(Send node) {
Selector selector = resolveSelector(node);
+ if (node.isSuperCall) mapping.superUses.add(node);
if (node.receiver == null) {
// If this send is of the form "assert(expr);", then
@@ -2930,6 +2970,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor {
previous = current;
current = currentMixinApplication.mixin;
}
+ compiler.world.registerMixinUse(mixinApplication, mixin);
return mixin;
}

Powered by Google App Engine
This is Rietveld 408576698