Skip to content

Commit 89a744f

Browse files
authored
Include P in the implicit scope of P.this.type (#17088)
Before this commit, `one` compiled but `two` didn't in: ```scala class Foo[+T] class Elem: def one(a: Elem, x: Foo[a.type]): Int = x.ext def two(x: Foo[Elem.this.type]): Int = x.ext object Elem: extension (x: Foo[Elem]) def ext: Int = 1 ``` This happened because the anchors of the singleton reference `a.type` includes its underlying type `Elem`, but `Elem.this.type` has no anchors at all. This commit changes the definition of anchors to rectify this, which also brings us closer to how Scala 2 behaves.
2 parents 528d931 + 6eeea19 commit 89a744f

File tree

3 files changed

+11
-1
lines changed

3 files changed

+11
-1
lines changed

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ trait ImplicitRunInfo:
622622
traverse(t.prefix)
623623
case t: ThisType if t.cls.is(Module) && t.cls.isStaticOwner =>
624624
traverse(t.cls.sourceModule.termRef)
625+
case t: ThisType =>
626+
traverse(t.tref)
625627
case t: ConstantType =>
626628
traverse(t.underlying)
627629
case t: TypeParamRef =>
@@ -743,6 +745,7 @@ trait ImplicitRunInfo:
743745
* - If `T` is a singleton reference, the anchors of its underlying type, plus,
744746
* if `T` is of the form `(P#x).type`, the anchors of `P`.
745747
* - If `T` is the this-type of a static object, the anchors of a term reference to that object.
748+
* - If `T` is some other this-type `P.this.type`, the anchors of `P`.
746749
* - If `T` is some other type, the union of the anchors of each constituent type of `T`.
747750
*
748751
* The _implicit scope_ of a type `tp` is the smallest set S of term references (i.e. TermRefs)

docs/_docs/reference/changed-features/implicit-resolution.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ Opaque type aliases count as anchors only outside the scope where their alias is
6767
1. If _T_ is a reference to a type parameter, the union of the anchors of both of its bounds.
6868
1. If _T_ is a singleton reference, the anchors of its underlying type, plus,
6969
if _T_ is of the form _(P#x).type_, the anchors of _P_.
70-
1. If _T_ is the this-type _o.this_ of a static object _o_, the anchors of a term reference _o.type_ to that object.
70+
1. If _T_ is the this-type _o.this_ of a static object _o_, the anchors of a term reference _o.type_ to that object,
71+
1. If _T_ is some other this-type _P.this.type_, the anchors of _P_.
7172
1. If _T_ is some other type, the union of the anchors of each constituent type of _T_.
7273

7374
**Definition:** The _implicit scope_ of a type _T_ is the smallest set _S_ of term references such that

tests/pos/this-implicit-scope.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Foo[+T]
2+
class Elem:
3+
def one(a: Elem, x: Foo[a.type]): Int = x.ext
4+
def two(x: Foo[Elem.this.type]): Int = x.ext
5+
object Elem:
6+
extension (x: Foo[Elem]) def ext: Int = 1

0 commit comments

Comments
 (0)