Skip to content

Commit a029737

Browse files
committed
change SIP-67 implementation based on @odersky's review
1 parent 0a565d0 commit a029737

File tree

5 files changed

+18
-14
lines changed

5 files changed

+18
-14
lines changed

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ trait Applications extends Compatibility {
13381338
case Apply(fn @ Select(left, _), right :: Nil) if fn.hasType =>
13391339
val op = fn.symbol
13401340
if (op == defn.Any_== || op == defn.Any_!=)
1341-
checkCanEqual(left.tpe.widen, right.tpe.widen, app.span)
1341+
checkCanEqual(left, right.tpe.widen, app.span)
13421342
case _ =>
13431343
}
13441344
app

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,7 @@ trait Implicits:
10391039
* - if one of T, U is a subtype of the lifted version of the other,
10401040
* unless strict equality is set.
10411041
*/
1042-
def assumedCanEqual(ltp: Type, rtp: Type)(using Context) = {
1042+
def assumedCanEqual(leftTreeOption: Option[Tree], ltp: Type, rtp: Type)(using Context): Boolean = {
10431043
// Map all non-opaque abstract types to their upper bound.
10441044
// This is done to check whether such types might plausibly be comparable to each other.
10451045
val lift = new TypeMap {
@@ -1062,15 +1062,20 @@ trait Implicits:
10621062

10631063
ltp.isError
10641064
|| rtp.isError
1065-
|| !strictEquality && (ltp <:< lift(rtp) || rtp <:< lift(ltp))
1065+
|| locally:
1066+
if strictEquality then
1067+
leftTreeOption.exists: leftTree =>
1068+
leftTree.symbol.flags.isAllOf(Flags.EnumValue) || (leftTree.symbol.flags.isAllOf(Flags.Module | Flags.Case))
1069+
else
1070+
(ltp <:< lift(rtp) || rtp <:< lift(ltp))
10661071
}
10671072

10681073
/** Check that equality tests between types `ltp` and `rtp` make sense */
1069-
def checkCanEqual(ltp: Type, rtp: Type, span: Span)(using Context): Unit =
1070-
if (!ctx.isAfterTyper && !assumedCanEqual(ltp, rtp)) {
1074+
def checkCanEqual(left: Tree, rtp: Type, span: Span)(using Context): Unit =
1075+
val ltp = left.tpe.widen
1076+
if !ctx.isAfterTyper && !assumedCanEqual(Some(left), ltp, rtp) then
10711077
val res = implicitArgTree(defn.CanEqualClass.typeRef.appliedTo(ltp, rtp), span)
10721078
implicits.println(i"CanEqual witness found for $ltp / $rtp: $res: ${res.tpe}")
1073-
}
10741079

10751080
object hasSkolem extends TreeAccumulator[Boolean]:
10761081
def apply(x: Boolean, tree: Tree)(using Context): Boolean =

compiler/src/dotty/tools/dotc/typer/ReTyper.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
175175

176176
override def inferView(from: Tree, to: Type)(using Context): Implicits.SearchResult =
177177
Implicits.NoMatchingImplicitsFailure
178-
override def checkCanEqual(ltp: Type, rtp: Type, span: Span)(using Context): Unit = ()
178+
override def checkCanEqual(left: Tree, rtp: Type, span: Span)(using Context): Unit = ()
179179

180180
override def widenEnumCase(tree: Tree, pt: Type)(using Context): Tree = tree
181181

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
183183
* one of `tp1`, `tp2` has a reflexive `CanEqual` instance.
184184
*/
185185
def validEqAnyArgs(tp1: Type, tp2: Type)(using Context) =
186-
typer.assumedCanEqual(tp1, tp2)
186+
typer.assumedCanEqual(None, tp1, tp2)
187187
|| withMode(Mode.StrictEquality) {
188188
!hasEq(tp1) && !hasEq(tp2)
189189
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5052,12 +5052,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
50525052

50535053
Linter.warnOnImplausiblePattern(tree, pt)
50545054

5055-
if ! (tree.tpe <:< pt && (tree.symbol.flags.isAllOf(Flags.EnumValue) || (tree.symbol.flags.isAllOf(Flags.Module | Flags.Case)))) then
5056-
val cmp =
5057-
untpd.Apply(
5058-
untpd.Select(untpd.TypedSplice(tree), nme.EQ),
5059-
untpd.TypedSplice(dummyTreeOfType(pt)))
5060-
typedExpr(cmp, defn.BooleanType)
5055+
val cmp =
5056+
untpd.Apply(
5057+
untpd.Select(untpd.TypedSplice(tree), nme.EQ),
5058+
untpd.TypedSplice(dummyTreeOfType(pt)))
5059+
typedExpr(cmp, defn.BooleanType)
50615060
case _ =>
50625061

50635062
private def checkStatementPurity(tree: tpd.Tree)(original: untpd.Tree, exprOwner: Symbol, isUnitExpr: Boolean = false)(using Context): Unit =

0 commit comments

Comments
 (0)