use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Types method closureMin.
/**
* Return the minimum types of a closure, suitable for computing
* compoundMin or glb.
*/
private List<Type> closureMin(List<Type> cl) {
ListBuffer<Type> classes = new ListBuffer<>();
ListBuffer<Type> interfaces = new ListBuffer<>();
Set<Type> toSkip = new HashSet<>();
while (!cl.isEmpty()) {
Type current = cl.head;
boolean keep = !toSkip.contains(current);
if (keep && current.hasTag(TYPEVAR)) {
// skip lower-bounded variables with a subtype in cl.tail
for (Type t : cl.tail) {
if (isSubtypeNoCapture(t, current)) {
keep = false;
break;
}
}
}
if (keep) {
if (current.isInterface())
interfaces.append(current);
else
classes.append(current);
for (Type t : cl.tail) {
// skip supertypes of 'current' in cl.tail
if (isSubtypeNoCapture(current, t))
toSkip.add(t);
}
}
cl = cl.tail;
}
return classes.appendList(interfaces).toList();
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Types method capture.
public Type capture(Type t) {
if (!t.hasTag(CLASS)) {
return t;
}
if (t.getEnclosingType() != Type.noType) {
Type capturedEncl = capture(t.getEnclosingType());
if (capturedEncl != t.getEnclosingType()) {
Type type1 = memberType(capturedEncl, t.tsym);
t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments());
}
}
t = t.unannotatedType();
ClassType cls = (ClassType) t;
if (cls.isRaw() || !cls.isParameterized())
return cls;
ClassType G = (ClassType) cls.asElement().asType();
List<Type> A = G.getTypeArguments();
List<Type> T = cls.getTypeArguments();
List<Type> S = freshTypeVariables(T);
List<Type> currentA = A;
List<Type> currentT = T;
List<Type> currentS = S;
boolean captured = false;
while (!currentA.isEmpty() && !currentT.isEmpty() && !currentS.isEmpty()) {
if (currentS.head != currentT.head) {
captured = true;
WildcardType Ti = (WildcardType) currentT.head.unannotatedType();
Type Ui = currentA.head.getUpperBound();
CapturedType Si = (CapturedType) currentS.head.unannotatedType();
if (Ui == null)
Ui = syms.objectType;
switch(Ti.kind) {
case UNBOUND:
Si.bound = subst(Ui, A, S);
Si.lower = syms.botType;
break;
case EXTENDS:
Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S));
Si.lower = syms.botType;
break;
case SUPER:
Si.bound = subst(Ui, A, S);
Si.lower = Ti.getSuperBound();
break;
}
Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar) Si.bound).qtype : Si.bound;
Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar) Si.lower).qtype : Si.lower;
if (!Si.bound.hasTag(ERROR) && !Si.lower.hasTag(ERROR) && isSameType(tmpBound, tmpLower, false)) {
currentS.head = Si.bound;
}
}
currentA = currentA.tail;
currentT = currentT.tail;
currentS = currentS.tail;
}
if (!currentA.isEmpty() || !currentT.isEmpty() || !currentS.isEmpty())
// some "rare" type involved
return erasure(t);
if (captured)
return new ClassType(cls.getEnclosingType(), S, cls.tsym);
else
return t;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Types method sideCastFinal.
private boolean sideCastFinal(Type from, Type to, Warner warn) {
// We are casting from type $from$ to type $to$, which are
// unrelated types one of which is final and the other of
// which is an interface. This method
// tries to reject a cast by transferring type parameters
// from the final class to the interface.
boolean reverse = false;
Type target = to;
if ((to.tsym.flags() & INTERFACE) == 0) {
Assert.check((from.tsym.flags() & INTERFACE) != 0);
reverse = true;
to = from;
from = target;
}
Assert.check((from.tsym.flags() & FINAL) != 0);
Type t1 = asSuper(from, to.tsym);
if (t1 == null)
return false;
Type t2 = to;
if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
return false;
if (!allowCovariantReturns)
// reject if there is a common method signature with
// incompatible return types.
chk.checkCompatibleAbstracts(warn.pos(), from, to);
if (!isReifiable(target) && (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)))
warn.warn(LintCategory.UNCHECKED);
return true;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Types method sideCast.
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Internal utility methods">
private boolean sideCast(Type from, Type to, Warner warn) {
// We are casting from type $from$ to type $to$, which are
// non-final unrelated types. This method
// tries to reject a cast by transferring type parameters
// from $to$ to $from$ by common superinterfaces.
boolean reverse = false;
Type target = to;
if ((to.tsym.flags() & INTERFACE) == 0) {
Assert.check((from.tsym.flags() & INTERFACE) != 0);
reverse = true;
to = from;
from = target;
}
List<Type> commonSupers = superClosure(to, erasure(from));
boolean giveWarning = commonSupers.isEmpty();
// get a more accurate analysis
while (commonSupers.nonEmpty()) {
Type t1 = asSuper(from, commonSupers.head.tsym);
// same as asSuper(to, commonSupers.head.tsym);
Type t2 = commonSupers.head;
if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments()))
return false;
giveWarning = giveWarning || (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2));
commonSupers = commonSupers.tail;
}
if (giveWarning && !isReifiable(reverse ? from : to))
warn.warn(LintCategory.UNCHECKED);
if (!allowCovariantReturns)
// reject if there is a common method signature with
// incompatible return types.
chk.checkCompatibleAbstracts(warn.pos(), from, to);
return true;
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type in project ceylon by eclipse.
the class Types method substBounds.
public List<Type> substBounds(List<Type> tvars, List<Type> from, List<Type> to) {
if (tvars.isEmpty())
return tvars;
ListBuffer<Type> newBoundsBuf = new ListBuffer<>();
boolean changed = false;
// calculate new bounds
for (Type t : tvars) {
TypeVar tv = (TypeVar) t;
Type bound = subst(tv.bound, from, to);
if (bound != tv.bound)
changed = true;
newBoundsBuf.append(bound);
}
if (!changed)
return tvars;
ListBuffer<Type> newTvars = new ListBuffer<>();
// create new type variables without bounds
for (Type t : tvars) {
newTvars.append(new TypeVar(t.tsym, null, syms.botType));
}
// the new bounds should use the new type variables in place
// of the old
List<Type> newBounds = newBoundsBuf.toList();
from = tvars;
to = newTvars.toList();
for (; !newBounds.isEmpty(); newBounds = newBounds.tail) {
newBounds.head = subst(newBounds.head, from, to);
}
newBounds = newBoundsBuf.toList();
// set the bounds of new type variables to the new bounds
for (Type t : newTvars.toList()) {
TypeVar tv = (TypeVar) t;
tv.bound = newBounds.head;
// Fix for Ceylon: try really hard not to make recursive bounds
if (tv.bound == tv)
tv.bound = null;
newBounds = newBounds.tail;
}
return newTvars.toList();
}
Aggregations