use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class ClassOrPackageDoc method writeTypeParametersConstraints.
protected final void writeTypeParametersConstraints(List<TypeParameter> typeParameters, Referenceable scope) throws IOException {
for (TypeParameter typeParam : typeParameters) {
if (typeParam.isConstrained()) {
open("div class='type-parameter-constraint'");
write("<span class='type-parameter-keyword'>given</span>");
write(" ");
around("span class='type-parameter'", typeParam.getName());
writeSatisfiedTypes(typeParam, scope);
writeCaseTypes(typeParam, scope);
close("div");
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class ExpressionVisitor method accountForIntermediateRefinements.
private Reference accountForIntermediateRefinements(Tree.SpecifierStatement that, FunctionOrValue refinedMethodOrValue, FunctionOrValue methodOrValue, ClassOrInterface refiningType, List<Declaration> interveningRefinements) {
// accumulate an intersection of the types of
// everything it refines
List<Type> refinedTypes = new ArrayList<Type>();
// don't check this one here because it is
// separately checked in visit(SpecifierStatement)
Reference refinedProducedReference = getRefinedMemberReference(refinedMethodOrValue, refiningType);
Map<TypeParameter, Type> substs = substitutions(refinedMethodOrValue, methodOrValue);
Type refinedType = refinedProducedReference.getType().substitute(substs, null);
boolean allHaveNulls = hasNullReturnValues(refinedType, refinedMethodOrValue);
intersectReturnType(refinedTypes, refinedType);
for (Declaration intervening : interveningRefinements) {
if (intervening instanceof FunctionOrValue && // factors here as well?
!refinedMethodOrValue.equals(intervening)) {
FunctionOrValue refinement = (FunctionOrValue) intervening;
Reference refinedMember = getRefinedMemberReference(refinement, refiningType);
Map<TypeParameter, Type> subs = substitutions(refinement, methodOrValue);
Type type = refinedMember.getType().substitute(subs, null);
allHaveNulls = allHaveNulls && hasNullReturnValues(type, refinement);
intersectReturnType(refinedTypes, type);
checkIntermediateRefinement(that, refinement, refinedMember);
}
}
Type it = canonicalIntersection(refinedTypes, unit);
if (allHaveNulls && !unit.isOptionalType(it)) {
methodOrValue.setUncheckedNullType(true);
Tree.Term lhs = that.getBaseMemberExpression();
// TODO: this is pretty ugly, think of something better!
lhs.setTypeModel(unit.getOptionalType(lhs.getTypeModel()));
}
methodOrValue.setType(it);
return refinedProducedReference;
}
use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class ExpressionVisitor method substitutions.
private static Map<TypeParameter, Type> substitutions(FunctionOrValue refined, FunctionOrValue member) {
if (refined instanceof Function) {
Function refinedMethod = (Function) refined;
Function method = (Function) member;
List<TypeParameter> refinedParams = refinedMethod.getTypeParameters();
List<TypeParameter> params = method.getTypeParameters();
Map<TypeParameter, Type> result = new HashMap<TypeParameter, Type>(params.size());
for (int i = 0; i < refinedParams.size() && i < params.size(); i++) {
result.put(refinedParams.get(i), params.get(i).getType());
}
return result;
} else {
return NO_SUBSTITUTIONS;
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class ExpressionVisitor method checkTypeConstructorParam.
private void checkTypeConstructorParam(TypeParameter param, Type argType, Node argNode) {
if (!argType.isTypeConstructor()) {
argNode.addError("not a type constructor: '" + argType.asString(unit) + "'");
} else {
argType = unwrapAliasedTypeConstructor(argType);
if (argType.isUnion()) {
for (Type ct : argType.getCaseTypes()) {
checkTypeConstructorParam(param, ct, argNode);
}
} else if (argType.isIntersection()) {
for (Type st : argType.getSatisfiedTypes()) {
checkTypeConstructorParam(param, st, argNode);
}
} else if (argType.isNothing()) {
// just let it through?!
} else {
TypeDeclaration argTypeDec = argType.getDeclaration();
List<TypeParameter> argTypeParams = argTypeDec.getTypeParameters();
int allowed = argTypeParams.size();
int required = 0;
for (TypeParameter tp : argTypeParams) {
if (tp.isDefaulted()) {
break;
}
required++;
}
List<TypeParameter> paramTypeParams = param.getTypeParameters();
int size = paramTypeParams.size();
if (allowed < size || required > size) {
argNode.addError("argument type constructor has wrong number of type parameters: argument '" + argTypeDec.getName(unit) + "' has " + allowed + " type parameters " + "but parameter '" + param.getName(unit) + "' has " + size + " type parameters");
}
for (int j = 0; j < size && j < allowed; j++) {
TypeParameter paramParam = paramTypeParams.get(j);
TypeParameter argParam = argTypeParams.get(j);
if (paramParam.isCovariant() && !argParam.isCovariant()) {
argNode.addError("argument type constructor is not covariant: '" + argParam.getName() + "' of '" + argTypeDec.getName(unit) + "' must have the same variance as '" + paramParam.getName() + "' of '" + param.getName(unit) + "'");
} else if (paramParam.isContravariant() && !argParam.isContravariant()) {
argNode.addError("argument type constructor is not contravariant: '" + argParam.getName() + "' of '" + argTypeDec.getName(unit) + "' must have the same variance as '" + paramParam.getName() + "' of '" + param.getName(unit) + "'");
}
if (!intersectionOfSupertypes(paramParam).isSubtypeOf(intersectionOfSupertypes(argParam))) {
argNode.addError("upper bound on type parameter of argument type constructor is not a supertype of upper bound on corresponding type parameter of parameter: '" + argParam.getName() + "' of '" + argTypeDec.getName(unit) + "' does accept all type arguments accepted by '" + paramParam.getName() + "' of '" + param.getName(unit) + "'");
}
if (!unionOfCaseTypes(paramParam).isSubtypeOf(unionOfCaseTypes(argParam))) {
argNode.addError("enumerated bound on type parameter of argument type constructor is not a supertype of enumerated bound on corresponding type parameter of parameter: '" + argParam.getName() + "' of '" + argTypeDec.getName(unit) + "' does accept all type arguments accepted by '" + paramParam.getName() + "' of '" + param.getName(unit) + "'");
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class ExpressionVisitor method refineMethod.
private void refineMethod(Tree.SpecifierStatement that) {
Function refinedMethod = (Function) that.getRefined();
Function method = (Function) that.getDeclaration();
ClassOrInterface ci = (ClassOrInterface) method.getContainer();
Declaration root = method.getRefinedDeclaration();
TypeDeclaration td = (TypeDeclaration) root.getContainer();
List<Declaration> interveningRefinements = getInterveningRefinements(method, root, ci, td);
if (interveningRefinements.isEmpty()) {
that.getBaseMemberExpression().addError("shortcut refinement does not exactly refine any overloaded inherited member");
} else {
Reference refinedProducedReference = accountForIntermediateRefinements(that, refinedMethod, method, ci, interveningRefinements);
List<Tree.ParameterList> parameterLists;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
parameterLists = pe.getParameterLists();
} else {
parameterLists = emptyList();
}
List<ParameterList> refinedParamLists = refinedMethod.getParameterLists();
List<ParameterList> methodParamLists = method.getParameterLists();
Map<TypeParameter, Type> subs = substitutions(refinedMethod, method);
for (int i = 0; i < refinedParamLists.size() && i < methodParamLists.size(); i++) {
ParameterList refinedParameters = refinedParamLists.get(i);
ParameterList parameters = methodParamLists.get(i);
Tree.ParameterList parameterList = parameterLists.size() <= i ? null : parameterLists.get(i);
List<Parameter> rps = refinedParameters.getParameters();
for (int j = 0; j < rps.size(); j++) {
Parameter refinedParameter = rps.get(j);
Type refinedParameterType = refinedProducedReference.getTypedParameter(refinedParameter).getFullType().substitute(subs, null);
Parameter parameter;
if (parameterList == null || parameterList.getParameters().size() <= j) {
parameter = parameters.getParameters().get(j);
parameter.getModel().setType(refinedParameterType);
parameter.setSequenced(refinedParameter.isSequenced());
} else {
Tree.Parameter param = parameterList.getParameters().get(j);
parameter = param.getParameterModel();
Type parameterType = parameter.getModel().getTypedReference().getFullType();
Node typeNode = param;
if (param instanceof Tree.ParameterDeclaration) {
Tree.ParameterDeclaration pd = (Tree.ParameterDeclaration) param;
Tree.Type type = pd.getTypedDeclaration().getType();
if (type != null) {
typeNode = type;
}
}
checkIsExactlyIgnoringNull(refinedParameters.isNamedParametersSupported(), parameterType, refinedParameterType, typeNode, "type of parameter '" + parameter.getName() + "' of '" + method.getName() + "' declared by '" + ci.getName() + "' is different to type of corresponding parameter " + message(refinedMethod, refinedParameter), 9200);
if (refinedParameter.isSequenced() && !parameter.isSequenced()) {
param.addError("parameter must be variadic: parameter " + message(refinedMethod, refinedParameter) + " is variadic");
}
if (!refinedParameter.isSequenced() && parameter.isSequenced()) {
param.addError("parameter may not be variadic: parameter " + message(refinedMethod, refinedParameter) + " is not variadic");
}
}
}
}
}
}
Aggregations