From 311e5ce8f353f2283a49d1bc0825033bf6429c56 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 13 Oct 2020 11:44:09 +0200 Subject: [PATCH] Fix multiversal equality checks for pattern matching Equality checks against constants in patterns were usually suppressed since they were only issued if the GADT constrainer return false. We now drop this as a condition. This uncovered a missing position error, where we did a resolveOverloading when unpickling some Scala 2 code in Pattern mode. The missing position was the tree in the equality check, which is not surprising since was an annotation argument. The fix here was to make sure that we do overloading resolution only in expression mode. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 4 ++- .../src/dotty/tools/dotc/typer/Typer.scala | 12 ++++----- tests/neg/eql.scala | 25 +++++++++++++++++++ 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 tests/neg/eql.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 721bac57d907..9470ae045083 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1594,7 +1594,9 @@ object Trees { def resolveConstructor(atp: Type, args: List[Tree])(using Context): tpd.Tree = { val targs = atp.argTypes - applyOverloaded(tpd.New(atp.typeConstructor), nme.CONSTRUCTOR, args, targs, atp) + withoutMode(Mode.PatternOrTypeBits) { + applyOverloaded(tpd.New(atp.typeConstructor), nme.CONSTRUCTOR, args, targs, atp) + } } } } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 93453c22226b..f288c1ae38fb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3608,20 +3608,18 @@ class Typer extends Namer * Overwritten to no-op in ReTyper. */ protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(using Context) : Unit = - tree match { + tree match case _: RefTree | _: Literal - if !isVarPattern(tree) - && !(pt <:< tree.tpe) - && !withMode(Mode.GadtConstraintInference) { - TypeComparer.constrainPatternType(tree.tpe, pt) - } => + if !isVarPattern(tree) && !(pt <:< tree.tpe) => + withMode(Mode.GadtConstraintInference) { + TypeComparer.constrainPatternType(tree.tpe, pt) + } val cmp = untpd.Apply( untpd.Select(untpd.TypedSplice(tree), nme.EQ), untpd.TypedSplice(dummyTreeOfType(pt))) typedExpr(cmp, defn.BooleanType) case _ => - } private def checkStatementPurity(tree: tpd.Tree)(original: untpd.Tree, exprOwner: Symbol)(using Context): Unit = if !tree.tpe.isErroneous diff --git a/tests/neg/eql.scala b/tests/neg/eql.scala new file mode 100644 index 000000000000..04a317e6d9ea --- /dev/null +++ b/tests/neg/eql.scala @@ -0,0 +1,25 @@ +object lst: + opaque type Lst[+T] = Any + object Lst: + given lstEql[T, U] as Eql[Lst[T], Lst[U]] = Eql.derived + val Empty: Lst[Nothing] = ??? +end lst + +import lst.Lst + +val xs: Lst[Int] = ??? +val ys: List[Int] = ??? + +def test = + xs == ys // error: cannot be compared + ys == xs // error + xs == Nil // error + Nil == xs // error + ys == Lst.Empty // error + Lst.Empty == ys // error + xs match + case Nil => ??? // error, used to pass + ys match + case Lst.Empty => ??? // error, used to pass + +