fixes bugs in TypeInfo
This commit is contained in:
@@ -1740,7 +1740,22 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
v.dup();
|
v.dup();
|
||||||
}
|
}
|
||||||
Type type = typeMapper.boxType(typeMapper.mapType(jetType, OwnerKind.INTERFACE));
|
Type type = typeMapper.boxType(typeMapper.mapType(jetType, OwnerKind.INTERFACE));
|
||||||
v.instanceOf(type);
|
if(jetType.isNullable()) {
|
||||||
|
Label nope = new Label();
|
||||||
|
Label end = new Label();
|
||||||
|
|
||||||
|
v.dup();
|
||||||
|
v.ifnull(nope);
|
||||||
|
v.instanceOf(type);
|
||||||
|
v.goTo(end);
|
||||||
|
v.mark(nope);
|
||||||
|
v.pop();
|
||||||
|
v.aconst(1);
|
||||||
|
v.mark(end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.instanceOf(type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.intellij.psi.tree.TokenSet;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
|
import org.jetbrains.jet.lang.ErrorHandler;
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -1708,7 +1709,7 @@ public class JetTypeInferrer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
|
if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
|
||||||
context.trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType); // TODO : message
|
context.trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType + " " + ErrorHandler.atLocation(reportErrorOn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,66 @@
|
|||||||
class A() {}
|
class A() {}
|
||||||
class B<T>() {}
|
class B<T>() {
|
||||||
|
fun isT (a : Any?) : Boolean {
|
||||||
|
return a is T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun box() : String {
|
fun t1() : Boolean {
|
||||||
val a = A()
|
val a = A()
|
||||||
System.out?.println(a is A) //true
|
if(a !is A) return false
|
||||||
System.out?.println(a is A?) //true
|
if(a !is A?) return false
|
||||||
|
if(null !is A?) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t2 () : Boolean {
|
||||||
val b = B<String>()
|
val b = B<String>()
|
||||||
System.out?.println(b is B<String>) //true
|
if(b !is B<String>) return false
|
||||||
System.out?.println(b is B<String>?) //false !!!
|
if(b !is B<String>?) return false
|
||||||
|
if(null !is B<String>?) return false
|
||||||
|
|
||||||
val v = b as B<String> //ok
|
val v = b as B<String> //ok
|
||||||
val u = b as B<String>? //TypeCastException
|
val u = b as B<String>? //TypeCastException
|
||||||
|
|
||||||
val w : B<String>? = b as B<String> //ok
|
val w : B<String>? = b as B<String> //ok
|
||||||
val x = w as B<String>? //TypeCastException
|
val x = w as B<String>? //TypeCastException
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t3 () : Boolean {
|
||||||
|
val b = B<String>()
|
||||||
|
if(!b.isT("aaa")) return false
|
||||||
|
|
||||||
|
if(b.isT(10)) return false
|
||||||
|
if(b.isT(null)) return false
|
||||||
|
|
||||||
|
val d = B<String?>()
|
||||||
|
if(!d.isT("aaa")) return false
|
||||||
|
if(d.isT(10)) return false
|
||||||
|
if(!d.isT(null)) return false
|
||||||
|
|
||||||
|
val c = B<Int>()
|
||||||
|
if(c.isT("aaa")) return false
|
||||||
|
if(!c.isT(10)) return false
|
||||||
|
if(c.isT(null)) return false
|
||||||
|
|
||||||
|
val e = B<Int?>()
|
||||||
|
if(e.isT("aaa")) return false
|
||||||
|
if(!e.isT(10)) return false
|
||||||
|
if(!e.isT(null)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
if(!t1()) {
|
||||||
|
return "t1 failed"
|
||||||
|
}
|
||||||
|
if(!t2()) {
|
||||||
|
return "t2 failed"
|
||||||
|
}
|
||||||
|
if(!t3()) {
|
||||||
|
return "t3 failed"
|
||||||
|
}
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -40,25 +40,28 @@ public class TypeInfo<T> implements JetObject {
|
|||||||
|
|
||||||
public boolean isInstance(Object obj) {
|
public boolean isInstance(Object obj) {
|
||||||
if (obj instanceof JetObject) {
|
if (obj instanceof JetObject) {
|
||||||
return isSubtypeOf(((JetObject) obj).getTypeInfo());
|
return ((JetObject) obj).getTypeInfo().isSubtypeOf(this);
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException(); // TODO
|
if(obj == null)
|
||||||
|
return nullable;
|
||||||
|
|
||||||
|
return theClass.isAssignableFrom(obj.getClass()); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSubtypeOf(TypeInfo<?> other) {
|
public boolean isSubtypeOf(TypeInfo<?> superType) {
|
||||||
if (!theClass.isAssignableFrom(other.theClass)) {
|
if (!superType.theClass.isAssignableFrom(theClass)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!nullable && other.nullable) {
|
if (nullable && !superType.nullable) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeParameters != null) {
|
if (typeParameters != null) {
|
||||||
if (other.typeParameters == null || other.typeParameters.length != typeParameters.length) {
|
if (superType.typeParameters == null || superType.typeParameters.length != typeParameters.length) {
|
||||||
throw new IllegalArgumentException("inconsistent type infos for the same class");
|
throw new IllegalArgumentException("inconsistent type infos for the same class");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < typeParameters.length; i++) {
|
for (int i = 0; i < typeParameters.length; i++) {
|
||||||
// TODO handle variance here
|
// TODO handle variance here
|
||||||
if (!typeParameters [i].equals(other.typeParameters [i])) {
|
if (!typeParameters [i].equals(superType.typeParameters [i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,9 +98,22 @@ public class TypeInfo<T> implements JetObject {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = theClass.hashCode();
|
return 31 * theClass.hashCode() + (typeParameters != null ? Arrays.hashCode(typeParameters) : 0);
|
||||||
result = 31 * result + (typeParameters != null ? Arrays.hashCode(typeParameters) : 0);
|
}
|
||||||
return result;
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder().append(theClass.getName());
|
||||||
|
if(typeParameters != null && typeParameters.length != 0) {
|
||||||
|
sb.append("<");
|
||||||
|
for(int i = 0; i != typeParameters.length-1; ++i) {
|
||||||
|
sb.append(typeParameters[i].toString()).append(",");
|
||||||
|
}
|
||||||
|
sb.append(typeParameters[typeParameters.length - 1].toString()).append(">");
|
||||||
|
}
|
||||||
|
if(nullable)
|
||||||
|
sb.append("?");
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final TypeInfo<Byte> BYTE_TYPE_INFO = new TypeInfo<Byte>(Byte.class, false);
|
public static final TypeInfo<Byte> BYTE_TYPE_INFO = new TypeInfo<Byte>(Byte.class, false);
|
||||||
|
|||||||
Reference in New Issue
Block a user