Skip to content

Outer field suppression based on "local instantiation" should consider transitive owners #11367

Closed
@retronym

Description

@retronym

Compiler version

./bin/scalac -version
Scala compiler version 3.0.0-M4-bin-SNAPSHOT-git-a66eaf3 -- Copyright 2002-2021, LAMP/EPFL

Minimized code

class C { 
  def foo = {
    class D {
      class E
    }
    class F
  }
}

Output

jardiff -c '/tmp/C$D$1$E.class'

+++ C$D$1$E.class.asm
// class version 52.0 (52)
// access flags 0x21
public class C$D$1$E {

  // access flags 0xA
  private static INNERCLASS C$D$1 C D
  // access flags 0x1
  public INNERCLASS C$D$1$E C$D$1 E

  // access flags 0x12
  private final LC$D$1; $outer

  // access flags 0x1
  public <init>(LC$D$1;)V

  // access flags 0x11
  public final C$_$D$E$$$outer()LC$D$1;
}

Expectation

There is no need for an outer pointer here as E is not instantiable from another compilation unit and it does not refer to the outer instance.

This check could be extended to consider walk the owner chain in search of a transitive term owner.

  private def hasLocalInstantiation(cls: ClassSymbol)(using Context): Boolean =
    // Modules are normally locally instantiated, except if they are declared in a trait,
    // in which case they will be instantiated in the classes that mix in the trait.
    cls.owner.isTerm || cls.is(Private, butNot = Module) || (cls.is(Module) && !cls.owner.is(Trait))

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions