+
+ @Override
+ public int hashCode(int hash) {
+ int count=1;
+ {
+ Type t = Types.canonical(type);
+ while(t instanceof TForAll) {
+ t = Types.canonical( ((TForAll)t).type );
+ ++count;
+ }
+ }
+ TVar[] boundVars = new TVar[count];
+ boundVars[0] = var;
+ TForAll t = this;
+ {
+ for(int i=1;i<count;++i) {
+ t = (TForAll)Types.canonical(t.type);
+ boundVars[i] = t.var;
+ }
+ }
+
+ for(int i=0;i<count;++i)
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
+ return t.type.hashCode(hash, boundVars);
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] oldBoundVars) {
+ int count=1;
+ {
+ Type t = Types.canonical(type);
+ while(t instanceof TForAll) {
+ t = Types.canonical( ((TForAll)t).type );
+ ++count;
+ }
+ }
+ TVar[] boundVars = Arrays.copyOf(oldBoundVars, oldBoundVars.length + count);
+ boundVars[oldBoundVars.length] = var;
+ TForAll t = this;
+ {
+ for(int i=1;i<count;++i) {
+ t = (TForAll)Types.canonical(t.type);
+ boundVars[oldBoundVars.length + i] = t.var;
+ }
+ }
+
+ for(int i=0;i<count;++i)
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
+ return t.type.hashCode(hash, boundVars);
+ }
+
+ public Type getCanonicalType() {
+ if(type instanceof TMetaVar)
+ type = type.canonical();
+ return type;
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TForAll.class))
+ return false;
+ TForAll forAll = (TForAll)other;
+ return getCanonicalType().equalsCanonical(forAll.getCanonicalType().replace(forAll.var, var));
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return Kinds.STAR;
+ }
+