private List<ProducedType> getSatisfiedTypes() {
   List<ProducedType> satisfiedTypes = new ArrayList<ProducedType>();
   for (ProducedType st : getDeclaration().getSatisfiedTypes()) {
     satisfiedTypes.add(st.substitute(getTypeArguments()));
   }
   return satisfiedTypes;
 }
 public String getProducedTypeQualifiedName() {
   if (getDeclaration() == null) {
     // unknown type
     return null;
   }
   String producedTypeName = "";
   if (getDeclaration().isMember()) {
     producedTypeName += getQualifyingType().getProducedTypeQualifiedName();
     producedTypeName += ".";
   }
   producedTypeName += getDeclaration().getQualifiedNameString();
   if (!getTypeArgumentList().isEmpty()) {
     producedTypeName += "<";
     for (ProducedType t : getTypeArgumentList()) {
       if (t == null) {
         producedTypeName += "?,";
       } else {
         producedTypeName += t.getProducedTypeQualifiedName() + ",";
       }
     }
     producedTypeName += ">";
     producedTypeName = producedTypeName.replace(",>", ">");
   }
   return producedTypeName;
 }
 private void addLocalType(
     Declaration dec,
     ProducedType type,
     List<TypeDeclaration> localTypes,
     List<ProducedType> visited) {
   if (visited.contains(type)) {
     return;
   } else {
     visited.add(type);
   }
   TypeDeclaration td = type.getDeclaration();
   if (td.getContainer() == dec) {
     boolean found = false;
     for (TypeDeclaration typeDeclaration : localTypes) {
       if (typeDeclaration == td) {
         found = true;
         break;
       }
     }
     if (!found) {
       localTypes.add(td);
     }
   }
   for (ProducedType pt : td.getSatisfiedTypes()) {
     addLocalType(dec, pt, localTypes, visited);
   }
   for (ProducedType pt : type.getTypeArgumentList()) {
     addLocalType(dec, pt, localTypes, visited);
   }
 }
 private CollectionLiteralAnnotationTerm startCollection(Tree.Term t) {
   Unit unit = t.getUnit();
   // Continue the visit to collect the elements
   ProducedType iteratedType = unit.getIteratedType(parameter().getType());
   TypeDeclaration declaration = iteratedType.getDeclaration();
   LiteralAnnotationTerm factory;
   if (unit.getStringDeclaration().equals(declaration)) {
     factory = StringLiteralAnnotationTerm.FACTORY;
   } else if (unit.getIntegerDeclaration().equals(declaration)) {
     factory = IntegerLiteralAnnotationTerm.FACTORY;
   } else if (unit.getCharacterDeclaration().equals(declaration)) {
     factory = CharacterLiteralAnnotationTerm.FACTORY;
   } else if (unit.getBooleanDeclaration().equals(declaration)) {
     factory = BooleanLiteralAnnotationTerm.FACTORY;
   } else if (unit.getFloatDeclaration().equals(declaration)) {
     factory = FloatLiteralAnnotationTerm.FACTORY;
   } else if (Decl.isEnumeratedTypeWithAnonCases(iteratedType)) {
     factory = ObjectLiteralAnnotationTerm.FACTORY;
   } else if (Decl.isAnnotationClass(declaration)) {
     t.addError(
         "compiler bug: iterables of annotation classes or annotation constructors not supported as literal "
             + (checkingDefaults ? "defaulted parameters" : "arguments"));
     return null;
   } else if (iteratedType.isSubtypeOf(
       ((TypeDeclaration) unit.getLanguageModuleDeclarationDeclaration("Declaration"))
           .getType())) {
     factory = DeclarationLiteralAnnotationTerm.FACTORY;
   } else {
     throw new RuntimeException();
   }
   CollectionLiteralAnnotationTerm result = this.elements;
   this.elements = new CollectionLiteralAnnotationTerm(factory);
   return result;
 }
Exemple #5
0
 public ProducedType getElementType(ProducedType pt) {
   ProducedType st = getNonemptySequenceType(pt);
   if (st != null && st.getTypeArguments().size() == 1) {
     return st.getTypeArgumentList().get(0);
   } else {
     return null;
   }
 }
