Skip to content

Handle symbol.defTree properly for nested definitions in bindings #11550

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 1, 2021

Conversation

liufengyun
Copy link
Contributor

Handle symbol.defTree properly for nested definitions in bindings

Nested definitions in inlining bindings will get new symbols in
changeOwner. The Symbol.defTree is never set for those symbols.

The problem is exhibited in the following test

tests/pos/i10542.scala

The fix in 0f034aa works by accident:

@@ -115,7 +115,9 @@ class ReTyper extends Typer with ReChecking {
  }

  override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
    try super.typedUnadapted(tree, pt, locked)
    try super.typedUnadapted(tree, pt, locked) match
      case member: MemberDef => member.setDefTree
      case tree => tree

The reason is the following:

  • If we enable -Ycheck:all, it will sync the tree definition for
    all symbols during TreeChecker, thus no crash in initialization
    checker.

  • if we disable -Ycheck:all, the defTree for <init> is not set,
    initialization checker ignore the method, thus no crash.

However, if we change InlineTyper instead of Retyper:

+    override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
+      super.typedUnadapted(tree, pt, locked) match
+        case member: MemberDef => member.setDefTree
+        case tree => tree

There will be some mysterious behavior in compiling tests/pos/i10542.scala:

  • Without -Ycheck:all, it succeeds
  • With -Ycheck:all, the initialization check crashes due to missing
    defTree for the class $anon.

The reason for the mysterious behavior is the following:

  • Without -Ycheck:all, there is no defTree for <init>,
    initialization check is skipped, thus no crash.

  • With -Ycheck:all, the method Typer.typedDefDef will set
    Symbol.defTree for <init>, called from the TreeChecker, which
    extends Typer indirectly via ReTyper. However, in
    Typer.typedClassDef, we never set defTree for class symbols,
    thus the defTree for the class symbol $anon is empty, causing an
    exception in initialization check.

Co-authored-by: Nicolas Stucki [email protected]

Nested definitions in inlining bindings will get new symbols in
`changeOwner`. The field `Symbol.defTree` is never set for those symbols.

The problem is exhibited in the following test

    tests/pos/i10542.scala

The fix in 0f034aa works by accident:

```
@@ -115,7 +115,9 @@ class ReTyper extends Typer with ReChecking {
  }

  override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
    try super.typedUnadapted(tree, pt, locked)
    try super.typedUnadapted(tree, pt, locked) match
      case member: MemberDef => member.setDefTree
      case tree => tree
```

The reason is the following:

- If we enable `-Ycheck:all`, it will sync the tree definition for
  all symbols during TreeChecker, thus no crash in initialization
  checker.

- if we disable `-Ycheck:all`, the `defTree` for `<init>` is not set,
  initialization checker ignores the method, thus no crash.

However, if we change `InlineTyper` instead of `Retyper`:

```
+    override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
+      super.typedUnadapted(tree, pt, locked) match
+        case member: MemberDef => member.setDefTree
+        case tree => tree
```

There will be some mysterious behavior in compiling `tests/pos/i10542.scala`:

- Without `-Ycheck:all`, it succeeds.
- With `-Ycheck:all`, the initialization check crashes due to missing
 `defTree` for the class `$anon`.

The reason for the mysterious behavior is the following:

- Without `-Ycheck:all`, there is no defTree for `<init>`,
  initialization check is skipped, thus no crash.

- With `-Ycheck:all`, the method `Typer.typedDefDef` will set
  `Symbol.defTree` for `<init>`, called from the TreeChecker, which
  extends `Typer` indirectly via `ReTyper`. However, in
  `Typer.typedClassDef`, we never set `defTree` for class symbols,
  thus the `defTree` for the class symbol `$anon` is empty, causing an
  exception in initialization check.

Co-authored-by: Nicolas Stucki <[email protected]>
@liufengyun liufengyun merged commit 55da939 into scala:master Mar 1, 2021
@liufengyun liufengyun deleted the improve-deftree branch March 1, 2021 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants