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

Unified Diff: sdk/lib/_internal/compiler/implementation/types/type_mask.dart

Issue 14049010: Take noSuchMethod into account when computing the potential targets of a call. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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/types/type_mask.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/types/type_mask.dart (revision 21607)
+++ sdk/lib/_internal/compiler/implementation/types/type_mask.dart (working copy)
@@ -362,6 +362,127 @@
}
}
+ /**
+ * Returns whether [element] will be the one used at runtime when being
+ * invoked on an instance of [cls]. [selector] is used to ensure library
+ * privacy is taken into account.
+ */
+ static bool hasElementIn(ClassElement cls,
+ Selector selector,
+ Element element) {
+ // Use [:implementation:] of [element]
+ // because our function set only stores declarations.
+ Element result = findMatchIn(cls, selector);
+ return result == null
+ ? false
+ : result.implementation == element.implementation;
+ }
+
+ static Element findMatchIn(ClassElement cls, Selector selector) {
+ // Use the [:implementation] of [cls] in case the found [element]
+ // is in the patch class.
+ return cls.implementation.lookupSelector(selector);
+ }
+
+ /**
+ * Returns whether [element] is a potential target when being
+ * invoked on this type mask. [selector] is used to ensure library
+ * privacy is taken into account.
+ */
+ bool canHit(Element element, Selector selector, Compiler compiler) {
+ if (isEmpty) {
+ if (!isNullable) return false;
+ return hasElementIn(
+ compiler.backend.nullImplementation, selector, element);
+ }
+
+ // TODO(kasperl): Can't we just avoid creating typed selectors
+ // based of function types?
+ Element self = base.element;
+ if (self.isTypedef()) {
+ // A typedef is a function type that doesn't have any
+ // user-defined members.
+ return false;
+ }
+
+ ClassElement other = element.getEnclosingClass();
+ if (compiler.backend.isNullImplementation(other)) {
+ return isNullable;
+ } else if (isExact) {
+ return hasElementIn(self, selector, element);
+ } else if (isSubclass) {
+ return hasElementIn(self, selector, element)
+ || other.isSubclassOf(self)
+ || compiler.world.hasAnySubclassThatMixes(self, other);
+ } else {
+ assert(isSubtype);
+ if (other.implementsInterface(self)
+ || other.isSubclassOf(self)
+ || compiler.world.hasAnySubclassThatMixes(self, other)
+ || compiler.world.hasAnySubclassThatImplements(other, base)) {
+ return true;
+ }
+
+ // If [self] is a subclass of [other], it inherits the
+ // implementation of [element].
+ ClassElement cls = self;
+ if (cls.isSubclassOf(other)) {
+ // Resolve an invocation of [element.name] on [self]. If it
+ // is found, this selector is a candidate.
+ return hasElementIn(cls, selector, element);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether a [selector] call on an instance of [cls]
+ * will hit a method at runtime, and not go through [noSuchMethod].
+ */
+ static bool hasConcreteMatch(ClassElement cls,
+ Selector selector,
+ Compiler compiler) {
+ Element element = findMatchIn(cls, selector);
+ return element != null
+ && !element.isAbstract(compiler)
+ && selector.appliesUntyped(element, compiler);
+ }
+
+ /**
+ * Returns whether a [selector] call will hit a method at runtime,
+ * and not go through [noSuchMethod].
+ */
+ bool willHit(Selector selector, Compiler compiler) {
+ Element cls;
+ if (isEmpty) {
+ if (!isNullable) return false;
+ cls = compiler.backend.nullImplementation;
+ } else {
+ cls = base.element;
+ }
+
+ if (!cls.isAbstract(compiler)) {
+ return hasConcreteMatch(cls, selector, compiler);
+ }
+
+ Set<ClassElement> subtypesToCheck;
+ if (isExact) {
+ return false;
+ } else if (isSubtype) {
+ subtypesToCheck = compiler.world.subtypes[cls];
+ } else {
+ assert(isSubclass);
+ subtypesToCheck = compiler.world.subclasses[cls];
+ }
+
+ return subtypesToCheck != null
+ && subtypesToCheck.every((ClassElement cls) {
+ return cls.isAbstract(compiler)
+ ? true
+ : hasConcreteMatch(cls, selector, compiler);
+ });
+ }
+
bool operator ==(var other) {
if (other is !TypeMask) return false;
TypeMask otherMask = other;

Powered by Google App Engine
This is Rietveld 408576698