Skip to content

Improve orDominator #12272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1981,7 +1981,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
* @note We do not admit singleton types in or-types as lubs.
*/
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false): Type = /*>|>*/ trace(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain)", subtyping, show = true) /*<|<*/ {

if (tp1 eq tp2) tp1
else if (!tp1.exists) tp1
else if (!tp2.exists) tp2
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,12 @@ object TypeOps:

tp match {
case tp: OrType =>
approximateOr(tp.tp1, tp.tp2)
(tp.tp1.dealias, tp.tp2.dealias) match
case (tp1 @ AppliedType(tycon1, args1), tp2 @ AppliedType(tycon2, args2))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this addresses the most common issue, I don't think that's enough to handle things like Tag[Long] | (Tag[Int] & SomeTrait) or type Tag2[X] <: Tag[X]; Tag[Long] | Tag2[Int]. But to properly deal with all possible cases it seems that we'd need a generalization of baseClasses that also returns base abstract types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since what we do here is an approximation anyway, I'd leave that under possible future improvement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me.

if tycon1.typeSymbol == tycon2.typeSymbol && (tycon1 =:= tycon2) =>
mergeRefinedOrApplied(tp1, tp2)
case (tp1, tp2) =>
approximateOr(tp1, tp2)
case _ =>
tp
}
Expand Down
40 changes: 40 additions & 0 deletions tests/pos/i12264.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
object test1:

object Html {
final opaque type Tag[+N] = String
def apply[N](name: String): Tag[N] = ???
}

object HtmlTags {
final def br: Html.Tag[Int] = Html("br")
final def p = Html[Long]("p")
}

object Test {
type Expect = Html.Tag[Any]

val x = List[Expect](HtmlTags.br, HtmlTags.p) // ok

val y = List(HtmlTags.br, HtmlTags.p)
y: List[Expect] // was error
}

class test2:
type Tag[+N]
object Html:
def apply[N](name: String): Tag[N] = ???

object HtmlTags {
final def br: Tag[Int] = Html("br")
final def p = Html[Long]("p")
}

object Test {
type Expect = Tag[Any]

val x = List[Expect](HtmlTags.br, HtmlTags.p) // ok

val y = List(HtmlTags.br, HtmlTags.p)
y: List[Expect] // was error
}