Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Nonsensical TASTy for the SELFDEF of non-static object with an explicit self => name. #19019

Closed
sjrd opened this issue Nov 22, 2023 · 1 comment

Comments

@sjrd
Copy link
Member

sjrd commented Nov 22, 2023

Compiler version

3.3.1

Minimized code

package simple_trees

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

Output

Tree after typer:

package simple_trees {
  final lazy module val ObjectWithSelf: simple_trees.ObjectWithSelf =
    new simple_trees.ObjectWithSelf()
  final module class ObjectWithSelf() extends Object() {
    this: simple_trees.ObjectWithSelf.type =>
    final lazy module val StaticObjectNoSelf:
      simple_trees.ObjectWithSelf.StaticObjectNoSelf =
      new simple_trees.ObjectWithSelf.StaticObjectNoSelf()
    final module class StaticObjectNoSelf() extends Object() {
      this: simple_trees.ObjectWithSelf.StaticObjectNoSelf.type =>
      def foo: Any = this
    }
    final lazy module val StaticObjectWithSelf:
      simple_trees.ObjectWithSelf.StaticObjectWithSelf =
      new simple_trees.ObjectWithSelf.StaticObjectWithSelf()
    final module class StaticObjectWithSelf() extends Object() {
      self: simple_trees.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: this.type =>
        def foo: Any = self
      }
    }
  }
}
Full decoded TASTy Tress
Trees:
start = Addr(0), base = 551, current = Addr(0), end = Addr(445)
445 bytes of AST, base = Addr(0)

     0: PACKAGE(442)
     3:   TERMREFpkg 1 [simple_trees]
     5:   VALDEF(18) 2 [ObjectWithSelf]
     8:     IDENTtpt 3 [ObjectWithSelf[ModuleClass]]
    10:       TYPEREFsymbol 25
    12:         TERMREFpkg 1 [simple_trees]
    14:     APPLY(8)
    16:       SELECTin(6) 7 [<init>[Signed Signature(List(),simple_trees.ObjectWithSelf$) @<init>]]
    19:         NEW
    20:           SHAREDterm 8
    22:         SHAREDtype 10
    24:     OBJECT
    25:   TYPEDEF(417) 3 [ObjectWithSelf[ModuleClass]]
    29:     TEMPLATE(392)
    32:       APPLY(10)
    34:         SELECTin(8) 13 [<init>[Signed Signature(List(),java.lang.Object) @<init>]]
    37:           NEW
    38:             TYPEREF 11 [Object]
    40:               TERMREFpkg 10 [java[Qualified . lang]]
    42:           SHAREDtype 38
    44:       SELFDEF 14 [_]
    46:         SINGLETONtpt
    47:           TERMREFsymbol 5
    49:             SHAREDtype 12
    51:       DEFDEF(6) 4 [<init>]
    54:         EMPTYCLAUSE
    55:         TYPEREF 15 [Unit]
    57:           TERMREFpkg 16 [scala]
    59:       DEFDEF(23) 17 [writeReplace]
    62:         EMPTYCLAUSE
    63:         TYPEREF 18 [AnyRef]
    65:           SHAREDtype 57
    67:         APPLY(13)
    69:           SELECTin(8) 25 [<init>[Signed Signature(List(java.lang.Class),scala.runtime.ModuleSerializationProxy) @<init>]]
    72:             NEW
    73:               TYPEREF 21 [ModuleSerializationProxy]
    75:                 TERMREFpkg 20 [scala[Qualified . runtime]]
    77:             SHAREDtype 73
    79:           CLASSconst
    80:             SHAREDtype 47
    82:         PRIVATE
    83:         SYNTHETIC
    84:       VALDEF(19) 26 [StaticObjectNoSelf]
    87:         IDENTtpt 27 [StaticObjectNoSelf[ModuleClass]]
    89:           TYPEREFsymbol 105
    91:             THIS
    92:               SHAREDtype 10
    94:         APPLY(8)
    96:           SELECTin(6) 30 [<init>[Signed Signature(List(),simple_trees.ObjectWithSelf$.StaticObjectNoSelf$) @<init>]]
    99:             NEW
   100:               SHAREDterm 87
   102:             SHAREDtype 89
   104:         OBJECT
   105:       TYPEDEF(61) 27 [StaticObjectNoSelf[ModuleClass]]
   108:         TEMPLATE(57)
   110:           APPLY(8)
   112:             SELECTin(6) 13 [<init>[Signed Signature(List(),java.lang.Object) @<init>]]
   115:               NEW
   116:                 SHAREDtype 38
   118:               SHAREDtype 38
   120:           SELFDEF 14 [_]
   122:             SINGLETONtpt
   123:               TERMREFsymbol 84
   125:                 SHAREDtype 91
   127:           DEFDEF(5) 4 [<init>]
   130:             EMPTYCLAUSE
   131:             SHAREDtype 55
   133:             STABLE
   134:           DEFDEF(19) 17 [writeReplace]
   137:             EMPTYCLAUSE
   138:             SHAREDtype 63
   140:             APPLY(11)
   142:               SELECTin(6) 25 [<init>[Signed Signature(List(java.lang.Class),scala.runtime.ModuleSerializationProxy) @<init>]]
   145:                 NEW
   146:                   SHAREDtype 73
   148:                 SHAREDtype 73
   150:               CLASSconst
   151:                 SHAREDtype 123
   153:             PRIVATE
   154:             SYNTHETIC
   155:           DEFDEF(10) 31 [foo]
   158:             IDENTtpt 32 [Any]
   160:               TYPEREF 32 [Any]
   162:                 TERMREFpkg 16 [scala]
   164:             THIS
   165:               SHAREDtype 89
   167:         OBJECT
   168:       VALDEF(21) 33 [StaticObjectWithSelf]
   171:         IDENTtpt 34 [StaticObjectWithSelf[ModuleClass]]
   173:           TYPEREFsymbol 191
   176:             SHAREDtype 91
   178:         APPLY(10)
   180:           SELECTin(8) 37 [<init>[Signed Signature(List(),simple_trees.ObjectWithSelf$.StaticObjectWithSelf$) @<init>]]
   183:             NEW
   184:               SHAREDterm 171
   187:             SHAREDtype 173
   190:         OBJECT
   191:       TYPEDEF(65) 34 [StaticObjectWithSelf[ModuleClass]]
   194:         TEMPLATE(61)
   196:           APPLY(8)
   198:             SELECTin(6) 13 [<init>[Signed Signature(List(),java.lang.Object) @<init>]]
   201:               NEW
   202:                 SHAREDtype 38
   204:               SHAREDtype 38
   206:           SELFDEF 38 [self]
   208:             SINGLETONtpt
   209:               TERMREFsymbol 168
   212:                 SHAREDtype 91
   214:           DEFDEF(5) 4 [<init>]
   217:             EMPTYCLAUSE
   218:             SHAREDtype 55
   220:             STABLE
   221:           DEFDEF(20) 17 [writeReplace]
   224:             EMPTYCLAUSE
   225:             SHAREDtype 63
   227:             APPLY(12)
   229:               SELECTin(6) 25 [<init>[Signed Signature(List(java.lang.Class),scala.runtime.ModuleSerializationProxy) @<init>]]
   232:                 NEW
   233:                   SHAREDtype 73
   235:                 SHAREDtype 73
   237:               CLASSconst
   238:                 SHAREDtype 209
   241:             PRIVATE
   242:             SYNTHETIC
   243:           DEFDEF(12) 31 [foo]
   246:             IDENTtpt 32 [Any]
   248:               SHAREDtype 160
   251:             QUALTHIS
   252:               IDENTtpt 34 [StaticObjectWithSelf[ModuleClass]]
   254:                 SHAREDtype 173
   257:         OBJECT
   258:       TYPEDEF(163) 39 [Container]
   262:         TEMPLATE(159)
   265:           APPLY(8)
   267:             SELECTin(6) 13 [<init>[Signed Signature(List(),java.lang.Object) @<init>]]
   270:               NEW
   271:                 SHAREDtype 38
   273:               SHAREDtype 38
   275:           DEFDEF(4) 4 [<init>]
   278:             EMPTYCLAUSE
   279:             SHAREDtype 55
   281:           VALDEF(25) 40 [NonStaticObjectNoSelf]
   284:             IDENTtpt 41 [NonStaticObjectNoSelf[ModuleClass]]
   286:               TYPEREFsymbol 308
   289:                 THIS
   290:                   TYPEREFsymbol 258
   293:                     SHAREDtype 91
   295:             APPLY(10)
   297:               SELECTin(8) 45 [<init>[Signed Signature(List(),simple_trees.ObjectWithSelf$.Container.NonStaticObjectNoSelf$) @<init>]]
   300:                 NEW
   301:                   SHAREDterm 284
   304:                 SHAREDtype 286
   307:             OBJECT
   308:           TYPEDEF(44) 41 [NonStaticObjectNoSelf[ModuleClass]]
   311:             TEMPLATE(40)
   313:               APPLY(8)
   315:                 SELECTin(6) 13 [<init>[Signed Signature(List(),java.lang.Object) @<init>]]
   318:                   NEW
   319:                     SHAREDtype 38
   321:                   SHAREDtype 38
   323:               SELFDEF 14 [_]
   325:                 SINGLETONtpt
   326:                   SELECT 40 [NonStaticObjectNoSelf]
   328:                     QUALTHIS
   329:                       IDENTtpt 39 [Container]
   331:                         SHAREDtype 290
   334:               DEFDEF(5) 4 [<init>]
   337:                 EMPTYCLAUSE
   338:                 SHAREDtype 55
   340:                 STABLE
   341:               DEFDEF(10) 31 [foo]
   344:                 IDENTtpt 32 [Any]
   346:                   SHAREDtype 160
   349:                 THIS
   350:                   SHAREDtype 286
   353:             OBJECT
   354:           VALDEF(22) 46 [NonStaticObjectWithSelf]
   357:             IDENTtpt 47 [NonStaticObjectWithSelf[ModuleClass]]
   359:               TYPEREFsymbol 378
   362:                 SHAREDtype 289
   365:             APPLY(10)
   367:               SELECTin(8) 50 [<init>[Signed Signature(List(),simple_trees.ObjectWithSelf$.Container.NonStaticObjectWithSelf$) @<init>]]
   370:                 NEW
   371:                   SHAREDterm 357
   374:                 SHAREDtype 359
   377:             OBJECT
   378:           TYPEDEF(44) 47 [NonStaticObjectWithSelf[ModuleClass]]
   381:             TEMPLATE(40)
   383:               APPLY(8)
   385:                 SELECTin(6) 13 [<init>[Signed Signature(List(),java.lang.Object) @<init>]]
   388:                   NEW
   389:                     SHAREDtype 38
   391:                   SHAREDtype 38
   393:               SELFDEF 38 [self]
   395:                 SINGLETONtpt
   396:                   QUALTHIS
   397:                     IDENTtpt 47 [NonStaticObjectWithSelf[ModuleClass]]
   399:                       SHAREDtype 359
   402:               DEFDEF(5) 4 [<init>]
   405:                 EMPTYCLAUSE
   406:                 SHAREDtype 55
   408:                 STABLE
   409:               DEFDEF(12) 31 [foo]
   412:                 IDENTtpt 32 [Any]
   414:                   SHAREDtype 160
   417:                 QUALTHIS
   418:                   IDENTtpt 47 [NonStaticObjectWithSelf[ModuleClass]]
   420:                     SHAREDtype 359
   423:             OBJECT
   424:     OBJECT
   425:     ANNOTATION(18)
   427:       TYPEREF 51 [SourceFile]
   429:         TERMREFpkg 55 [scala[Qualified . annotation][Qualified . internal]]
   431:       APPLY(12)
   433:         SELECTin(8) 59 [<init>[Signed Signature(List(java.lang.String),scala.annotation.internal.SourceFile) @<init>]]
   436:           NEW
   437:             SHAREDtype 427
   440:           SHAREDtype 427
   443:         STRINGconst 60 [test-sources/src/main/scala/simple_trees/ObjectWithSelf.scala]
   445:

