use of org.eclipse.ceylon.model.typechecker.model.Unit in project ceylon by eclipse.
the class InheritanceVisitor method collectCaseTypes.
void collectCaseTypes(Tree.CaseTypes that, TypeDeclaration td) {
Set<TypeDeclaration> typeSet = new HashSet<TypeDeclaration>();
for (Tree.StaticType ct : that.getTypes()) {
Type type = ct.getTypeModel();
if (!isTypeUnknown(type)) {
type = type.resolveAliases();
TypeDeclaration ctd = type.getDeclaration();
if (!typeSet.add(ctd)) {
// this error is not really truly necessary
Unit unit = that.getUnit();
ct.addError("duplicate case type: '" + ctd.getName(unit) + "' of '" + td.getName() + "'");
}
if (!(ctd instanceof TypeParameter)) {
// it's not a self type
if (checkDirectSubtype(td, ct, type)) {
checkAssignable(type, td.getType(), ct, getCaseTypeExplanation(td, type));
}
// note: this is a better, faster way to call
// validateEnumeratedSupertypeArguments()
// but unfortunately it winds up displaying
// the error on the wrong node, confusing
// the user
/*
Type supertype =
type.getDeclaration()
.getType()
.getSupertype(td);
validateEnumeratedSupertypeArguments(t,
type.getDeclaration(), supertype);
*/
}
checkCaseType(td, ct, ctd);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Unit in project ceylon by eclipse.
the class InheritanceVisitor method validateUpperBounds.
private void validateUpperBounds(Tree.TypeConstraint that, TypeDeclaration td) {
if (!td.isInconsistentType()) {
Unit unit = that.getUnit();
List<Type> upperBounds = td.getSatisfiedTypes();
List<Type> list = new ArrayList<Type>(upperBounds.size());
for (Type st : upperBounds) {
addToIntersection(list, st, unit);
}
if (canonicalIntersection(list, unit).isNothing()) {
that.addError(typeDescription(td, unit) + " has unsatisfiable upper bound constraints: the constraints '" + typeNamesAsIntersection(upperBounds, unit) + "' cannot be satisfied by any type except 'Nothing'");
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Unit in project ceylon by eclipse.
the class InheritanceVisitor method visit.
@Override
public void visit(Tree.SatisfiedTypes that) {
super.visit(that);
TypeDeclaration td = (TypeDeclaration) that.getScope();
if (td.isAlias()) {
return;
}
Set<TypeDeclaration> set = new HashSet<TypeDeclaration>();
if (td.getSatisfiedTypes().isEmpty()) {
// handle undecidable case
return;
}
Unit unit = that.getUnit();
for (Tree.StaticType t : that.getTypes()) {
Type type = t.getTypeModel();
if (!isTypeUnknown(type) && type.isClassOrInterface()) {
type = type.resolveAliases();
TypeDeclaration dec = type.getDeclaration();
if (td instanceof ClassOrInterface && !unit.getPackage().getModule().isLanguageModule()) {
if (unit.isCallableType(type)) {
t.addError("satisfies 'Callable'");
}
TypeDeclaration cad = unit.getConstrainedAnnotationDeclaration();
if (dec.equals(cad)) {
t.addError("directly satisfies 'ConstrainedAnnotation'");
}
}
if (!set.add(dec)) {
// this error is not really truly necessary
// but the spec says it is an error, and
// the backend doesn't like it
t.addError("duplicate satisfied type: '" + dec.getName(unit) + "' of '" + td.getName() + "'");
}
if (td instanceof ClassOrInterface) {
TypeDeclaration std = dec;
if (std.isSealed() && !unit.inSameModule(std)) {
String moduleName = std.getUnit().getPackage().getModule().getNameAsString();
t.addError("satisfies a sealed interface in a different module: '" + std.getName(unit) + "' in '" + moduleName + "'");
}
}
checkSelfTypes(t, td, type);
checkExtensionOfMemberType(t, td, type);
/*if (!(td instanceof TypeParameter)) {
checkCaseOfSupertype(t, td, type);
}*/
}
if (t instanceof Tree.SimpleType) {
Tree.SimpleType st = (Tree.SimpleType) t;
checkSupertypeVarianceAnnotations(st);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Unit in project ceylon by eclipse.
the class InheritanceVisitor method validateEnumeratedSupertypes.
private void validateEnumeratedSupertypes(Node that, ClassOrInterface d) {
Type type = d.getType();
Unit unit = that.getUnit();
if (d instanceof Class) {
Type superclass = d.getExtendedType();
if (superclass != null && superclass.isAnything() && !type.isObject() && !type.isNull()) {
// a class which directly extends Anything
// must be handled as a special case here
// because of a performance optimization in
// Class.inherits()
that.addError("not a subtype of any case of root type: '" + d.getName(unit) + "' directly inherits 'Anything'");
}
}
for (Type supertype : type.getSupertypes()) {
if (!type.isExactly(supertype)) {
TypeDeclaration std = supertype.getDeclaration();
List<Type> cts = std.getCaseTypes();
if (cts != null && !cts.isEmpty()) {
if (cts.size() == 1 && cts.get(0).getDeclaration().isSelfType()) {
continue;
}
List<Type> types = new ArrayList<Type>(cts.size());
for (Type ct : cts) {
TypeDeclaration ctd = ct.resolveAliases().getDeclaration();
Type cst = type.getSupertype(ctd);
if (cst != null) {
types.add(cst);
}
}
if (types.isEmpty()) {
that.addError("type is not a subtype of any case of enumerated supertype: '" + d.getName(unit) + "' inherits '" + std.getName(unit) + "'");
} else if (types.size() > 1) {
StringBuilder sb = new StringBuilder();
for (Type pt : types) {
sb.append("'").append(pt.asString(unit)).append("' and ");
}
sb.setLength(sb.length() - 5);
that.addError("type is a subtype of multiple cases of enumerated supertype '" + std.getName(unit) + "': '" + d.getName(unit) + "' inherits " + sb);
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Unit in project ceylon by eclipse.
the class InheritanceVisitor method checkSupertypeIntersection.
private void checkSupertypeIntersection(Node that, TypeDeclaration td, Type st1, Type st2) {
TypeDeclaration st1d = st1.getDeclaration();
TypeDeclaration st2d = st2.getDeclaration();
if (st1d.equals(st2d)) /*&& !st1.isExactly(st2)*/
{
Unit unit = that.getUnit();
if (!areConsistentSupertypes(st1, st2, unit)) {
that.addError(typeDescription(td, unit) + " has the same parameterized supertype twice with incompatible type arguments: '" + st1.asString(unit) + " & " + st2.asString(unit) + "'");
td.setInconsistentType(true);
}
}
}
Aggregations