Skip to content

Commit

Permalink
Fix #19019: Always type self ValDefs in their outer context. (#19030)
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky authored Nov 23, 2023
2 parents 08ab809 + 194ad8e commit bd5a2ae
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
15 changes: 11 additions & 4 deletions compiler/src/dotty/tools/dotc/core/ContextOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,19 @@ object ContextOps:
}

/** A fresh local context with given tree and owner.
* Owner might not exist (can happen for self valdefs), in which case
* no owner is set in result context
*/
*
* #19019 Self valdefs must always keep their enclosing ctx.owner. They
* can be NoSymbol or having a symbol with the SelfName flag, depending on
* whether they have an explicit name or not. In either case, we avoid
* `setOwner`.
*
* The owner might also not exist for other kinds of trees, such as
* `LambdaTypeTree` and `TermLambdaTypeTree`. In these cases, we also
* keep the enclosing owner.
*/
def localContext(tree: untpd.Tree, owner: Symbol): FreshContext = inContext(ctx) {
val freshCtx = ctx.fresh.setTree(tree)
if owner.exists then freshCtx.setOwner(owner) else freshCtx
if owner.exists && !owner.is(SelfName) then freshCtx.setOwner(owner) else freshCtx
}

/** Context where `sym` is defined, assuming we are in a nested context. */
Expand Down
37 changes: 37 additions & 0 deletions tests/printing/i19019.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[[syntax trees at end of typer]] // tests/printing/i19019.scala
package <empty> {
final lazy module val ObjectWithSelf: ObjectWithSelf = new ObjectWithSelf()
final module class ObjectWithSelf() extends Object() {
this: ObjectWithSelf.type =>
final lazy module val StaticObjectNoSelf: ObjectWithSelf.StaticObjectNoSelf
= new ObjectWithSelf.StaticObjectNoSelf()
final module class StaticObjectNoSelf() extends Object() {
this: ObjectWithSelf.StaticObjectNoSelf.type =>
def foo: Any = this
}
final lazy module val StaticObjectWithSelf:
ObjectWithSelf.StaticObjectWithSelf =
new ObjectWithSelf.StaticObjectWithSelf()
final module class StaticObjectWithSelf() extends Object() {
self: ObjectWithSelf.StaticObjectWithSelf.type =>
def foo: Any = self
}
class Container() extends Object() {
final lazy module val NonStaticObjectNoSelf:
Container.this.NonStaticObjectNoSelf =
new Container.this.NonStaticObjectNoSelf()
final module class NonStaticObjectNoSelf() extends Object() {
this: Container.this.NonStaticObjectNoSelf.type =>
def foo: Any = this
}
final lazy module val NonStaticObjectWithSelf:
Container.this.NonStaticObjectWithSelf =
new Container.this.NonStaticObjectWithSelf()
final module class NonStaticObjectWithSelf() extends Object() {
self: Container.this.NonStaticObjectWithSelf.type =>
def foo: Any = self
}
}
}
}

23 changes: 23 additions & 0 deletions tests/printing/i19019.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
object ObjectWithSelf:
object StaticObjectNoSelf:
def foo: Any = this
end StaticObjectNoSelf

object StaticObjectWithSelf:
self =>

def foo: Any = self
end StaticObjectWithSelf

class Container:
object NonStaticObjectNoSelf:
def foo: Any = this
end NonStaticObjectNoSelf

object NonStaticObjectWithSelf:
self =>

def foo: Any = self
end NonStaticObjectWithSelf
end Container
end ObjectWithSelf

0 comments on commit bd5a2ae

Please sign in to comment.