Chosen excerpts:

// StaticObjectNoSelf

    84:       VALDEF(19) 26 [StaticObjectNoSelf]
    87:         IDENTtpt 27 [StaticObjectNoSelf[ModuleClass]]
    89:           TYPEREFsymbol 105
    91:             THIS
    92:               SHAREDtype 10
    94:         APPLY(8)
...
   105:       TYPEDEF(61) 27 [StaticObjectNoSelf[ModuleClass]]
   108:         TEMPLATE(57)
...
   120:           SELFDEF 14 [_]
   122:             SINGLETONtpt
   123:               TERMREFsymbol 84
   125:                 SHAREDtype 91
...

// StaticObjectWithSelf

   168:       VALDEF(21) 33 [StaticObjectWithSelf]
   171:         IDENTtpt 34 [StaticObjectWithSelf[ModuleClass]]
   173:           TYPEREFsymbol 191
   176:             SHAREDtype 91
...
   191:       TYPEDEF(65) 34 [StaticObjectWithSelf[ModuleClass]]
   194:         TEMPLATE(61)
...
   206:           SELFDEF 38 [self]
   208:             SINGLETONtpt
   209:               TERMREFsymbol 168
   212:                 SHAREDtype 91
...

// Container.NonStaticObjectNoSelf

   281:           VALDEF(25) 40 [NonStaticObjectNoSelf]
   284:             IDENTtpt 41 [NonStaticObjectNoSelf[ModuleClass]]
   286:               TYPEREFsymbol 308
   289:                 THIS
   290:                   TYPEREFsymbol 258
   293:                     SHAREDtype 91
...
   308:           TYPEDEF(44) 41 [NonStaticObjectNoSelf[ModuleClass]]
   311:             TEMPLATE(40)
...
   323:               SELFDEF 14 [_]
   325:                 SINGLETONtpt
   326:                   SELECT 40 [NonStaticObjectNoSelf]
   328:                     QUALTHIS
   329:                       IDENTtpt 39 [Container]
   331:                         SHAREDtype 290
...

// NonStaticObjectWithSelf

   354:           VALDEF(22) 46 [NonStaticObjectWithSelf]
   357:             IDENTtpt 47 [NonStaticObjectWithSelf[ModuleClass]]
   359:               TYPEREFsymbol 378
   362:                 SHAREDtype 289
...
   378:           TYPEDEF(44) 47 [NonStaticObjectWithSelf[ModuleClass]]
   381:             TEMPLATE(40)
...
   393:               SELFDEF 38 [self]
   395:                 SINGLETONtpt
   396:                   QUALTHIS
   397:                     IDENTtpt 47 [NonStaticObjectWithSelf[ModuleClass]]
   399:                       SHAREDtype 359
...

Remarks:

OK: The declared type of every module VALDEF is a TypeRef of the module class, for example Container.this.NonStaticObjectNoSelf[ModuleClass].

OK: The type of the SELFDEF for the 3 first cases (both static objects, and the non-static object without self =>), is a SINGLETONtpt of a term ref to the VALDEF, for example Container.this.NonStaticObjectNoSelf.type.

