From fd97de5d677c41a2a68e560dc0dd32d4cbb235b7 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 7 Sep 2023 18:38:17 +0100 Subject: [PATCH 1/3] Use the unwidened type when casting structural calls So if the call is to a stable val, the call will have a stable type. --- .../src/dotty/tools/dotc/typer/Dynamic.scala | 4 ++-- tests/pos/i18263.orig.scala | 16 ++++++++++++++++ tests/pos/i18263.scala | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i18263.orig.scala create mode 100644 tests/pos/i18263.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 717966923708..1c829567058a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -235,14 +235,14 @@ trait Dynamic { if ValueClasses.isDerivedValueClass(tpe.classSymbol) && qual.tpe <:< defn.ReflectSelectableTypeRef then val genericUnderlying = ValueClasses.valueClassUnbox(tpe.classSymbol.asClass) val underlying = tpe.select(genericUnderlying).widen.resultType - New(tpe, tree.cast(underlying) :: Nil) + New(tpe.widen, tree.cast(underlying) :: Nil) else tree maybeBoxed.cast(tpe) fun.tpe.widen match { case tpe: ValueType => - structuralCall(nme.selectDynamic, Nil).maybeBoxingCast(tpe) + structuralCall(nme.selectDynamic, Nil).maybeBoxingCast(fun.tpe) case tpe: MethodType => def isDependentMethod(tpe: Type): Boolean = tpe match { diff --git a/tests/pos/i18263.orig.scala b/tests/pos/i18263.orig.scala new file mode 100644 index 000000000000..68b000580f08 --- /dev/null +++ b/tests/pos/i18263.orig.scala @@ -0,0 +1,16 @@ +sealed trait Scope +sealed trait Domain extends Scope +object Domain extends Domain + +trait Baz[T] +def baz(using ck: Scope): Baz[ck.type] = ??? + +class Foo extends scala.reflect.Selectable: + type TScope = Domain + final protected given TScope = Domain + +object ID: + val internal1 = new Foo: + val ii = new Foo: + val x = baz + val z = internal1.ii.x //error diff --git a/tests/pos/i18263.scala b/tests/pos/i18263.scala new file mode 100644 index 000000000000..4fe79999afe7 --- /dev/null +++ b/tests/pos/i18263.scala @@ -0,0 +1,15 @@ +final class Bar +final class Inv[T] +class Foo extends scala.reflect.Selectable: + type Boo = Bar + final given boo1: Boo = new Bar + +class Test: + def mkInv(using bar: Bar): Inv[bar.type] = new Inv() + + def test: Unit = + val foo1 /* : Foo { val foo2: { z1 => Foo { val inv1: Inv[(z1.boo1 : z1.Boo)] }}} */ = new Foo: + val foo2 /* : { z1 => Foo { val inv1: Inv[(z1.boo1 : z1.Boo)] }} */ = new Foo: + val inv1 /* : Inv[( boo1 : Boo)] */ = mkInv /* (this.boo1) */ + val inv2 = foo1.foo2.inv1 // error + () From f1758a61d46d8cd8a474fc50ca3b5c918967ac9a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 8 Sep 2023 13:36:16 +0100 Subject: [PATCH 2/3] Add a .widenExpr call --- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 7 +------ compiler/src/dotty/tools/dotc/typer/Dynamic.scala | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 6659818b333e..fa8e3d0850a7 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -969,16 +969,11 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => !tree.symbol.exists && tree.isTerm && hasRefinement(tree.qualifier.tpe) - def loop(tree: Tree): Boolean = tree match - case TypeApply(fun, _) => - loop(fun) - case Apply(fun, _) => - loop(fun) + funPart(tree) match case tree: Select => isStructuralTermSelect(tree) case _ => false - loop(tree) } /** Return a pair consisting of (supercall, rest) diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 1c829567058a..51734e1a5d4b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -242,7 +242,7 @@ trait Dynamic { fun.tpe.widen match { case tpe: ValueType => - structuralCall(nme.selectDynamic, Nil).maybeBoxingCast(fun.tpe) + structuralCall(nme.selectDynamic, Nil).maybeBoxingCast(fun.tpe.widenExpr) case tpe: MethodType => def isDependentMethod(tpe: Type): Boolean = tpe match { From af81e64cb81efd295f02b4b071492fb8e28e0186 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 26 Sep 2023 10:25:16 +0100 Subject: [PATCH 3/3] Fix HoverProvider --- .../src/main/dotty/tools/pc/HoverProvider.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala index 6c2251988f65..1ddb79fabc98 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala @@ -181,7 +181,7 @@ object HoverProvider: findRefinement(parent) case _ => None - val refTpe = sel.tpe.metalsDealias match + val refTpe = sel.tpe.widen.metalsDealias match case r: RefinedType => Some(r) case t: (TermRef | TypeProxy) => Some(t.termSymbol.info.metalsDealias) case _ => None