use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.
the class AbstractTransformer method isWideningTypeArguments.
private boolean isWideningTypeArguments(Type declType, Type refinedDeclType, boolean allowSubtypes) {
if (declType == null || refinedDeclType == null)
return false;
// make sure we work on simplified types, to avoid stuff like optional or size-1 unions
declType = simplifyType(declType);
refinedDeclType = simplifyType(refinedDeclType);
// special case for type parameters
if (declType.getDeclaration() instanceof TypeParameter && refinedDeclType.getDeclaration() instanceof TypeParameter) {
// consider them equivalent if they have the same bounds
TypeParameter tp = (TypeParameter) declType.getDeclaration();
TypeParameter refinedTP = (TypeParameter) refinedDeclType.getDeclaration();
if (haveSameBounds(tp, refinedTP))
return false;
// if they don't have the same bounds and we don't allow subtypes then we're widening
if (!allowSubtypes)
return false;
// if we allow subtypes, we're widening if tp is not a subtype of refinedTP
return !tp.getType().isSubtypeOf(refinedTP.getType());
}
if (allowSubtypes) {
if ((willEraseToObject(refinedDeclType))) {
// - similarly if we both erase to object we're not widening
return false;
}
// if we have exactly the same type don't bother finding a common ancestor
if (!declType.isExactly(refinedDeclType)) {
// check if we can form an informed decision
if (refinedDeclType.getDeclaration() == null)
return true;
// find the instantiation of the refined decl type in the decl type
// special case for optional types: let's find the definite type since
// in java they are equivalent
Type definiteType = typeFact().getDefiniteType(refinedDeclType);
if (definiteType != null)
refinedDeclType = definiteType;
declType = declType.getSupertype(refinedDeclType.getDeclaration());
// could not find common type, we must be widening somehow
if (declType == null)
return true;
}
}
Map<TypeParameter, Type> typeArguments = declType.getTypeArguments();
Map<TypeParameter, Type> refinedTypeArguments = refinedDeclType.getTypeArguments();
java.util.List<TypeParameter> typeParameters = declType.getDeclaration().getTypeParameters();
for (TypeParameter tp : typeParameters) {
Type typeArgument = typeArguments.get(tp);
if (typeArgument == null)
// something fishy here
return true;
Type refinedTypeArgument = refinedTypeArguments.get(tp);
if (refinedTypeArgument == null)
// something fishy here
return true;
// check if the type arg is widening due to erasure
if (isWidening(typeArgument, refinedTypeArgument))
return true;
// check if we are refining a covariant param which we must "fix" because it is dependend on, like Tuple's first TP
if (declType.isCovariant(tp) && hasDependentTypeParameters(typeParameters, tp) && !typeArgument.isExactly(refinedTypeArgument) && // it is not widening if we refine Object with a TP, though
!(willEraseToObject(refinedTypeArgument) && (isTypeParameter(typeArgument) || // it is also not widening if we erase both to Object
willEraseToObject(typeArgument))))
return true;
// check if the type arg is a subtype, or if its type args are widening
if (isWideningTypeArguments(typeArgument, refinedTypeArgument, tp.isCovariant()))
return true;
}
// so far so good
return false;
}
use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.
the class AbstractTransformer method isWideningTypeDecl.
public boolean isWideningTypeDecl(TypedReference typedReference, Type currentType) {
TypedReference refinedTypedReference = getRefinedDeclaration(typedReference, currentType);
if (refinedTypedReference == null)
return false;
/*
* We are widening if the type:
* - is not object
* - is erased to object
* - refines a declaration that is not erased to object
*/
Type declType = typedReference.getType();
Type refinedDeclType = refinedTypedReference.getType();
if (declType == null || refinedDeclType == null)
return false;
if (isWidening(declType, refinedDeclType))
return true;
// make sure we get the instantiated refined decl
if (refinedDeclType.getDeclaration() instanceof TypeParameter && !(declType.getDeclaration() instanceof TypeParameter))
refinedDeclType = nonWideningType(typedReference, refinedTypedReference);
if (isWideningTypeArguments(declType, refinedDeclType, true))
return true;
if (CodegenUtil.hasTypeErased(refinedTypedReference.getDeclaration()) && !willEraseToObject(declType))
return true;
return false;
}
use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.
the class AbstractTransformer method hasDependentCovariantTypeParameters.
boolean hasDependentCovariantTypeParameters(Type type) {
if (type.isUnion()) {
for (Type m : type.getCaseTypes()) if (hasDependentCovariantTypeParameters(m))
return true;
return false;
}
if (type.isIntersection()) {
for (Type m : type.getSatisfiedTypes()) if (hasDependentCovariantTypeParameters(m))
return true;
return false;
}
// check its type arguments
// special case for Callable which has only a single type param in Java
boolean isCallable = isCeylonCallable(type);
// check if any type parameter is dependent on and covariant
TypeDeclaration declaration = type.getDeclaration();
java.util.List<TypeParameter> typeParams = declaration.getTypeParameters();
Map<TypeParameter, Type> typeArguments = type.getTypeArguments();
for (TypeParameter typeParam : typeParams) {
Type typeArg = typeArguments.get(typeParam);
if (type.isCovariant(typeParam) && hasDependentTypeParameters(typeParams, typeParam)) {
// see if the type argument in question contains type parameters and is erased to Object
if (containsTypeParameter(typeArg) && willEraseToObject(typeArg))
return true;
}
// now check if we the type argument has the same problem
if (hasDependentCovariantTypeParameters(typeArg))
return true;
// stop after the first type arg for Callable
if (isCallable)
break;
}
return false;
}
use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.
the class ClassTransformer method buildJpaConstructor.
protected void buildJpaConstructor(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder ctor = classBuilder.addConstructor();
ctor.modelAnnotations(makeAtJpa());
ctor.modelAnnotations(makeAtIgnore());
ctor.modifiers(PROTECTED);
for (TypeParameter tp : model.getTypeParameters()) {
ctor.reifiedTypeParameter(tp);
}
final ListBuffer<JCStatement> stmts = ListBuffer.lb();
// invoke super (or this if
ListBuffer<JCExpression> superArgs = ListBuffer.<JCExpression>lb();
if (model.isSerializable()) {
superArgs.add(make().TypeCast(make().QualIdent(syms().ceylonSerializationType.tsym), makeNull()));
for (JCExpression ta : makeReifiedTypeArguments(model.getType())) {
superArgs.add(ta);
}
} else {
for (JCExpression ta : makeReifiedTypeArguments(model.getExtendedType())) {
superArgs.add(ta);
}
}
stmts.add(make().Exec(make().Apply(null, model.isSerializable() ? naming.makeThis() : naming.makeSuper(), superArgs.toList())));
if (!model.isSerializable()) {
buildFieldInits(model, classBuilder, stmts);
}
ctor.body(stmts.toList());
}
use of com.redhat.ceylon.model.typechecker.model.TypeParameter in project ceylon-compiler by ceylon.
the class ClassTransformer method refineMethod.
private Function refineMethod(Scope container, TypedReference pr, ClassOrInterface classModel, Function formalMethod, Unit unit) {
Function refined = new Function();
refined.setActual(true);
refined.setShared(formalMethod.isShared());
refined.setContainer(container);
// in case there are subclasses
refined.setDefault(true);
refined.setDeferred(false);
refined.setDeprecated(formalMethod.isDeprecated());
refined.setName(formalMethod.getName());
refined.setRefinedDeclaration(formalMethod.getRefinedDeclaration());
refined.setScope(container);
refined.setType(pr.getType());
refined.setUnit(unit);
refined.setUnboxed(formalMethod.getUnboxed());
refined.setUntrustedType(formalMethod.getUntrustedType());
refined.setTypeErased(formalMethod.getTypeErased());
ArrayList<TypeParameter> refinedTp = new ArrayList<TypeParameter>();
;
for (TypeParameter formalTp : formalMethod.getTypeParameters()) {
refinedTp.add(formalTp);
}
refined.setTypeParameters(refinedTp);
for (ParameterList formalPl : formalMethod.getParameterLists()) {
ParameterList refinedPl = new ParameterList();
for (Parameter formalP : formalPl.getParameters()) {
Parameter refinedP = new Parameter();
refinedP.setAtLeastOne(formalP.isAtLeastOne());
refinedP.setDeclaration(refined);
refinedP.setDefaulted(formalP.isDefaulted());
refinedP.setDeclaredAnything(formalP.isDeclaredAnything());
refinedP.setHidden(formalP.isHidden());
refinedP.setSequenced(formalP.isSequenced());
refinedP.setName(formalP.getName());
final TypedReference typedParameter = pr.getTypedParameter(formalP);
FunctionOrValue paramModel;
if (formalP.getModel() instanceof Value) {
Value paramValueModel = refineValue((Value) formalP.getModel(), typedParameter, refined, classModel.getUnit());
paramValueModel.setInitializerParameter(refinedP);
paramModel = paramValueModel;
} else {
Function paramFunctionModel = refineMethod(refined, typedParameter, classModel, (Function) formalP.getModel(), unit);
paramFunctionModel.setInitializerParameter(refinedP);
paramModel = paramFunctionModel;
}
refinedP.setModel(paramModel);
refinedPl.getParameters().add(refinedP);
}
refined.addParameterList(refinedPl);
}
return refined;
}
Aggregations