Skip to content

Commit

Permalink
Use the unwidened type when casting structural calls (#18527)
Browse files Browse the repository at this point in the history
So if the call is to a stable val, the call will have a stable type.
  • Loading branch information
sjrd authored Oct 5, 2023
2 parents 7b3682d + af81e64 commit d788ef2
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 9 deletions.
7 changes: 1 addition & 6 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1005,16 +1005,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)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Dynamic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.widenExpr)

case tpe: MethodType =>
def isDependentMethod(tpe: Type): Boolean = tpe match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions tests/pos/i18263.orig.scala
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions tests/pos/i18263.scala
Original file line number Diff line number Diff line change
@@ -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
()

0 comments on commit d788ef2

Please sign in to comment.