Type checking for basic patterns
This commit is contained in:
@@ -1019,49 +1019,7 @@ public class JetTypeInferrer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
|
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
|
||||||
JetPattern pattern = condition.getPattern();
|
checkPatternType(condition.getPattern(), finalSubjectType);
|
||||||
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]");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
public void visitTryExpression(JetTryExpression expression) {
|
public void visitTryExpression(JetTryExpression expression) {
|
||||||
JetExpression tryBlock = expression.getTryBlock();
|
JetExpression tryBlock = expression.getTryBlock();
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user