NOT OK: The type of the SELFDEF for the last case--the non-static object with a self =>-- is the this-type of its own module class, namely NonStaticObjectWithSelf[ModuleClass].this.type.

Why is not OK? Because it creates a loop in the superType chain (or underlying) of that this type. The underlying of the this-type is the self type; but the underlying of the self is the this-type!

Expectation

I expect the type of the last SELFDEF to be consistent with the other three, and point to the singleton type of the accompanying VALDEF.

@sjrd sjrd added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 22, 2023
sjrd added a commit to sjrd/tasty-query that referenced this issue Nov 22, 2023
…sses.

Re-create the correct self type which is a term reference to the
accompanying lazy val.
@sjrd
Copy link
Member Author

sjrd commented Nov 23, 2023

⭐ How to debug a weird compiler issue in 10 EASY steps! ⭐

This happens because:

  1. Desugar always correctly creates self: ModuleVal.type =>

  2. When typing the ValDef of that self, if there is an explicit name, it has a symbol

  3. Because it has a symbol, it becomes the ctx.owner in typedValDef. This comes from def localContext.

  4. localContext has, funnily enough, a comment that reads

    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

    but it then overrides the efforts that typedClassDef made to type it using ctx.outer (with a nice comment "outer context where class members are not visible")

  5. When we get to typing the Ident(ModuleVal), we check whether its prefixIsElidable. If its owner is a class (but not a package or a local scope), that will not be elidable.

  6. Therefore, typedIdent > setType turns it into a fresh ref(ModuleValSym)

  7. Since it's (still) not elidable, and because the target symbol is(Module), ref tests ctx.owner.isContainedIn(tp.symbol.moduleClass)

  8. Can you feel it now? the ctx.owner is the symbol of the self ValDef (because it has an explicit name, see step 3)

  9. And yup, the val def is "contained in" the module class of the symbol.

  10. In that situation, ref creates a new This(moduleClass)

This explains why:

  • it works when the scope is static or local (prefixIsElidable is true) -- regardless of explicit self => or not
  • it works without explicit self => because the self ValDef has no symbol -- making ctx.owner.isContainedIn false

@sjrd sjrd self-assigned this Nov 23, 2023
@sjrd sjrd added area:typer and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 23, 2023
sjrd added a commit to scalacenter/tasty-query that referenced this issue Nov 23, 2023
Work around scala/scala3#19019: patch the SelfDef of inner module classes.
sjrd added a commit to dotty-staging/dotty that referenced this issue Nov 23, 2023
WojciechMazur added a commit that referenced this issue Jun 23, 2024
…." to LTS (#20764)

Backports #19030 to the LTS branch.

PR submitted by the release tooling.
[skip ci]
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

1 participant