From ab201d4c0d3bdb944ebdaf56568f210e856d61b8 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 17 Sep 2025 14:47:03 +0200 Subject: [PATCH] Revert "Merge pull request #275 from scala/backport-lts-3.3-22604" This reverts commit 91aacdb7505fa9e78a8e4d8a38194868f9fea3d4, reversing changes made to cc130d4917a985b0f35920f8f1677686cb3c47b7. --- .../tools/dotc/transform/patmat/Space.scala | 6 ++- .../dotty/tools/dotc/typer/Implicits.scala | 47 +++++++++---------- .../dotty/tools/scaladoc/site/templates.scala | 8 ++-- tests/pos/switches.scala | 1 - tests/{warn => pos}/t10373.scala | 4 +- tests/warn/i15662.scala | 1 - tests/warn/i21218.scala | 1 - tests/warn/i22590.arity2.scala | 15 ------ tests/warn/i22590.scala | 9 ---- tests/warn/opaque-match.scala | 2 - 10 files changed, 35 insertions(+), 59 deletions(-) rename tests/{warn => pos}/t10373.scala (74%) delete mode 100644 tests/warn/i22590.arity2.scala delete mode 100644 tests/warn/i22590.scala diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0dfa73035099..def5eaec708e 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -801,6 +801,7 @@ object SpaceEngine { } private def exhaustivityCheckable(sel: Tree)(using Context): Boolean = { + val seen = collection.mutable.Set.empty[Symbol] // Possible to check everything, but be compatible with scalac by default def isCheckable(tp: Type): Boolean = @@ -815,7 +816,10 @@ object SpaceEngine { }) || tpw.isRef(defn.BooleanClass) || classSym.isAllOf(JavaEnumTrait) || - classSym.is(Case) + classSym.is(Case) && { + if seen.add(classSym) then productSelectorTypes(tpw, sel.srcPos).exists(isCheckable(_)) + else true // recursive case class: return true and other members can still fail the check + } !sel.tpe.hasAnnotation(defn.UncheckedAnnot) && { diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index c7e7de0dc61a..23dede13ffec 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1298,30 +1298,29 @@ trait Implicits: if alt1.isExtension then // Fall back: if both results are extension method applications, // compare the extension methods instead of their wrappers. - def stripExtension(alt: SearchSuccess) = - methPart(stripApply(alt.tree)).tpe: @unchecked match { case ref: TermRef => ref } - val ref1 = stripExtension(alt1) - val ref2 = stripExtension(alt2) - // ref1 and ref2 might refer to type variables owned by - // alt1.tstate and alt2.tstate respectively, to compare the - // alternatives correctly we need a TyperState that includes - // constraints from both sides, see - // tests/*/extension-specificity2.scala for test cases. - val constraintsIn1 = alt1.tstate.constraint ne ctx.typerState.constraint - val constraintsIn2 = alt2.tstate.constraint ne ctx.typerState.constraint - def exploreState(alt: SearchSuccess): TyperState = - alt.tstate.fresh(committable = false) - val comparisonState = - if constraintsIn1 && constraintsIn2 then - exploreState(alt1).mergeConstraintWith(alt2.tstate) - else if constraintsIn1 then - exploreState(alt1) - else if constraintsIn2 then - exploreState(alt2) - else - ctx.typerState - - diff = inContext(ctx.withTyperState(comparisonState)): + def stripExtension(alt: SearchSuccess) = methPart(stripApply(alt.tree)).tpe + ((stripExtension(alt1), stripExtension(alt2)) : @unchecked) match + case (ref1: TermRef, ref2: TermRef) => + // ref1 and ref2 might refer to type variables owned by + // alt1.tstate and alt2.tstate respectively, to compare the + // alternatives correctly we need a TyperState that includes + // constraints from both sides, see + // tests/*/extension-specificity2.scala for test cases. + val constraintsIn1 = alt1.tstate.constraint ne ctx.typerState.constraint + val constraintsIn2 = alt2.tstate.constraint ne ctx.typerState.constraint + def exploreState(alt: SearchSuccess): TyperState = + alt.tstate.fresh(committable = false) + val comparisonState = + if constraintsIn1 && constraintsIn2 then + exploreState(alt1).mergeConstraintWith(alt2.tstate) + else if constraintsIn1 then + exploreState(alt1) + else if constraintsIn2 then + exploreState(alt2) + else + ctx.typerState + + diff = inContext(ctx.withTyperState(comparisonState)): compare(ref1, ref2) else // alt1 is a conversion, prefer extension alt2 over it diff = -1 diff --git a/scaladoc/src/dotty/tools/scaladoc/site/templates.scala b/scaladoc/src/dotty/tools/scaladoc/site/templates.scala index 56a0f7f6d6b6..92e0096e5af1 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/templates.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/templates.scala @@ -102,9 +102,11 @@ case class TemplateFile( ctx.layouts.getOrElse(name, throw new RuntimeException(s"No layouts named $name in ${ctx.layouts}")) ) - def asJavaElement(o: Any): Any = o match - case m: Map[?, ?] => m.transform { (k, v) => asJavaElement(v) }.asJava - case l: List[?] => l.map(asJavaElement).asJava + def asJavaElement(o: Object): Object = o match + case m: Map[_, _] => m.transform { + case (k: String, v: Object) => asJavaElement(v) + }.asJava + case l: List[_] => l.map(x => asJavaElement(x.asInstanceOf[Object])).asJava case other => other // Library requires mutable maps.. diff --git a/tests/pos/switches.scala b/tests/pos/switches.scala index beb378debb40..bd7e44f1c8cf 100644 --- a/tests/pos/switches.scala +++ b/tests/pos/switches.scala @@ -42,7 +42,6 @@ class Test { case IntAnyVal(100) => 2 case IntAnyVal(1000) => 3 case IntAnyVal(10000) => 4 - case _ => -1 } } diff --git a/tests/warn/t10373.scala b/tests/pos/t10373.scala similarity index 74% rename from tests/warn/t10373.scala rename to tests/pos/t10373.scala index ca49e7b1ce16..0d91313f694d 100644 --- a/tests/warn/t10373.scala +++ b/tests/pos/t10373.scala @@ -1,4 +1,4 @@ -//> using options -deprecation -feature +//> using options -Xfatal-warnings -deprecation -feature abstract class Foo { def bar(): Unit = this match { @@ -7,7 +7,7 @@ abstract class Foo { // Works fine } - def baz(that: Foo): Unit = (this, that) match { // warn: match may not be exhaustive. + def baz(that: Foo): Unit = (this, that) match { case (Foo_1(), _) => //do something case (Foo_2(), _) => //do something // match may not be exhaustive diff --git a/tests/warn/i15662.scala b/tests/warn/i15662.scala index f17a040b4980..0cf0e57ed0c3 100644 --- a/tests/warn/i15662.scala +++ b/tests/warn/i15662.scala @@ -5,7 +5,6 @@ case class Composite[T](v: T) def m(composite: Composite[?]): Unit = composite match { case Composite[Int](v) => println(v) // warn: cannot be checked at runtime - case _ => println("OTHER") } def m2(composite: Composite[?]): Unit = diff --git a/tests/warn/i21218.scala b/tests/warn/i21218.scala index db0810c5d7b0..29fa957e2e70 100644 --- a/tests/warn/i21218.scala +++ b/tests/warn/i21218.scala @@ -6,6 +6,5 @@ def Test[U, A](thisElem: A, thatElem: U) = { case (`passedEnd`, r: U @unchecked) => (thisElem, r) case (l: A @unchecked, `passedEnd`) => (l, thatElem) case t: (A, U) @unchecked => t // false-positive warning - case (t1, t2) => (t1, t2) } } diff --git a/tests/warn/i22590.arity2.scala b/tests/warn/i22590.arity2.scala deleted file mode 100644 index 8ce84ab299f1..000000000000 --- a/tests/warn/i22590.arity2.scala +++ /dev/null @@ -1,15 +0,0 @@ -sealed trait T_B -case class CC_A() extends T_B -case class CC_C() extends T_B - -sealed trait T_A -case class CC_B[B](a: B,b:T_B) extends T_A - - -@main def test() = { - val v_a: CC_B[Int] = null - val v_b: Int = v_a match { // warn: match may not be exhaustive. - case CC_B(12, CC_A()) => 0 - case CC_B(_, CC_C()) => 0 - } -} diff --git a/tests/warn/i22590.scala b/tests/warn/i22590.scala deleted file mode 100644 index 1520a07b86b8..000000000000 --- a/tests/warn/i22590.scala +++ /dev/null @@ -1,9 +0,0 @@ -sealed trait T_A -case class CC_B[T](a: T) extends T_A - -@main def test() = { - val v_a: CC_B[Int] = CC_B(10) - val v_b: Int = v_a match{ // warn: match may not be exhaustive. - case CC_B(12) => 0 - } -} diff --git a/tests/warn/opaque-match.scala b/tests/warn/opaque-match.scala index f66370def9b2..06cca835ab91 100644 --- a/tests/warn/opaque-match.scala +++ b/tests/warn/opaque-match.scala @@ -13,10 +13,8 @@ def Test[T] = case _: C => ??? // ok C() match case _: O.T => ??? // warn - case _ => ??? C() match case _: T => ??? // warn - case _ => ??? (??? : Any) match case _: List[O.T] => ??? // warn