public SubstMap unify(final Loc loc, final Type other, final TypeEnv env) { if (env.checkVisited(this, other)) return SubstMap.EMPTY; if (other instanceof TypeVar) return SubstMap.bindVar(loc, (TypeVar) other, this); // if our application expression can be evaluated, unify against that. if (isAbsApply()) return eval().unify(loc, other, env); final Type otherEval = other.deref().eval(); if (otherEval instanceof TypeApp) { final TypeApp otherApp = (TypeApp) otherEval; final SubstMap baseSubst = base.unify(loc, otherApp.base, env); if (baseSubst != null) { final SubstMap argSubst = arg.subst(baseSubst).unify(loc, otherApp.arg.subst(baseSubst), env); if (argSubst != null) return baseSubst.compose(loc, argSubst); } } else if (kind.equals(otherEval.getKind())) { // other is not an application expression, but kinds match. // other type classes do opportunistic matching of type apps // implementations of unify. This approach is really ad-hoc, // needs to be rationalized. return otherEval.unify(loc, this, env); } return null; }
/** internal reality checks on param/arg kinds */ private boolean checkKindAgreement(final Type abs, final Type argDeref) { final Kind absKind = abs.getKind(); if (!(absKind instanceof ArrowKind)) { Session.error( loc, "internal error: abs {0} has non-lambda kind {1} in type app {2}", abs.dump(), absKind.dump(), dump()); return false; } final Kind paramKind = ((ArrowKind) absKind).getParamKind(); final Kind argKind = argDeref.getKind(); if (!paramKind.equals(argKind)) { Session.error( loc, "internal error: param kind {0} incompatible with arg kind {1} in type app {2}", paramKind.dump(), argKind.dump(), dump()); return false; } return true; }
@Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; final TypeParam typeParam = (TypeParam) o; if (kind != null ? !kind.equals(typeParam.kind) : typeParam.kind != null) return false; if (typeScope != null ? typeScope != typeParam.typeScope : typeParam.typeScope != null) return false; return true; }
@Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (kind != null ? kind.hashCode() : 0); return result; }