Exemple #6
0
 public ProducedType getIteratedType(ProducedType type) {
   ProducedType st = type.getSupertype(getIterableDeclaration());
   if (st != null && st.getTypeArguments().size() == 1) {
     return st.getTypeArgumentList().get(0);
   } else {
     return null;
   }
 }
 public List<TypeDeclaration> getSatisfiedTypeDeclarations() {
   List<ProducedType> sts = getSatisfiedTypes();
   List<TypeDeclaration> list = new ArrayList<TypeDeclaration>(sts.size());
   for (ProducedType pt : sts) {
     list.add(pt == null ? null : pt.getDeclaration());
   }
   return list;
 }
 public ClassOrInterface getExtendedTypeDeclaration() {
   ProducedType et = getExtendedType();
   if (et == null || !(et.getDeclaration() instanceof ClassOrInterface)) {
     return null;
   } else {
     return (ClassOrInterface) et.getDeclaration();
   }
 }
Exemple #9
0
 public ProducedType getValueType(ProducedType type) {
   ProducedType st = type.getSupertype(getEntryDeclaration());
   if (st != null && st.getTypeArguments().size() == 2) {
     return st.getTypeArgumentList().get(1);
   } else {
     return null;
   }
 }
 /** Is the type welldefined? Are any of its arguments garbage unknown types? */
 public boolean isWellDefined() {
   for (ProducedType at : getTypeArgumentList()) {
     if (at == null || !at.isWellDefined()) {
       return false;
     }
   }
   return true;
 }
 /**
  * A member type of the type with actual type arguments to the receiving type and invocation.
  *
  * @param member the declaration of a member type of this type
  * @param typeArguments the type arguments of the invocation
  */
 public ProducedType getTypeMember(TypeDeclaration member, List<ProducedType> typeArguments) {
   ProducedType declaringType = getSupertype((TypeDeclaration) member.getContainer());
   ProducedType pt = new ProducedType();
   pt.setDeclaration(member);
   pt.setQualifyingType(declaringType);
   Map<TypeParameter, ProducedType> map = arguments(member, declaringType, typeArguments);
   // map.putAll(sub(map));
   pt.setTypeArguments(map);
   return pt;
 }
 /**
  * Determine if this is a decidable supertype, i.e. if it obeys the restriction that types with
  * contravariant type parameters may only appear in covariant positions.
  *
  * @return a list of type parameters which appear in illegal positions
  */
 public List<TypeDeclaration> checkDecidability() {
   List<TypeDeclaration> errors = new ArrayList<TypeDeclaration>();
   for (TypeParameter tp : getDeclaration().getTypeParameters()) {
     ProducedType pt = getTypeArguments().get(tp);
     if (pt != null) {
       pt.checkDecidability(tp.isCovariant(), tp.isContravariant(), errors);
     }
   }
   return errors;
 }
 ProducedType substitute(ProducedType pt, Map<TypeParameter, ProducedType> substitutions) {
   Declaration dec;
   if (pt.getDeclaration() instanceof UnionType) {
     UnionType ut = new UnionType(pt.getDeclaration().getUnit());
     List<ProducedType> types = new ArrayList<ProducedType>();
     for (ProducedType ct : pt.getDeclaration().getCaseTypes()) {
       addTypeToUnion(ct, substitutions, types);
     }
     ut.setCaseTypes(types);
     dec = ut;
   } else if (pt.getDeclaration() instanceof IntersectionType) {
     IntersectionType it = new IntersectionType(pt.getDeclaration().getUnit());
     List<ProducedType> types = new ArrayList<ProducedType>();
     for (ProducedType ct : pt.getDeclaration().getSatisfiedTypes()) {
       addTypeToIntersection(ct, substitutions, types);
     }
     it.setSatisfiedTypes(types);
     dec = it.canonicalize();
   } else {
     if (pt.getDeclaration() instanceof TypeParameter) {
       ProducedType sub = substitutions.get(pt.getDeclaration());
       if (sub != null) {
         return sub;
       }
     }
     dec = pt.getDeclaration();
   }
   return substitutedType(dec, pt, substitutions);
 }
 private List<ProducedType> getCaseTypes() {
   if (getDeclaration().getCaseTypes() == null) {
     return null;
   } else {
     List<ProducedType> caseTypes = new ArrayList<ProducedType>();
     for (ProducedType ct : getDeclaration().getCaseTypes()) {
       caseTypes.add(ct.substitute(getTypeArguments()));
     }
     return caseTypes;
   }
 }
 /**
  * Get a produced type for this declaration by binding explicit or inferred type arguments and
  * type arguments of the type of which this declaration is a member, in the case that this is a
  * nested type.
  *
  * @param qualifyingType the qualifying produced type or null if this is not a nested type dec
  * @param typeArguments arguments to the type parameters of this declaration
  */
 public ProducedType getProducedType(
     ProducedType qualifyingType, List<ProducedType> typeArguments) {
   if (qualifyingType != null && qualifyingType.isNothing()) {
     return qualifyingType;
   }
   ProducedType pt = new ProducedType();
   pt.setDeclaration(this);
   pt.setQualifyingType(qualifyingType);
   pt.setTypeArguments(getTypeArgumentMap(this, qualifyingType, typeArguments));
   return pt;
 }
 @Override
 public ProducedType getReference() {
   ProducedType pt = new ProducedType();
   if (isMember()) {
     pt.setQualifyingType(((ClassOrInterface) getContainer()).getType());
   }
   pt.setDeclaration(this);
   pt.setTypeArguments(
       getTypeArgumentMap(this, pt.getQualifyingType(), Collections.<ProducedType>emptyList()));
   return pt;
 }
 private ProducedType substitutedType(
     Declaration dec, ProducedType pt, Map<TypeParameter, ProducedType> substitutions) {
   ProducedType type = new ProducedType();
   type.setDeclaration(dec);
   ProducedType qt = pt.getQualifyingType();
   if (qt != null) {
     type.setQualifyingType(substitute(qt, substitutions));
   }
   type.setTypeArguments(substitutedTypeArguments(pt, substitutions));
   return type;
 }
  @Test
  public void testPackageQualified() {
    ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("unknown.b", null);
    Assert.assertNotNull(type);
    TypeDeclaration declaration = type.getDeclaration();
    Assert.assertNotNull(declaration);
    Assert.assertTrue(declaration instanceof Class);
    Assert.assertEquals("unknown.b", declaration.getName());

    Assert.assertNull(type.getQualifyingType());
  }
 public List<TypeDeclaration> getCaseTypeDeclarations() {
   List<ProducedType> caseTypes = getCaseTypes();
   if (caseTypes == null) {
     return null;
   } else {
     List<TypeDeclaration> list = new ArrayList<TypeDeclaration>(caseTypes.size());
     for (ProducedType pt : caseTypes) {
       list.add(pt == null ? null : pt.getDeclaration());
     }
     return list;
   }
 }
  protected void init() {
    com.redhat.ceylon.compiler.typechecker.model.ClassOrInterface decl =
        (com.redhat.ceylon.compiler.typechecker.model.ClassOrInterface)
            producedType.getDeclaration();
    this.declaration = (FreeClassOrInterface) Metamodel.getOrCreateMetamodel(decl);
    java.util.Map<
            ceylon.language.meta.declaration.TypeParameter,
            ceylon.language.meta.declaration.OpenType>
        typeArguments =
            new LinkedHashMap<
                ceylon.language.meta.declaration.TypeParameter,
                ceylon.language.meta.declaration.OpenType>();
    Iterator<? extends ceylon.language.meta.declaration.TypeParameter> typeParameters =
        declaration.getTypeParameterDeclarations().iterator();
    Object it;
    java.util.Map<
            com.redhat.ceylon.compiler.typechecker.model.TypeParameter,
            com.redhat.ceylon.compiler.typechecker.model.ProducedType>
        ptArguments = producedType.getTypeArguments();
    while ((it = typeParameters.next()) != finished_.$get()) {
      com.redhat.ceylon.compiler.java.runtime.metamodel.FreeTypeParameter tp =
          (com.redhat.ceylon.compiler.java.runtime.metamodel.FreeTypeParameter) it;
      com.redhat.ceylon.compiler.typechecker.model.TypeParameter tpDecl =
          (com.redhat.ceylon.compiler.typechecker.model.TypeParameter) tp.declaration;
      com.redhat.ceylon.compiler.typechecker.model.ProducedType ptArg = ptArguments.get(tpDecl);
      OpenType ptArgWrapped = Metamodel.getMetamodel(ptArg);
      typeArguments.put(tp, ptArgWrapped);
    }
    this.typeArguments =
        new InternalMap<
            ceylon.language.meta.declaration.TypeParameter,
            ceylon.language.meta.declaration.OpenType>(
            ceylon.language.meta.declaration.TypeParameter.$TypeDescriptor,
            ceylon.language.meta.declaration.OpenType.$TypeDescriptor,
            typeArguments);

    com.redhat.ceylon.compiler.typechecker.model.ProducedType superType = decl.getExtendedType();
    if (superType != null) {
      com.redhat.ceylon.compiler.typechecker.model.ProducedType superTypeResolved =
          superType.substitute(producedType.getTypeArguments());
      this.superclass =
          (ceylon.language.meta.declaration.OpenClassType)
              Metamodel.getMetamodel(superTypeResolved);
    }

    List<com.redhat.ceylon.compiler.typechecker.model.ProducedType> satisfiedTypes =
        decl.getSatisfiedTypes();
    ceylon.language.meta.declaration.OpenInterfaceType[] interfaces =
        new ceylon.language.meta.declaration.OpenInterfaceType[satisfiedTypes.size()];
    int i = 0;
    for (com.redhat.ceylon.compiler.typechecker.model.ProducedType pt : satisfiedTypes) {
      com.redhat.ceylon.compiler.typechecker.model.ProducedType resolvedPt =
          pt.substitute(producedType.getTypeArguments());
      interfaces[i++] =
          (ceylon.language.meta.declaration.OpenInterfaceType) Metamodel.getMetamodel(resolvedPt);
    }
    this.interfaces =
        Util.sequentialInstance(
            ceylon.language.meta.declaration.OpenInterfaceType.$TypeDescriptor, interfaces);
  }
 @Test
 public void testIntersection() {
   ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("a&b&c", null);
   Assert.assertNotNull(type);
   TypeDeclaration declaration = type.getDeclaration();
   Assert.assertNotNull(declaration);
   Assert.assertTrue(declaration instanceof IntersectionType);
   IntersectionType intersection = (IntersectionType) declaration;
   List<ProducedType> types = intersection.getSatisfiedTypes();
   Assert.assertEquals(3, types.size());
   Assert.assertEquals("a", types.get(0).getDeclaration().getName());
   Assert.assertTrue(types.get(0).getDeclaration() instanceof Class);
   Assert.assertEquals("b", types.get(1).getDeclaration().getName());
   Assert.assertTrue(types.get(1).getDeclaration() instanceof Class);
   Assert.assertEquals("c", types.get(2).getDeclaration().getName());
   Assert.assertTrue(types.get(2).getDeclaration() instanceof Class);
 }
 /**
  * Eliminate the given type from the union type. (Performs a set complement operation.) Note that
  * this operation is not robust and only works if this is a union of the given type with some
  * other types that don't involve the given type.
  */
 public ProducedType minus(ClassOrInterface ci) {
   if (getDeclaration().equals(ci)) {
     return new BottomType(getDeclaration().getUnit()).getType();
   } else if (getDeclaration() instanceof UnionType) {
     List<ProducedType> types = new ArrayList<ProducedType>();
     for (ProducedType ct : getCaseTypes()) {
       if (ct.getSupertype(ci) == null) {
         addToUnion(types, ct.minus(ci));
       }
     }
     UnionType ut = new UnionType(getDeclaration().getUnit());
     ut.setCaseTypes(types);
     return ut.getType();
   } else {
     return this;
   }
 }
  public JCNewClass build() {
    // Generate a subclass of Callable
    ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
    int numParams = paramLists.getParameters().size();
    int minimumParams = 0;
    for (Parameter p : paramLists.getParameters()) {
      if (p.isDefaulted() || p.isSequenced()) break;
      minimumParams++;
    }
    boolean isVariadic = minimumParams != numParams;
    if (parameterListTree != null) {
      // generate a method for each defaulted param
      for (Tree.Parameter p : parameterListTree.getParameters()) {
        if (p.getDefaultArgument() != null || p.getDeclarationModel().isSequenced()) {
          MethodDefinitionBuilder methodBuilder =
              gen.classGen().makeParamDefaultValueMethod(false, null, parameterListTree, p);
          classBody.append(methodBuilder.build());
        }
      }
    }

    // collect each parameter type from the callable type model rather than the declarations to get
    // them all bound
    java.util.List<ProducedType> parameterTypes = new ArrayList<ProducedType>(numParams);
    if (forwardCallTo != null) {
      for (int i = 0; i < numParams; i++)
        parameterTypes.add(gen.getParameterTypeOfCallable(typeModel, i));
    } else {
      // get them from our declaration
      for (Parameter p : paramLists.getParameters()) parameterTypes.add(p.getType());
    }

    // now generate a method for each supported minimum number of parameters below 4
    // which delegates to the $call$typed method if required
    for (int i = minimumParams, max = Math.min(numParams, 4); i < max; i++) {
      classBody.append(makeDefaultedCall(i, isVariadic, parameterTypes));
    }
    // generate the $call method for the max number of parameters,
    // which delegates to the $call$typed method if required
    classBody.append(makeDefaultedCall(numParams, isVariadic, parameterTypes));
    // generate the $call$typed method if required
    if (isVariadic && forwardCallTo == null)
      classBody.append(makeCallTypedMethod(body, parameterTypes));

    JCClassDecl classDef =
        gen.make().AnonymousClassDef(gen.make().Modifiers(0), classBody.toList());

    JCNewClass instance =
        gen.make()
            .NewClass(
                null,
                null,
                gen.makeJavaType(typeModel, JT_EXTENDS | JT_CLASS_NEW),
                List.<JCExpression>of(gen.make().Literal(typeModel.getProducedTypeName(true))),
                classDef);
    return instance;
  }
  private boolean isConstantValue(Declaration d) {
    if (d instanceof Value) {
      Value value = (Value) d;
      if (value.isShared() && !value.isVariable()) {
        Unit unit = value.getUnit();
        TypeDeclaration type = value.getTypeDeclaration();

        if (type == unit.getSequentialDeclaration()) {
          ProducedType elementType = unit.getIteratedType(value.getType());
          type = elementType.getDeclaration();
        }

        if (unit.getStringDeclaration().equals(type)
            || unit.getIntegerDeclaration().equals(type)
            || unit.getFloatDeclaration().equals(type)
            || unit.getCharacterDeclaration().equals(type)) {
          return true;
        }
      }
    }
    return false;
  }
 private void checkVariance(
     boolean covariant,
     boolean contravariant,
     Declaration declaration,
     List<TypeParameter> errors) {
   // TODO: fix this to allow reporting multiple errors!
   if (getDeclaration() instanceof TypeParameter) {
     TypeParameter tp = (TypeParameter) getDeclaration();
     boolean ok =
         tp.getDeclaration().equals(declaration)
             || ((covariant || !tp.isCovariant()) && (contravariant || !tp.isContravariant()));
     if (!ok) {
       // a covariant type parameter appears in a contravariant location, or
       // a contravariant type parameter appears in a covariant location.
       errors.add(tp);
     }
   } else if (getDeclaration() instanceof UnionType) {
     for (ProducedType ct : getCaseTypes()) {
       ct.checkVariance(covariant, contravariant, declaration, errors);
     }
   } else if (getDeclaration() instanceof IntersectionType) {
     for (ProducedType ct : getSatisfiedTypes()) {
       ct.checkVariance(covariant, contravariant, declaration, errors);
     }
   } else {
     for (TypeParameter tp : getDeclaration().getTypeParameters()) {
       ProducedType pt = getTypeArguments().get(tp);
       if (pt != null) {
         if (tp.isCovariant()) {
           pt.checkVariance(covariant, contravariant, declaration, errors);
         } else if (tp.isContravariant()) {
           if (covariant | contravariant) {
             pt.checkVariance(!covariant, !contravariant, declaration, errors);
           } else {
             // else if we are in a nonvariant position, it stays nonvariant
             pt.checkVariance(covariant, contravariant, declaration, errors);
           }
         } else {
           pt.checkVariance(false, false, declaration, errors);
         }
       }
     }
   }
 }
 public String getProducedTypeName(boolean abbreviate) {
   if (getDeclaration() == null) {
     // unknown type
     return null;
   }
   if (abbreviate && getDeclaration() instanceof UnionType) {
     UnionType ut = (UnionType) getDeclaration();
     if (ut.getCaseTypes().size() == 2) {
       Unit unit = getDeclaration().getUnit();
       if (Util.isElementOfUnion(ut, unit.getNothingDeclaration())) {
         return unit.getDefiniteType(this).getProducedTypeName() + "?";
       }
       if (Util.isElementOfUnion(ut, unit.getEmptyDeclaration())
           && Util.isElementOfUnion(ut, unit.getSequenceDeclaration())) {
         return unit.getElementType(this).getProducedTypeName() + "[]";
       }
     }
   }
   String producedTypeName = "";
   if (getDeclaration().isMember()) {
     producedTypeName += getQualifyingType().getProducedTypeName(abbreviate);
     producedTypeName += ".";
   }
   producedTypeName += getDeclaration().getName();
   if (!getTypeArgumentList().isEmpty()) {
     producedTypeName += "<";
     for (ProducedType t : getTypeArgumentList()) {
       if (t == null) {
         producedTypeName += "unknown,";
       } else {
         producedTypeName += t.getProducedTypeName(abbreviate) + ",";
       }
     }
     producedTypeName += ">";
     producedTypeName = producedTypeName.replace(",>", ">");
   }
   return producedTypeName;
 }
 private static String type(Tree.Type type) {
   if (type == null) {
     return "<Unknown>";
   } else {
     ProducedType tm = type.getTypeModel();
     if (tm == null) {
       return "<Unknown>";
     } else {
       boolean sequenced = type instanceof Tree.SequencedType;
       if (sequenced) {
         tm = type.getUnit().getIteratedType(tm);
         if (tm == null) {
           return "<Unknown>";
         }
       }
       String tn = tm.getProducedTypeName();
       if (sequenced) {
         tn += "...";
       }
       return tn;
     }
   }
 }
 private Map<TypeParameter, ProducedType> substitutedTypeArguments(
     ProducedType pt, Map<TypeParameter, ProducedType> substitutions) {
   Map<TypeParameter, ProducedType> map = new HashMap<TypeParameter, ProducedType>();
   for (Map.Entry<TypeParameter, ProducedType> e : pt.getTypeArguments().entrySet()) {
     if (e.getValue() != null) {
       map.put(e.getKey(), substitute(e.getValue(), substitutions));
     }
   }
   /*ProducedType dt = pt.getDeclaringType();
   if (dt!=null) {
                map.putAll(substituted(dt, substitutions));
            }*/
   return map;
 }
 @Test
 public void testParams() {
   ProducedType type = new TypeParser(MockLoader.instance, mockUnit).decodeType("t2<b,c>", null);
   Assert.assertNotNull(type);
   TypeDeclaration declaration = type.getDeclaration();
   Assert.assertNotNull(declaration);
   Assert.assertTrue(declaration instanceof Class);
   Assert.assertEquals("t2", declaration.getName());
   Assert.assertEquals(2, type.getTypeArgumentList().size());
   Assert.assertEquals("b", type.getTypeArgumentList().get(0).getDeclaration().getName());
   Assert.assertTrue(type.getTypeArgumentList().get(0).getDeclaration() instanceof Class);
   Assert.assertEquals("c", type.getTypeArgumentList().get(1).getDeclaration().getName());
   Assert.assertTrue(type.getTypeArgumentList().get(1).getDeclaration() instanceof Class);
 }
 private void checkDecidability(
     boolean covariant, boolean contravariant, List<TypeDeclaration> errors) {
   if (getDeclaration() instanceof TypeParameter) {
     // nothing to do
   } else if (getDeclaration() instanceof UnionType) {
     for (ProducedType ct : getCaseTypes()) {
       ct.checkDecidability(covariant, contravariant, errors);
     }
   } else if (getDeclaration() instanceof IntersectionType) {
     for (ProducedType ct : getSatisfiedTypes()) {
       ct.checkDecidability(covariant, contravariant, errors);
     }
   } else {
     for (TypeParameter tp : getDeclaration().getTypeParameters()) {
       if (!covariant && tp.isContravariant()) {
         // a type with contravariant parameters appears at
         // a contravariant location in satisfies / extends
         errors.add(getDeclaration());
       }
       ProducedType pt = getTypeArguments().get(tp);
       if (pt != null) {
         if (tp.isCovariant()) {
           pt.checkDecidability(covariant, contravariant, errors);
         } else if (tp.isContravariant()) {
           if (covariant | contravariant) {
             pt.checkDecidability(!covariant, !contravariant, errors);
           } else {
             // else if we are in a nonvariant position, it stays nonvariant
             pt.checkDecidability(covariant, contravariant, errors);
           }
         } else {
           pt.checkDecidability(false, false, errors);
         }
       }
     }
   }
 }