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

Unified Diff: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java

Issue 11293058: Issue 5157. Introduce TypeQuality. Try to find member in subclasses. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 1 month 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: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
index 82deb87fe8b0859f423b10665f2ddd4471985e00..398b1e70fe677812fcc7e71e2dec7afce911f875 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -218,7 +218,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
return true;
}
// was assignment, inferred
- if (type != null && type.isInferred()) {
+ if (type != null && TypeQuality.isInferred(type)) {
return true;
}
// was declared with type, keep it
@@ -442,7 +442,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
}
// may be replace type of variable
- setVariableElementType(lhsNode.getElement(), rhs);
+ setVariableElementType(lhsNode.getElement(), rhs, getTypeQuality(rhsNode));
checkAssignableElement(lhsNode);
// if cascade, then use type of "lhs" qualifier
if (lhsNode instanceof DartPropertyAccess) {
@@ -653,10 +653,17 @@ public class TypeAnalyzer implements DartCompilationPhase {
if (member == null) {
member = itype.lookupMember("setter " + methodName);
}
+ // is "receiver" is inferred, attempt to find member in one of the subtypes
+ if (member == null) {
+ if (TypeQuality.of(receiver) == TypeQuality.INFERRED && receiver instanceof InterfaceType) {
+ member = ((InterfaceType) receiver).lookupSubTypeMember(methodName);
+ }
+ }
+ // report problem
if (member == null && problemTarget != null) {
if (reportNoMemberWhenHasInterceptor || !Elements.handlesNoSuchMethod(itype)) {
- if (typeChecksForInferredTypes || !receiver.isInferred()) {
- ErrorCode code = receiver.isInferred()
+ if (typeChecksForInferredTypes || !TypeQuality.isInferred(receiver)) {
+ ErrorCode code = TypeQuality.isInferred(receiver)
? TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED_INFERRED
: TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED;
typeError(problemTarget, code, receiver, methodName);
@@ -671,10 +678,10 @@ public class TypeAnalyzer implements DartCompilationPhase {
* If left-hand-side is {@link VariableElement} with propagated type, then remember type before
* current "basic block" and set new type.
*/
- private void setVariableElementType(Element element, Type rhs) {
+ private void setVariableElementType(Element element, Type type, TypeQuality quality) {
if (ElementKind.of(element) == ElementKind.VARIABLE) {
VariableElement variableElement = (VariableElement) element;
- Type newType = Types.makeInferred(rhs);
+ Type newType = Types.makeInferred(type, quality);
blockOldTypes.getFirst().setType(variableElement, newType);
}
}
@@ -690,7 +697,8 @@ public class TypeAnalyzer implements DartCompilationPhase {
* @return <code>true</code> if given {@link Element} is has inferred {@link Type}.
*/
private static boolean hasInferredType(Element element) {
- return element != null && element.getType() != null && element.getType().isInferred();
+ return element != null && element.getType() != null
+ && element.getType().getQuality() != TypeQuality.EXACT;
}
/**
@@ -771,7 +779,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
// apply inferred type
if (inferredType != null) {
- if (TypeKind.of(currentType) == TypeKind.DYNAMIC && currentType.isInferred()) {
+ if (TypeKind.of(currentType) == TypeKind.DYNAMIC && TypeQuality.isInferred(currentType)) {
// if we fell back to Dynamic, keep it
} else {
Type unionType = getUnionType(currentType, inferredType);
@@ -938,11 +946,22 @@ public class TypeAnalyzer implements DartCompilationPhase {
* If type of variable-like {@link DartDeclaration} (i.e. variables, parameter, field) is not
* specified and we know somehow this type, then use it.
*/
- private static void inferVariableDeclarationType(DartDeclaration<?> node, Type type) {
+ private static void inferVariableDeclarationType(DartDeclaration<?> node, DartExpression value) {
+ Type type = value.getType();
+ TypeQuality quality = getTypeQuality(value);
+ inferVariableDeclarationType(node, type, quality);
+ }
+
+ /**
+ * If type of variable-like {@link DartDeclaration} (i.e. variables, parameter, field) is not
+ * specified and we know somehow this type, then use it.
+ */
+ private static void inferVariableDeclarationType(DartDeclaration<?> node, Type type,
+ TypeQuality typeQuality) {
if (type != null && TypeKind.of(type) != TypeKind.DYNAMIC) {
Element element = node.getElement();
if (element != null && TypeKind.of(element.getType()) == TypeKind.DYNAMIC) {
- Type inferredType = Types.makeInferred(type);
+ Type inferredType = Types.makeInferred(type, typeQuality);
Elements.setType(element, inferredType);
node.getName().setType(inferredType);
}
@@ -976,7 +995,8 @@ public class TypeAnalyzer implements DartCompilationPhase {
for (int i = 0; i < n; i++) {
Type requiredNormalParameterType = requiredNormalParameterTypes.get(i);
DartParameter parameterNode = parameterNodes.get(i);
- inferVariableDeclarationType(parameterNode, requiredNormalParameterType);
+ inferVariableDeclarationType(parameterNode, requiredNormalParameterType,
+ TypeQuality.INFERRED);
}
}
}
@@ -990,7 +1010,8 @@ public class TypeAnalyzer implements DartCompilationPhase {
Type newType = blockTypeContext.newTypes.get(variable);
Type oldType = blockTypeContext.oldTypes.get(variable);
Type mergedType = types.intersection(newType, oldType);
- setVariableElementType(variable, mergedType);
+ TypeQuality mergedTypeQuality = Types.getIntersectionQuality(newType, oldType);
+ setVariableElementType(variable, mergedType, mergedTypeQuality);
}
}
@@ -999,13 +1020,13 @@ public class TypeAnalyzer implements DartCompilationPhase {
s.getClass(); // Null check.
// ignore inferred types, treat them as Dynamic
if (!typeChecksForInferredTypes) {
- if (t.isInferred() || s.isInferred()) {
+ if (TypeQuality.isInferred(t) || TypeQuality.isInferred(s)) {
return true;
}
}
// do check and report error
if (!types.isAssignable(t, s)) {
- TypeErrorCode errorCode = t.isInferred() || s.isInferred()
+ TypeErrorCode errorCode = TypeQuality.isInferred(t) || TypeQuality.isInferred(s)
? TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE_INFERRED
: TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE;
typeError(node, errorCode, s, t);
@@ -1034,7 +1055,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
private FunctionType getMethodType(Type receiver, Member member, String name,
DartNode diagnosticNode) {
FunctionType functionType = getMethodType0(receiver, member, name, diagnosticNode);
- if (receiver.isInferred()) {
+ if (TypeQuality.isInferred(receiver)) {
functionType = (FunctionType) Types.makeInferred(functionType);
}
return functionType;
@@ -1078,8 +1099,8 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
}
default:
- if (typeChecksForInferredTypes || !receiver.isInferred()) {
- TypeErrorCode errorCode = receiver.isInferred()
+ if (typeChecksForInferredTypes || !TypeQuality.isInferred(receiver)) {
+ TypeErrorCode errorCode = TypeQuality.isInferred(receiver)
? TypeErrorCode.NOT_A_METHOD_IN_INFERRED : TypeErrorCode.NOT_A_METHOD_IN;
typeError(diagnosticNode, errorCode, name, receiver);
}
@@ -1994,7 +2015,8 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
// do merge
Type mergedType = types.intersection(possibleTypes);
- setVariableElementType(variable, mergedType);
+ TypeQuality mergedTypeQuality = Types.getIntersectionQuality(possibleTypes);
+ setVariableElementType(variable, mergedType, mergedTypeQuality);
}
}
// done
@@ -2337,16 +2359,24 @@ public class TypeAnalyzer implements DartCompilationPhase {
member = member2;
}
}
+ // is "receiver" is inferred, attempt to find member in one of the subtypes
+ if (member == null) {
+ if (TypeQuality.of(receiver) == TypeQuality.INFERRED && receiver instanceof InterfaceType) {
+ member = ((InterfaceType) receiver).lookupSubTypeMember(name);
+ }
+ }
+ // report "not a member"
if (member == null) {
if (reportNoMemberWhenHasInterceptor || !Elements.handlesNoSuchMethod(cls)) {
- if (typeChecksForInferredTypes || !receiver.isInferred()) {
- TypeErrorCode errorCode = receiver.isInferred()
+ if (typeChecksForInferredTypes || !TypeQuality.isInferred(receiver)) {
+ TypeErrorCode errorCode = TypeQuality.isInferred(receiver)
? TypeErrorCode.NOT_A_MEMBER_OF_INFERRED : TypeErrorCode.NOT_A_MEMBER_OF;
typeError(node.getName(), errorCode, name, cls);
}
}
return dynamicType;
}
+ // set resolved element
element = member.getElement();
node.setElement(element);
Modifiers modifiers = element.getModifiers();
@@ -2835,8 +2865,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
Type result = checkInitializedDeclaration(node, value);
// if no type declared for variables, try to use type of value
if (value != null) {
- Type valueType = value.getType();
- inferVariableDeclarationType(node, valueType);
+ inferVariableDeclarationType(node, value);
}
// done
return result;
@@ -2945,8 +2974,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
// only final fields, because only in this case we can be sure that field is not assigned
// somewhere, may be even not in this unit
if (node.getModifiers().isFinal() && value != null) {
- Type valueType = value.getType();
- inferVariableDeclarationType(node, valueType);
+ inferVariableDeclarationType(node, value);
}
// done
return result;
@@ -3516,7 +3544,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
return namedParameters;
}
-
+
private Map<String, DartExpression> getParametersDefaultsNamed(List<VariableElement> parameters) {
Map<String, DartExpression> defaults = Maps.newHashMap();
for (VariableElement parameter : parameters) {
@@ -3529,8 +3557,51 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
}
- private static boolean isExclicitlySpecifiedType(Type fieldType) {
- return fieldType != null && TypeKind.of(fieldType) != TypeKind.DYNAMIC
- && !fieldType.isInferred();
+ private static boolean isExclicitlySpecifiedType(Type type) {
Brian Wilkerson 2012/11/02 14:00:35 nit: "Exclicitly" --> "Explicitly"
+ return type != null && TypeKind.of(type) != TypeKind.DYNAMIC
+ && !TypeQuality.isInferred(type);
+ }
+
+ /**
+ * @return the {@link TypeQuality} of given {@link DartExpression}.
+ */
+ public static TypeQuality getTypeQuality(DartExpression expr) {
+ if (expr != null) {
+ if (expr instanceof DartMethodInvocation) {
+ return TypeQuality.INFERRED;
+ }
+ if (expr instanceof DartUnqualifiedInvocation) {
+ return TypeQuality.INFERRED;
+ }
+ if (expr instanceof DartUnaryExpression) {
+ DartUnaryExpression unary = (DartUnaryExpression) expr;
+ if (hasTypeBoolIntDouble(unary.getArg())) {
+ return TypeQuality.INFERRED_EXACT;
+ }
+ return TypeQuality.INFERRED;
+ }
+ if (expr instanceof DartBinaryExpression) {
+ DartBinaryExpression binary = (DartBinaryExpression) expr;
+ if (hasTypeBoolIntDouble(binary.getArg1()) && hasTypeBoolIntDouble(binary.getArg2())) {
+ return TypeQuality.INFERRED_EXACT;
+ }
+ return TypeQuality.INFERRED;
+ }
+ if (expr instanceof DartNewExpression) {
+ return TypeQuality.INFERRED;
+ }
+ }
+ return TypeQuality.INFERRED_EXACT;
+ }
+
+ private static boolean hasTypeBoolIntDouble(DartExpression expr) {
+ Type type = expr.getType();
+ return isCoreType(type, "bool") || isCoreType(type, "int") || isCoreType(type, "double");
+ }
+
+ private static boolean isCoreType(Type type, String name) {
+ return type != null
+ && Elements.isCoreLibrarySource(type.getElement().getSourceInfo().getSource())
+ && type.getElement().getName().equals(name);
}
}
« no previous file with comments | « compiler/java/com/google/dart/compiler/type/Type.java ('k') | compiler/java/com/google/dart/compiler/type/Types.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698