From 3a00dc515759803b2f0860317fbb9458deb9367d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 8 Mar 2022 16:02:52 +0000 Subject: [PATCH 1/2] When assigning type cases, substitute any instances of type parameters for the applied arguments --- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 12 ++++++++---- tests/neg/6697.check | 13 ------------- tests/{neg => pos}/6697.scala | 0 tests/pos/i14477.scala | 9 +++++++++ 4 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 tests/neg/6697.check rename tests/{neg => pos}/6697.scala (100%) create mode 100644 tests/pos/i14477.scala diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 2b5e7dd6f17c..2303b2fbba08 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -401,15 +401,19 @@ trait TypeAssigner { def assignType(tree: untpd.CaseDef, pat: Tree, body: Tree)(using Context): CaseDef = { val ownType = if (body.isType) { - val params = new TreeAccumulator[mutable.ListBuffer[TypeSymbol]] { + val getParams = new TreeAccumulator[mutable.ListBuffer[TypeSymbol]] { def apply(ps: mutable.ListBuffer[TypeSymbol], t: Tree)(using Context) = t match { case t: Bind if t.symbol.isType => foldOver(ps += t.symbol.asType, t) case _ => foldOver(ps, t) } } - HKTypeLambda.fromParams( - params(new mutable.ListBuffer[TypeSymbol](), pat).toList, - defn.MatchCase(pat.tpe, body.tpe)) + val params = getParams(new mutable.ListBuffer[TypeSymbol](), pat).toList + pat.tpe match + case AppliedType(tycon, args) => + val tparams = tycon.typeParamSymbols + for param <- params do param.info = param.info.subst(tparams, args) + case _ => + HKTypeLambda.fromParams(params, defn.MatchCase(pat.tpe, body.tpe)) } else body.tpe tree.withType(ownType) diff --git a/tests/neg/6697.check b/tests/neg/6697.check deleted file mode 100644 index 3249ad7aa4af..000000000000 --- a/tests/neg/6697.check +++ /dev/null @@ -1,13 +0,0 @@ --- [E057] Type Mismatch Error: tests/neg/6697.scala:6:35 --------------------------------------------------------------- -6 | type Copy[O <: Off] = Of[Sup[O], Sub[O]] // error - | ^ - | Type argument Test.Sub[O] does not conform to upper bound Test.Sup[O] - | - | Note: a match type could not be fully reduced: - | - | trying to reduce Test.Sub[O] - | failed since selector O - | does not match case Test.Of[sup, sub] => sub - | and cannot be shown to be disjoint from it either. - | - | longer explanation available when compiling with `-explain` diff --git a/tests/neg/6697.scala b/tests/pos/6697.scala similarity index 100% rename from tests/neg/6697.scala rename to tests/pos/6697.scala diff --git a/tests/pos/i14477.scala b/tests/pos/i14477.scala new file mode 100644 index 000000000000..1647cb3432d4 --- /dev/null +++ b/tests/pos/i14477.scala @@ -0,0 +1,9 @@ +sealed trait Foo[A, X <: A] + +type FooX[F] = F match { + case Foo[a, x] => x +} + +type MyFoo = Foo[String, "hello"] + +val hello: FooX[MyFoo] = "hello" From 81cc6f11a19b1c7dce6e39b48a8b97b89672c9b6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 8 Mar 2022 17:46:12 +0000 Subject: [PATCH 2/2] Use substSym instead of mutating symbols --- .../dotty/tools/dotc/typer/TypeAssigner.scala | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 2303b2fbba08..7c15a2bb99bf 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -407,13 +407,19 @@ trait TypeAssigner { case _ => foldOver(ps, t) } } - val params = getParams(new mutable.ListBuffer[TypeSymbol](), pat).toList - pat.tpe match + val params1 = getParams(new mutable.ListBuffer[TypeSymbol](), pat).toList + val params2 = pat.tpe match case AppliedType(tycon, args) => val tparams = tycon.typeParamSymbols - for param <- params do param.info = param.info.subst(tparams, args) - case _ => - HKTypeLambda.fromParams(params, defn.MatchCase(pat.tpe, body.tpe)) + params1.mapconserve { param => + val info1 = param.info + val info2 = info1.subst(tparams, args) + if info2 eq info1 then param else param.copy(info = info2).asType + } + case _ => params1 + val matchCase1 = defn.MatchCase(pat.tpe, body.tpe) + val matchCase2 = if params2 eq params1 then matchCase1 else matchCase1.substSym(params1, params2) + HKTypeLambda.fromParams(params2, matchCase2) } else body.tpe tree.withType(ownType)