From 0ce09551350d817ba15ed5d30209ccf91d7b0ee0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 26 Oct 2023 11:18:01 +0100 Subject: [PATCH] Identify structural trees on Match Type qualifiers Without this change, selecting `v1` on a type `Ifce[(true : Boolean)]#RT` which widens to a MatchType wouldn't be identified as a structural tree, which later breaks Erasure. [Cherry-picked ff90012510dd986381871c425bd9341e9216d3c8] --- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 2 ++ tests/neg/i17192.5.scala | 12 ++++++++++++ tests/pos/i17192.scala | 11 +++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/neg/i17192.5.scala create mode 100644 tests/pos/i17192.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index befac83b824b..7cd6ef96b4f5 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -949,6 +949,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match case defn.PolyOrErasedFunctionOf(_) => false + case tp: MatchType => + hasRefinement(tp.tryNormalize) case RefinedType(parent, rname, rinfo) => rname == tree.name || hasRefinement(parent) case tp: TypeProxy => diff --git a/tests/neg/i17192.5.scala b/tests/neg/i17192.5.scala new file mode 100644 index 000000000000..2837af36b573 --- /dev/null +++ b/tests/neg/i17192.5.scala @@ -0,0 +1,12 @@ +class Ifce[BT <: Boolean]: + type RT = BT match + case true => this.type { val v1: Int } + def cast: RT = this.asInstanceOf[RT] + +class Test: + def t1: Unit = + val full1 = new Ifce[true]().cast + val v1 = full1.v1 // error +// ^^^^^ +// Found: (full1 : Ifce[(true : Boolean)]#RT) +// Required: Selectable | Dynamic diff --git a/tests/pos/i17192.scala b/tests/pos/i17192.scala new file mode 100644 index 000000000000..129da358b3ba --- /dev/null +++ b/tests/pos/i17192.scala @@ -0,0 +1,11 @@ +class Ifce[BT <: Boolean] extends Selectable: + type RT = BT match + case true => this.type { val v1: Int } + case false => this.type + def cast : RT = this.asInstanceOf[RT] + def selectDynamic(key: String): Any = ??? + +class Test: + def t1: Unit = + val full = (new Ifce[true]).cast + val v1 = full.v1