package dotty.tools package dotc package core import Types._, Contexts._, Symbols._ import util.SimpleMap import collection.mutable import printing.{Printer, Showable} import printing.Texts._ import config.Config import config.Printers.constr /** Constraint over undetermined type parameters. Constraints are built * over values of the following types: * * - PolyType A constraint constrains the type parameters of a set of PolyTypes * - PolyParam The parameters of the constrained polytypes * - TypeVar Every constrained parameter might be associated with a TypeVar * that has the PolyParam as origin. */ abstract class Constraint extends Showable { type This <: Constraint /** Does the constraint's domain contain the type parameters of `pt`? */ def contains(pt: GenericType): Boolean /** Does the constraint's domain contain the type parameter `param`? */ def contains(param: PolyParam): Boolean /** Does this constraint contain the type variable `tvar` and is it uninstantiated? */ def contains(tvar: TypeVar): Boolean /** The constraint entry for given type parameter `param`, or NoType if `param` is not part of * the constraint domain. Note: Low level, implementation dependent. */ def entry(param: PolyParam): Type /** The type variable corresponding to parameter `param`, or * NoType, if `param` is not in constrained or is not paired with a type variable. */ def typeVarOfParam(param: PolyParam): Type /** Is it known that `param1 <:< param2`? */ def isLess(param1: PolyParam, param2: PolyParam): Boolean /** The parameters that are known to be smaller wrt <: than `param` */ def lower(param: PolyParam): List[PolyParam] /** The parameters that are known to be greater wrt <: than `param` */ def upper(param: PolyParam): List[PolyParam] /** lower(param) \ lower(butNot) */ def exclusiveLower(param: PolyParam, butNot: PolyParam): List[PolyParam] /** upper(param) \ upper(butNot) */ def exclusiveUpper(param: PolyParam, butNot: PolyParam): List[PolyParam] /** The constraint bounds for given type parameter `param`. * Poly params that are known to be smaller or greater than `param` * are not contained in the return bounds. * @pre `param` is not part of the constraint domain. */ def nonParamBounds(param: PolyParam): TypeBounds /** The lower bound of `param` including all known-to-be-smaller parameters */ def fullLowerBound(param: PolyParam)(implicit ctx: Context): Type /** The upper bound of `param` including all known-to-be-greater parameters */ def fullUpperBound(param: PolyParam)(implicit ctx: Context): Type /** The bounds of `param` including all known-to-be-smaller and -greater parameters */ def fullBounds(param: PolyParam)(implicit ctx: Context): TypeBounds /** A new constraint which is derived from this constraint by adding * entries for all type parameters of `poly`. * @param tvars A list of type variables associated with the params, * or Nil if the constraint will just be checked for * satisfiability but will solved to give instances of * type variables. */ def add(poly: GenericType, tvars: List[TypeVar])(implicit ctx: Context): This /** A new constraint which is derived from this constraint by updating * the entry for parameter `param` to `tp`. * `tp` can be one of the following: * * - A TypeBounds value, indicating new constraint bounds * - Another type, indicating a solution for the parameter * * @pre `this contains param`. */ def updateEntry(param: PolyParam, tp: Type)(implicit ctx: Context): This /** A constraint that includes the relationship `p1 <: p2`. * `<:` relationships between parameters ("edges") are propagated, but * non-parameter bounds are left alone. */ def addLess(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This /** A constraint resulting from adding p2 = p1 to this constraint, and at the same * time transferring all bounds of p2 to p1 */ def unify(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This /** A new constraint which is derived from this constraint by removing * the type parameter `param` from the domain and replacing all top-level occurrences * of the parameter elsewhere in the constraint by type `tp`, or a conservative * approximation of it if that is needed to avoid cycles. * Occurrences nested inside a refinement or prefix are not affected. */ def replace(param: PolyParam, tp: Type)(implicit ctx: Context): This /** Narrow one of the bounds of type parameter `param` * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure * that `param >: bound`. */ def narrowBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): This /** Is entry associated with `pt` removable? This is the case if * all type parameters of the entry are associated with type variables * which have their `inst` fields set. */ def isRemovable(pt: GenericType): Boolean /** A new constraint with all entries coming from `pt` removed. */ def remove(pt: GenericType)(implicit ctx: Context): This /** The polytypes constrained by this constraint */ def domainPolys: List[GenericType] /** The polytype parameters constrained by this constraint */ def domainParams: List[PolyParam] /** Check whether predicate holds for all parameters in constraint */ def forallParams(p: PolyParam => Boolean): Boolean /** Perform operation `op` on all typevars, or only on uninstantiated * typevars, depending on whether `uninstOnly` is set or not. */ def foreachTypeVar(op: TypeVar => Unit): Unit /** The uninstantiated typevars of this constraint */ def uninstVars: collection.Seq[TypeVar] /** The weakest constraint that subsumes both this constraint and `other` */ def & (other: Constraint)(implicit ctx: Context): Constraint /** Check that no constrained parameter contains itself as a bound */ def checkNonCyclic()(implicit ctx: Context): Unit /** Check that constraint only refers to PolyParams bound by itself */ def checkClosed()(implicit ctx: Context): Unit }