diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0df81f756925..babebcfad8f0 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -3,23 +3,13 @@ package dotc package transform package patmat -import core.* -import Types.* -import Contexts.* -import Flags.* -import ast.* -import Decorators.{ show => _, * } -import Symbols.* -import StdNames.* -import NameOps.* -import Constants.* -import typer.* -import Applications.* -import Inferencing.* -import ProtoTypes.* +import core.*, Constants.*, Contexts.*, Decorators.*, Flags.*, Names.*, NameOps.*, StdNames.*, Symbols.*, Types.* +import ast.*, tpd.* +import config.Printers.* +import printing.{ Printer, * }, Texts.* import reporting.* -import config.Printers.{exhaustivity => debug} -import util.{SrcPos, NoSourcePosition} +import typer.*, Applications.*, Inferencing.*, ProtoTypes.* +import util.* import scala.annotation.internal.sharable import scala.collection.mutable @@ -56,7 +46,7 @@ import SpaceEngine.* */ /** space definition */ -sealed trait Space: +sealed trait Space extends Showable: @sharable private val isSubspaceCache = mutable.HashMap.empty[Space, Boolean] @@ -67,9 +57,7 @@ sealed trait Space: if (a ne a2) || (b ne b2) then a2.isSubspace(b2) else if a == Empty then true else if b == Empty then false - else trace(s"isSubspace(${show(this)}, ${show(b)})", debug) { - isSubspaceCache.getOrElseUpdate(b, computeIsSubspace(a, b)) - } + else isSubspaceCache.getOrElseUpdate(b, computeIsSubspace(a, b)) @sharable private var mySimplified: Space | Null = null @@ -80,6 +68,13 @@ sealed trait Space: mySimplified = simplified simplified else simplified + + def toText(p: Printer): Text = inContext(p.printerContext)(this match { + case Empty => s"Empty" + case sp: Typ => s"Typ(${display(sp)})" + case sp: Prod => s"Prod(${display(sp)})" + case sp: Or => s"Or(${display(sp)})" + }) end Space /** Empty space */ @@ -114,15 +109,13 @@ case class Prod(tp: Type, unappTp: TermRef, params: List[Space]) extends Space case class Or(spaces: Seq[Space]) extends Space object SpaceEngine { - import tpd.* - def simplify(space: Space)(using Context): Space = space.simplify def isSubspace(a: Space, b: Space)(using Context): Boolean = a.isSubspace(b) def canDecompose(typ: Typ)(using Context): Boolean = typ.canDecompose def decompose(typ: Typ)(using Context): List[Typ] = typ.decompose /** Simplify space such that a space equal to `Empty` becomes `Empty` */ - def computeSimplify(space: Space)(using Context): Space = trace(s"simplify ${show(space)} --> ", debug, show)(space match { + def computeSimplify(space: Space)(using Context): Space = trace(s"simplify($space)")(space match { case Prod(tp, fun, spaces) => val sps = spaces.mapconserve(simplify) if sps.contains(Empty) then Empty @@ -173,7 +166,7 @@ object SpaceEngine { } /** Is `a` a subspace of `b`? Equivalent to `simplify(simplify(a) - simplify(b)) == Empty`, but faster */ - def computeIsSubspace(a: Space, b: Space)(using Context): Boolean = { + def computeIsSubspace(a: Space, b: Space)(using Context): Boolean = trace(s"isSubspace($a, $b)") { val a2 = simplify(a) val b2 = simplify(b) if (a ne a2) || (b ne b2) then isSubspace(a2, b2) @@ -202,7 +195,7 @@ object SpaceEngine { } /** Intersection of two spaces */ - def intersect(a: Space, b: Space)(using Context): Space = trace(s"${show(a)} & ${show(b)}", debug, show) { + def intersect(a: Space, b: Space)(using Context): Space = trace(s"$a & $b") { (a, b) match { case (Empty, _) | (_, Empty) => Empty case (_, Or(ss)) => Or(ss.map(intersect(a, _)).filter(_ ne Empty)) @@ -211,11 +204,11 @@ object SpaceEngine { if isSubType(tp1, tp2) then a else if isSubType(tp2, tp1) then b else intersectUnrelatedAtomicTypes(tp1, tp2)(a) - case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) => + case (a @ Typ(tp1, _), b @ Prod(tp2, fun, ss)) => if isSubType(tp2, tp1) then b else if isSubType(tp1, tp2) then a // problematic corner case: inheriting a case class else intersectUnrelatedAtomicTypes(tp1, tp2)(b) - case (Prod(tp1, fun, ss), b @ Typ(tp2, _)) => + case (a @ Prod(tp1, fun, ss), b @ Typ(tp2, _)) => if isSubType(tp1, tp2) then a else if isSubType(tp2, tp1) then a // problematic corner case: inheriting a case class else intersectUnrelatedAtomicTypes(tp1, tp2)(a) @@ -227,7 +220,7 @@ object SpaceEngine { } /** The space of a not covered by b */ - def minus(a: Space, b: Space)(using Context): Space = trace(s"${show(a)} - ${show(b)}", debug, show) { + def minus(a: Space, b: Space)(using Context): Space = trace(s"$a - $b") { (a, b) match { case (Empty, _) => Empty case (_, Empty) => a @@ -291,8 +284,8 @@ object SpaceEngine { /** Is the unapply or unapplySeq irrefutable? * @param unapp The unapply function tree */ - def isIrrefutable(unapp: tpd.Tree, argLen: Int)(using Context): Boolean = { - tpd.funPart(unapp).tpe match + def isIrrefutable(unapp: Tree, argLen: Int)(using Context): Boolean = { + funPart(unapp).tpe match case funRef: TermRef => isIrrefutable(funRef, argLen) case _: ErrorType => false } @@ -301,7 +294,7 @@ object SpaceEngine { * @param body The body of the quoted pattern * @param bodyPt The scrutinee body type */ - def isIrrefutableQuotePattern(pat: tpd.QuotePattern, pt: Type)(using Context): Boolean = { + def isIrrefutableQuotePattern(pat: QuotePattern, pt: Type)(using Context): Boolean = { if pat.body.isType then pat.bindings.isEmpty && pt =:= pat.tpe else pat.body match case _: SplicePattern | Typed(_: SplicePattern, _) => pat.bindings.isEmpty && pt <:< pat.tpe @@ -313,24 +306,24 @@ object SpaceEngine { * The types should be atomic (non-decomposable) and unrelated (neither * should be a subtype of the other). */ - def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type)(sp: Space)(using Context): Space = trace(i"atomic intersection: ${AndType(tp1, tp2)}", debug, show) { + def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type)(sp: Typ | Prod)(using Context): Space = trace(i"intersectUnrelatedAtomicTypes($tp1, $tp2)(${sp.className})") { // Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1). + def intersection = sp match + case sp: Prod => sp.copy(AndType(tp1, tp2)) + case sp: Typ => sp.copy(AndType(tp1, tp2)) if !ctx.mode.is(Mode.SafeNulls) && (tp1.isNullType || tp2.isNullType) then // Since projections of types don't include null, intersection with null is empty. Empty - else - val intersection = sp match - case sp: Prod => sp.copy(AndType(tp1, tp2)) - case _ => Typ(AndType(tp1, tp2), decomposed = false) + else if tp1.classSymbol.isNumericValueClass && tp2.classSymbol.isNumericValueClass then // unrelated numeric value classes can equal each other, so let's not consider type space intersection empty - if tp1.classSymbol.isNumericValueClass && tp2.classSymbol.isNumericValueClass then intersection - else if isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) then intersection - else if TypeComparer.provablyDisjoint(tp1, tp2) then Empty - else intersection + intersection + else if isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) then intersection + else if TypeComparer.provablyDisjoint(tp1, tp2) then Empty + else intersection } /** Return the space that represents the pattern `pat` */ - def project(pat: Tree)(using Context): Space = trace(i"project($pat ${pat.className} ${pat.tpe})", debug, show)(pat match { + def project(pat: Tree)(using Context): Space = trace(i"project($pat ${pat.className} ${pat.tpe})")(pat match { case Literal(c) => if (c.value.isInstanceOf[Symbol]) Typ(c.value.asInstanceOf[Symbol].termRef, decomposed = false) @@ -447,7 +440,10 @@ object SpaceEngine { * This is needed to avoid spurious unreachable warnings. See tests/patmat/i6197.scala. */ private def erase(tp: Type, inArray: Boolean = false, isValue: Boolean = false, isTyped: Boolean = false)(using Context): Type = - trace(i"erase($tp${if inArray then " inArray" else ""}${if isValue then " isValue" else ""}${if isTyped then " isTyped" else ""})", debug)(tp match { + val inArr = if inArray then " inArray" else "" + val isVal = if isValue then " isValue" else "" + val isTyp = if isTyped then " isTyped" else "" + trace(i"erase($tp ${tp.className}$inArr$isVal$isTyp)")(tp match { case tp @ AppliedType(tycon, args) if tycon.typeSymbol.isPatternBound => WildcardType @@ -496,7 +492,7 @@ object SpaceEngine { tp.isPrimitiveValueType && (defn.boxedType(tp).classSymbol eq pt.classSymbol) /** Is `tp1` a subtype of `tp2`? */ - def isSubType(tp1: Type, tp2: Type)(using Context): Boolean = trace(i"$tp1 <:< $tp2", debug, show = true) { + def isSubType(tp1: Type, tp2: Type)(using Context): Boolean = trace(i"$tp1 <:< $tp2") { if tp1 == ConstantType(Constant(null)) && !ctx.mode.is(Mode.SafeNulls) then tp2 == ConstantType(Constant(null)) else if tp1.isTupleXXLExtract(tp2) then true // See isTupleXXLExtract, fixes TupleXXL parameter type @@ -520,11 +516,9 @@ object SpaceEngine { /** Return term parameter types of the extractor `unapp`. * Parameter types of the case class type `tp`. Adapted from `unapplyPlan` in patternMatcher */ - def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): List[Type] = { + def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): List[Type] = trace(i"signature($unapp, $scrutineeTp, $argLen)") { val unappSym = unapp.symbol - // println("scrutineeTp = " + scrutineeTp.show) - val mt: MethodType = unapp.widen match { case mt: MethodType => mt case pt: PolyType => @@ -583,8 +577,6 @@ object SpaceEngine { } } - debug.println(s"signature of ${unappSym.showFullName} ----> ${sig.map(_.show).mkString(", ")}") - sig.map(_.annotatedToRepeated) } @@ -602,7 +594,7 @@ object SpaceEngine { } /** Decompose a type into subspaces -- assume the type can be decomposed */ - def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)", debug) { + def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)") { def rec(tp: Type, mixins: List[Type]): List[Type] = tp.dealias match case AndType(tp1, tp2) => var tpB = tp2 @@ -640,13 +632,11 @@ object SpaceEngine { else if (child.is(Private) || child.is(Sealed)) && child.isOneOf(AbstractOrTrait) then getChildren(child) else List(child) } - val children = getChildren(tp.classSymbol) - debug.println(i"candidates for $tp : $children") + val children = trace(i"getChildren($tp)")(getChildren(tp.classSymbol)) val parts = children.map { sym => val sym1 = if (sym.is(ModuleClass)) sym.sourceModule else sym - val refined = TypeOps.refineUsingParent(tp, sym1, mixins) - debug.println(i"$sym1 refined to $refined") + val refined = trace(i"refineUsingParent($tp, $sym1, $mixins)")(TypeOps.refineUsingParent(tp, sym1, mixins)) def inhabited(tp: Type): Boolean = tp.dealias match case AndType(tp1, tp2) => !TypeComparer.provablyDisjoint(tp1, tp2) @@ -658,7 +648,6 @@ object SpaceEngine { if inhabited(refined) then refined else NoType }.filter(_.exists) - debug.println(i"$tp decomposes to $parts") parts case _ => ListOfNoType @@ -693,49 +682,13 @@ object SpaceEngine { * * E.g. C.this.B --> B if current owner is C * C.this.x.T --> x.T if current owner is C - * X[T] --> X * C --> C if current owner is C !!! - * */ - def showType(tp: Type, showTypeArgs: Boolean = false)(using Context): String = { + private class LocalPrinter(_ctx: Context) extends RefinedPrinter(_ctx): val enclosingCls = ctx.owner.enclosingClass - - def isOmittable(sym: Symbol) = - sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName || - ctx.definitions.unqualifiedOwnerTypes.exists(_.symbol == sym) || - sym.showFullName.startsWith("scala.") || - sym == enclosingCls || sym == enclosingCls.sourceModule - - def refinePrefix(tp: Type): String = tp match { - case NoPrefix => "" - case tp: NamedType if isOmittable(tp.symbol) => "" - case tp: ThisType => refinePrefix(tp.tref) - case tp: RefinedType => refinePrefix(tp.parent) - case tp: NamedType => tp.name.show.stripSuffix("$") - case tp: TypeVar => refinePrefix(tp.instanceOpt) - case _ => tp.show - } - - def refine(tp: Type): String = tp.stripped match { - case tp: RefinedType => refine(tp.parent) - case tp: AppliedType => - refine(tp.typeConstructor) + ( - if (showTypeArgs) tp.argInfos.map(refine).mkString("[", ",", "]") - else "" - ) - case tp: ThisType => refine(tp.tref) - case tp: NamedType => - val pre = refinePrefix(tp.prefix) - if (tp.name == tpnme.higherKinds) pre - else if (pre.isEmpty) tp.name.show.stripSuffix("$") - else pre + "." + tp.name.show.stripSuffix("$") - case tp: OrType => refine(tp.tp1) + " | " + refine(tp.tp2) - case _: TypeBounds => "_" - case _ => tp.show.stripSuffix("$") - } - - refine(tp) - } + override def isOmittablePrefix(sym: Symbol) = + super.isOmittablePrefix(sym) + || sym == enclosingCls || sym == enclosingCls.sourceModule /** Whether the counterexample is satisfiable. The space is flattened and non-empty. */ def satisfiable(sp: Space)(using Context): Boolean = { @@ -769,10 +722,8 @@ object SpaceEngine { checkConstraint(genConstraint(sp))(using ctx.fresh.setNewTyperState()) } - def showSpaces(ss: Seq[Space])(using Context): Seq[String] = ss.map(show) - - /** Display spaces */ - def show(s: Space)(using Context): String = { + /** Display spaces. Used for printing uncovered spaces in the in-exhaustive error message. */ + def display(s: Space)(using Context): String = inContext(ctx.fresh.setPrinterFn(LocalPrinter(_))) { def params(tp: Type): List[Type] = tp.classSymbol.primaryConstructor.info.firstParamTypes /** does the companion object of the given symbol have custom unapply */ @@ -789,39 +740,38 @@ object SpaceEngine { if (flattenList && tp <:< defn.NilType) "" else tp.symbol.showName case Typ(tp, decomposed) => - - val sym = tp.classSymbol - - if (ctx.definitions.isTupleNType(tp)) + val cls = tp.classSymbol + if ctx.definitions.isTupleNType(tp) then params(tp).map(_ => "_").mkString("(", ", ", ")") - else if (defn.ListType.isRef(sym)) - if (flattenList) "_*" else "_: List" - else if (defn.ConsType.isRef(sym)) - if (flattenList) "_, _*" else "List(_, _*)" - else if (tp.classSymbol.is(Sealed) && tp.classSymbol.hasAnonymousChild) - "_: " + showType(tp) + " (anonymous)" - else if (tp.classSymbol.is(CaseClass) && !hasCustomUnapply(tp.classSymbol)) - // use constructor syntax for case class - showType(tp) + params(tp).map(_ => "_").mkString("(", ", ", ")") - else if (decomposed) "_: " + showType(tp, showTypeArgs = true) - else "_" + else if defn.ListType.isRef(cls) then + if flattenList then "_*" else "_: List" + else if (defn.ConsType.isRef(cls)) + if flattenList then "_, _*" else "List(_, _*)" + else if cls.hasAnonymousChild then + s"_: ${tp.typeConstructor.show} (anonymous)" + else if cls.is(CaseClass) && !hasCustomUnapply(cls) then + // use constructor syntax for case class + tp.typeConstructor.show + params(tp).map(_ => "_").mkString("(", ", ", ")") + else if !decomposed then "_" + else "_: " + tp.show case Prod(tp, fun, params) => - if (ctx.definitions.isTupleNType(tp)) + if ctx.definitions.isTupleNType(tp) then "(" + params.map(doShow(_)).mkString(", ") + ")" - else if (tp.isRef(defn.ConsType.symbol)) - if (flattenList) params.map(doShow(_, flattenList)).filter(_.nonEmpty).mkString(", ") - else params.map(doShow(_, flattenList = true)).filter(!_.isEmpty).mkString("List(", ", ", ")") - else { - val sym = fun.symbol - val isUnapplySeq = sym.name.eq(nme.unapplySeq) + else if tp.isRef(defn.ConsType.symbol) then + val body = params.map(doShow(_, flattenList = true)).filter(_.nonEmpty).mkString(", ") + if flattenList then body else s"List($body)" + else + val isUnapplySeq = fun.symbol.name eq nme.unapplySeq val paramsStr = params.map(doShow(_, flattenList = isUnapplySeq)).mkString("(", ", ", ")") - showType(fun.prefix) + paramsStr - } + val prefix = fun.prefix match + case pre: TermRef => pre.symbol.typeRef + case pre => pre + prefix.typeConstructor.show + paramsStr case Or(ss) => ss.map(doShow(_, flattenList)).mkString(" | ") } - doShow(s, flattenList = false) + doShow(s) } private def exhaustivityCheckable(sel: Tree)(using Context): Boolean = { @@ -845,13 +795,11 @@ object SpaceEngine { else true // recursive case class: return true and other members can still fail the check } - val res = !sel.tpe.hasAnnotation(defn.UncheckedAnnot) && { + !sel.tpe.hasAnnotation(defn.UncheckedAnnot) + && { ctx.settings.YcheckAllPatmat.value || isCheckable(sel.tpe) } - - debug.println(s"exhaustivity checkable: ${sel.show} = $res") - res } /** Whether counter-examples should be further checked? True for GADTs. */ @@ -866,7 +814,7 @@ object SpaceEngine { /** Return the underlying type of non-module, non-constant, non-enum case singleton types. * Also widen ExprType to its result type, and rewrap any annotation wrappers. * For example, with `val opt = None`, widen `opt.type` to `None.type`. */ - def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp)", show = true)(tp match { + def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp)")(tp match { case _: ConstantType => tp case tp: TermRef if tp.symbol.is(Module) => tp case tp: TermRef if tp.symbol.isAllOf(EnumCase) => tp @@ -876,27 +824,25 @@ object SpaceEngine { case _ => tp }) - def checkExhaustivity(m: Match)(using Context): Unit = trace(i"checkExhaustivity($m)", debug) { + def checkExhaustivity(m: Match)(using Context): Unit = trace(i"checkExhaustivity($m)") { val selTyp = toUnderlying(m.selector.tpe).dealias - debug.println(i"selTyp = $selTyp") + val targetSpace = trace(i"targetSpace($selTyp)")(project(selTyp)) val patternSpace = Or(m.cases.foldLeft(List.empty[Space]) { (acc, x) => - val space = if (x.guard.isEmpty) project(x.pat) else Empty - debug.println(s"${x.pat.show} ====> ${show(space)}") + val space = if x.guard.isEmpty then trace(i"project(${x.pat})")(project(x.pat)) else Empty space :: acc }) val checkGADTSAT = shouldCheckExamples(selTyp) val uncovered = - flatten(simplify(minus(project(selTyp), patternSpace))).filter({ s => + flatten(simplify(minus(targetSpace, patternSpace))).filter({ s => s != Empty && (!checkGADTSAT || satisfiable(s)) }) - if uncovered.nonEmpty then val deduped = dedup(uncovered) - report.warning(PatternMatchExhaustivity(showSpaces(deduped), m), m.selector) + report.warning(PatternMatchExhaustivity(deduped.map(display), m), m.selector) } private def reachabilityCheckable(sel: Tree)(using Context): Boolean = @@ -909,17 +855,16 @@ object SpaceEngine { && !sel.tpe.widen.isRef(defn.QuotedExprClass) && !sel.tpe.widen.isRef(defn.QuotedTypeClass) - def checkReachability(m: Match)(using Context): Unit = trace(i"checkReachability($m)", debug) { + def checkReachability(m: Match)(using Context): Unit = trace(i"checkReachability($m)") { val cases = m.cases.toIndexedSeq val selTyp = toUnderlying(m.selector.tpe).dealias - debug.println(i"selTyp = $selTyp") val isNullable = selTyp.classSymbol.isNullableClass - val targetSpace = if isNullable + val targetSpace = trace(i"targetSpace($selTyp)")(if isNullable then project(OrType(selTyp, ConstantType(Constant(null)), soft = false)) else project(selTyp) - debug.println(s"targetSpace: ${show(targetSpace)}") + ) var i = 0 val len = cases.length @@ -929,16 +874,11 @@ object SpaceEngine { while (i < len) { val CaseDef(pat, guard, _) = cases(i) - debug.println(i"case pattern: $pat") - - val curr = project(pat) - debug.println(i"reachable? ${show(curr)}") + val curr = trace(i"project($pat)")(project(pat)) - val prev = simplify(Or(prevs)) - debug.println(s"prev: ${show(prev)}") + val covered = trace("covered")(simplify(intersect(curr, targetSpace))) - val covered = simplify(intersect(curr, targetSpace)) - debug.println(s"covered: ${show(covered)}") + val prev = trace("prev")(simplify(Or(prevs))) if prev == Empty && covered == Empty then // defer until a case is reachable deferred ::= pat diff --git a/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala b/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala index c13ef0532348..d7b2fd6a5173 100644 --- a/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala @@ -27,12 +27,12 @@ class SpaceEngineTest: val a = Prod(tp, unappTp, params) val b = Empty - val res1 = isSubspace(a, b) + val res1 = a.isSubspace(b) - val a2 = simplify(a) - val b2 = simplify(b) + val a2 = a.simplify + val b2 = b.simplify val rem1 = minus(a2, b2) - val rem2 = simplify(rem1) + val rem2 = rem1.simplify val res2 = rem2 == Empty assertEquals( @@ -46,19 +46,12 @@ class SpaceEngineTest: |simplify(rem1) == Empty |rem2 == Empty | - |a = ${show(a)} - |b = ${show(b)} - |a2 = ${show(a2)} - |b2 = ${show(b2)} - |rem1 = ${show(rem1)} - |rem2 = ${show(rem2)} - | - |a = ${a.toString} - |b = ${b.toString} - |a2 = ${a2.toString} - |b2 = ${b2.toString} - |rem1 = ${rem1.toString} - |rem2 = ${rem2.toString} + |a = $a + |b = $b + |a2 = $a2 + |b2 = $b2 + |rem1 = $rem1 + |rem2 = $rem2 | |""".stripMargin, res1, res2) } diff --git a/tests/patmat/aliasing.check b/tests/patmat/aliasing.check index c367626d6f1e..018905abf47e 100644 --- a/tests/patmat/aliasing.check +++ b/tests/patmat/aliasing.check @@ -1,3 +1,3 @@ -14: Pattern Match Exhaustivity: _: Trait & Test.Alias1, _: Clazz & Test.Alias1 -19: Pattern Match Exhaustivity: _: Trait & Test.Alias2 -23: Pattern Match Exhaustivity: _: Trait & (Test.Alias2 & OpenTrait2){val x: Int} +14: Pattern Match Exhaustivity: _: Trait & Alias1, _: Clazz & Alias1 +19: Pattern Match Exhaustivity: _: Trait & Alias2 +23: Pattern Match Exhaustivity: _: Trait & (Alias2 & OpenTrait2){val x: Int} diff --git a/tests/patmat/i12020.check b/tests/patmat/i12020.check index b89bdc8314e5..13b07e2e5992 100644 --- a/tests/patmat/i12020.check +++ b/tests/patmat/i12020.check @@ -1 +1 @@ -19: Pattern Match Exhaustivity: _: TypeDef +19: Pattern Match Exhaustivity: _: x$1.reflect.TypeDef diff --git a/tests/patmat/i2502.check b/tests/patmat/i2502.check index fe2194e650cf..56cd3f6c0b8c 100644 --- a/tests/patmat/i2502.check +++ b/tests/patmat/i2502.check @@ -1 +1 @@ -5: Pattern Match Exhaustivity: _: BTypes.ClassBType \ No newline at end of file +5: Pattern Match Exhaustivity: _: BTypes.this.ClassBType diff --git a/tests/patmat/i2502b.check b/tests/patmat/i2502b.check index fe2194e650cf..56cd3f6c0b8c 100644 --- a/tests/patmat/i2502b.check +++ b/tests/patmat/i2502b.check @@ -1 +1 @@ -5: Pattern Match Exhaustivity: _: BTypes.ClassBType \ No newline at end of file +5: Pattern Match Exhaustivity: _: BTypes.this.ClassBType diff --git a/tests/patmat/i3938.check b/tests/patmat/i3938.check index 5aaefe2263e1..2acd1040ead4 100644 --- a/tests/patmat/i3938.check +++ b/tests/patmat/i3938.check @@ -1 +1 @@ -34: Pattern Match Exhaustivity: bar.C() +34: Pattern Match Exhaustivity: foo.bar.C() diff --git a/tests/patmat/i6255b.check b/tests/patmat/i6255b.check index 265ec9fa9c4b..bd9585becc56 100644 --- a/tests/patmat/i6255b.check +++ b/tests/patmat/i6255b.check @@ -1 +1 @@ -3: Pattern Match Exhaustivity: _: Expr[Int] +3: Pattern Match Exhaustivity: _: scala.quoted.Expr[Int] diff --git a/tests/patmat/t10100.check b/tests/patmat/t10100.check index d11715a5f371..19a89cd08a74 100644 --- a/tests/patmat/t10100.check +++ b/tests/patmat/t10100.check @@ -1 +1 @@ -12: Pattern Match Exhaustivity: (_, FancyFoo(_)) +12: Pattern Match Exhaustivity: (_, NonExhaustive#FancyFoo(_)) diff --git a/tests/patmat/t9779.check b/tests/patmat/t9779.check index 63f3b8963cac..c1886064d8ef 100644 --- a/tests/patmat/t9779.check +++ b/tests/patmat/t9779.check @@ -1 +1 @@ -10: Pattern Match Exhaustivity: _: a.Elem[_] +10: Pattern Match Exhaustivity: _: a.Elem[?]