Skip to content

Instantly share code, notes, and snippets.

@HamsterofDeath
Created April 13, 2012 05:58
Show Gist options
  • Save HamsterofDeath/2374205 to your computer and use it in GitHub Desktop.
Save HamsterofDeath/2374205 to your computer and use it in GitHub Desktop.
lub fix
private def lub(t1: ScType, t2: ScType, depth : Int, checkWeak: Boolean)(implicit stopAddingUpperBound: Boolean): ScType = {
if (t1.conforms(t2, checkWeak)) t2
else if (t2.conforms(t1, checkWeak)) t1
else {
def lubWithExpandedAliases(t1: ScType, t2: ScType): ScType = {
(t1, t2) match {
case (fun@ScFunctionType(rt1, p1), ScFunctionType(rt2, p2)) if p1.length == p2.length =>
new ScFunctionType(lub(rt1, rt2, 0, checkWeak),
collection.immutable.Seq(p1.toSeq.zip(p2.toSeq).map({
case (t1, t2) => glb(t1, t2, checkWeak)
}).toSeq: _*))(fun.getProject, fun.getScope)
case (t1@ScTupleType(c1), ScTupleType(c2)) if c1.length == c2.length =>
new ScTupleType(collection.immutable.Seq(c1.toSeq.zip(c2.toSeq).map({
case (t1, t2) => lub(t1, t2, 0, checkWeak)
}).toSeq: _*))(t1.getProject, t1.getScope)
case (ScSkolemizedType(_, Nil, _, upper), _) => lub(upper, t2, 0, checkWeak)
case (_, ScSkolemizedType(_, Nil, _, upper)) => lub(t1, upper, 0, checkWeak)
case (ScTypeParameterType(_, Nil, _, upper, _), _) => lub(upper.v, t2, 0, checkWeak)
case (_, ScTypeParameterType(_, Nil, _, upper, _)) => lub(t1, upper.v, 0, checkWeak)
case (ex: ScExistentialType, _) => lub(ex.skolem, t2, 0, checkWeak)
case (_, ex: ScExistentialType) => lub(t1, ex.skolem, 0, checkWeak)
case (_: ValType, _: ValType) => types.AnyVal
case (JavaArrayType(arg1), JavaArrayType(arg2)) => {
JavaArrayType(calcForTypeParamWithoutVariance(arg1, arg2, depth, checkWeak))
}
case (JavaArrayType(arg), ScParameterizedType(des, args)) if args.length == 1 && (ScType.extractClass(des) match {
case Some(q) => q.qualifiedName == "scala.Array"
case _ => false
}) => {
ScParameterizedType(des, Seq(calcForTypeParamWithoutVariance(arg, args(0), depth, checkWeak)))
}
case (ScParameterizedType(des, args), JavaArrayType(arg)) if args.length == 1 && (ScType.extractClass(des) match {
case Some(q) => q.qualifiedName == "scala.Array"
case _ => false
}) => {
ScParameterizedType(des, Seq(calcForTypeParamWithoutVariance(arg, args(0), depth, checkWeak)))
}
case _ => {
val aOptions: Seq[Options] = {
t1 match {
case ScCompoundType(comps1, decls1, typeDecls1, subst1) => comps1.map(new Options(_))
case _ => Seq(new Options(t1))
}
}
val bOptions: Seq[Options] = {
t2 match {
case ScCompoundType(comps1, decls1, typeDecls1, subst1) => comps1.map(new Options(_))
case _ => Seq(new Options(t2))
}
}
if (aOptions.find(_.isEmpty) != None || bOptions.find(_.isEmpty) != None) Any
else {
val buf = new ArrayBuffer[ScType]
val supers: Array[(Options, Int, Int)] =
getLeastUpperClasses(aOptions, bOptions)
for (sup <- supers) {
val tp = getTypeForAppending(aOptions(sup._2), bOptions(sup._3), sup._1, depth, checkWeak)
if (tp != Any) buf += tp
}
buf.toArray match {
case a: Array[ScType] if a.length == 0 => Any
case a: Array[ScType] if a.length == 1 => a(0)
case many =>
new ScCompoundType(collection.immutable.Seq(many.toSeq: _*), Seq.empty, Seq.empty, ScSubstitutor.empty)
}
}
//todo: refinement for compound types
}
}
}
def maybeExpandAlias(t: ScType) = t match {
case alias: ScProjectionType => ScType.expandAliases(alias).getOrElse(t)
case _ => t
}
lubWithExpandedAliases(maybeExpandAlias(t1), maybeExpandAlias(t2))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment