Type checking for basic patterns

This commit is contained in:
Andrey Breslav
2011-05-19 23:34:27 +04:00
parent 298407210e
commit 5ad5a0e5e9
2 changed files with 90 additions and 44 deletions
@@ -1019,49 +1019,7 @@ public class JetTypeInferrer {
@Override
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
JetPattern pattern = condition.getPattern();
if (pattern != null) {
pattern.accept(new JetVisitor() {
@Override
public void visitTypePattern(JetTypePattern typePattern) {
JetTypeReference typeReference = typePattern.getTypeReference();
if (typeReference != null) {
JetType type = typeResolver.resolveType(scope, typeReference);
if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(type, finalSubjectType)) == null) {
trace.getErrorHandler().genericError(typePattern.getNode(), "Incompatible types"); // TODO : message
}
}
}
@Override
public void visitWildcardPattern(JetWildcardPattern pattern) {
// Nothing
}
@Override
public void visitExpressionPattern(JetExpressionPattern pattern) {
getType(scope, pattern.getExpression(), false); // TODO : check type compatibility
trace.getErrorHandler().genericWarning(pattern.getNode(), "TODO : Types not checked");
}
@Override
public void visitTuplePattern(JetTuplePattern pattern) {
for (JetTuplePatternEntry entry : pattern.getEntries()) {
// TODO : is a name always allowed, ie for tuple patterns, not decomposer arg lists?
String nameLabel = entry.getNameLabel();
JetPattern entryPattern = entry.getPattern();
if (entryPattern != null) {
entryPattern.accept(this); // TODO : type checking
}
}
}
@Override
public void visitJetElement(JetElement elem) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported [JetTypeInferrer]");
}
});
}
checkPatternType(condition.getPattern(), finalSubjectType);
}
@Override
@@ -1082,6 +1040,71 @@ public class JetTypeInferrer {
}
}
private void checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType) {
pattern.accept(new JetVisitor() {
@Override
public void visitTypePattern(JetTypePattern typePattern) {
JetTypeReference typeReference = typePattern.getTypeReference();
if (typeReference != null) {
JetType type = typeResolver.resolveType(scope, typeReference);
checkTypeCompatibility(type, subjectType, typePattern);
}
}
@Override
public void visitWildcardPattern(JetWildcardPattern pattern) {
// Nothing
}
@Override
public void visitExpressionPattern(JetExpressionPattern pattern) {
JetType type = getType(scope, pattern.getExpression(), false);
checkTypeCompatibility(type, subjectType, pattern);
}
@Override
public void visitTuplePattern(JetTuplePattern pattern) {
List<JetTuplePatternEntry> entries = pattern.getEntries();
TypeConstructor typeConstructor = subjectType.getConstructor();
if (!JetStandardClasses.getTuple(entries.size()).getTypeConstructor().equals(typeConstructor)
|| typeConstructor.getParameters().size() != entries.size()) {
trace.getErrorHandler().genericError(pattern.getNode(), "Type mismatch: subject is of type " + subjectType + " but the pattern if of type Tuple" + entries.size()); // TODO : message
}
else {
for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) {
JetTuplePatternEntry entry = entries.get(i);
JetType type = subjectType.getArguments().get(i).getType();
// TODO : is a name always allowed, ie for tuple patterns, not decomposer arg lists?
ASTNode nameLabelNode = entry.getNameLabelNode();
if (nameLabelNode != null) {
trace.getErrorHandler().genericError(nameLabelNode, "Unsupported [JetTypeInferrer]");
}
JetPattern entryPattern = entry.getPattern();
if (entryPattern != null) {
checkPatternType(entryPattern, type);
}
}
}
}
private void checkTypeCompatibility(@Nullable JetType type, @NotNull JetType subjectType, @NotNull JetElement reportErrorOn) {
if (type == null) {
return;
}
if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType); // TODO : message
}
}
@Override
public void visitJetElement(JetElement elem) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported [JetTypeInferrer]");
}
});
}
@Override
public void visitTryExpression(JetTryExpression expression) {
JetExpression tryBlock = expression.getTryBlock();
+24 -1
View File
@@ -21,4 +21,27 @@ fun foo() {
}
}
val _type_test : Int = foo() // this is needed to ensure the inferred return type of foo()
val _type_test : Int = foo() // this is needed to ensure the inferred return type of foo()
fun test() {
val x = 1;
val s = "";
when (x) {
<error>s</error> => 1
is <error>""</error> => 1
x => 1
is 1 => 1
is <error>(1, 1)</error> => 1
}
val z = (1, 1)
when (z) {
is (*, *) => 1
is (*, 1) => 1
is (1, 1) => 1
is (1, <error>"1"</error>) => 1
is <error>(1, "1", *)</error> => 1
}
}