Skip to content

Adding self type breaks usages of an otherwise accessible protected method #24305

@raquo

Description

@raquo

Compiler version

3.3.7, 3.5.2, 3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY

Minimized code

Must be in two separate files in different packages:

example/other/StyleProp.scala:

package example.other
import example.StyleBuilder

class StyleProp(val name: String) extends StyleBuilder {
  override protected def builder(value: String): String = value
}

example/Example.scala:

package example

import example.other.StyleProp

trait StyleBuilder {
  protected def builder(value: String): String
}

trait AutoStyle extends StyleBuilder { // this: StyleProp =>
  lazy val auto: String = builder("auto")
}

// Usage:
object AutoStyle {
  val width = new StyleProp("width") with AutoStyle
  assert(AutoStyle.width.auto == "auto")
}

Output

The code above compiles ok as-written, as expected.

However, if you uncomment the self-type constraintthis: StyleProp =>, then the code fails with:

[error] -- Error: .../src/main/scala/example/Example.scala:10:26
[error] 10 |  lazy val auto: String = builder("auto")
[error]    |                          ^^^^^^^
[error]    |illegal access to protected method builder in class StyleProp from trait AutoStyle

Changing class StyleProp(val name: String) to trait StyleProp(val name: String) avoids the error for some reason (in 3.3.7 and 3.7.1). However, note that after changing back from trait to class, you need to sbt clean to see the error again.

Also, perhaps a separate issue, but changing to trait StyleProp(val name: String) seems to crash the Scala.js part of the compiler in 3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY:

Click to expand [debug] [zinc] IncrementalCompile ----------- [debug] IncrementalCompile.incrementalCompile [debug] previous = Stamps for: 0 products, 0 sources, 0 libraries [debug] current source = Set(${BASE}/src/main/scala/example/Main.scala, ${BASE}/src/main/scala/example/HelloWorld.scala, ${BASE}/src/main/scala/example/Example.scala, ${BASE}/src/main/scala/example/other/StyleProp.scala, ${BASE}/src/main/scala/example/other/Direction.scala, ${BASE}/src/main/scala/example/other/EnumObj.scala) [debug] > initialChanges = InitialChanges(Changes(added = Set(${BASE}/src/main/scala/example/other/EnumObj.scala, ${BASE}/src/main/scala/example/HelloWorld.scala, ${BASE}/src/main/scala/example/other/Direction.scala, ${BASE}/src/main/scala/example/Example.scala, ${BASE}/src/main/scala/example/Main.scala, ${BASE}/src/main/scala/example/other/StyleProp.scala), removed = Set(), changed = Set(), unmodified = ...),Set(),Set(),API Changes: Set()) [debug] Full compilation, no sources in previous analysis. [debug] all 6 sources are invalidated [debug] Initial set of included nodes: [debug] Recompiling all sources: number of invalidated sources > 50.0 percent of all sources [debug] compilation cycle 1 [info] compiling 6 Scala sources to /Users/raquo/code/scala/test/target/scala-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/classes ... [debug] Returning already retrieved and compiled bridge: /Users/raquo/Library/Caches/Coursier/v1/https/repo.scala-lang.org/artifactory/maven-nightlies/org/scala-lang/scala3-sbt-bridge/3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/scala3-sbt-bridge-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY.jar. [debug] [zinc] Running cached compiler 2ff617dd for Scala Compiler version 3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY-git-6b3569d [debug] [zinc] The Scala compiler is invoked with: [debug] -scalajs [debug] -encoding [debug] utf-8 [debug] -deprecation [debug] -feature [debug] -classpath [debug] /Users/raquo/code/scala/test/target/scala-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/classes:/Users/raquo/Library/Caches/Coursier/v1/https/repo.scala-lang.org/artifactory/maven-nightlies/org/scala-lang/scala3-library_sjs1_3/3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/scala3-library_sjs1_3-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-library_2.13/1.17.0/scalajs-library_2.13-1.17.0.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-dom_sjs1_3/2.8.0/scalajs-dom_sjs1_3-2.8.0.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/com/raquo/laminar_sjs1_3/17.2.0/laminar_sjs1_3-17.2.0.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo.scala-lang.org/artifactory/maven-nightlies/org/scala-js/scalajs-scalalib_2.13_sjs1_3/3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/scalajs-scalalib_2.13_sjs1_3-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo.scala-lang.org/artifactory/maven-nightlies/org/scala-lang/scala-library/3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/scala-library-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-javalib/1.20.1/scalajs-javalib-1.20.1.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-js/scalajs-scalalib_2.13/2.13.13%2B1.17.0/scalajs-scalalib_2.13-2.13.13%2B1.17.0.jar:/Users/raquo/.ivy2/local/com.raquo/airstream_sjs1_3/17.2.0/jars/airstream_sjs1_3.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/com/raquo/ew_sjs1_3/0.2.0/ew_sjs1_3-0.2.0.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo.scala-lang.org/artifactory/maven-nightlies/org/scala-lang/scala3-library_3/3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/scala3-library_3-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY.jar:/Users/raquo/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/app/tulz/tuplez-full-light_sjs1_3/0.4.0/tuplez-full-light_sjs1_3-0.4.0.jar [error] ## Exception when compiling 6 sources to /Users/raquo/code/scala/test/target/scala-3.8.0-RC1-bin-20251030-6b3569d-NIGHTLY/classes [error] dotty.tools.dotc.core.TypeError$$anon$1: package scala.scalajs.js does not have a member method async [error] [error] [error] dotty.tools.dotc.core.TypeError$$anon$1: package scala.scalajs.js does not have a member method async

Expectation

There is previous discussion of protected methods vs self-types in #18245, however I believe my example here is (related, but) a different problem: AutoStyle extends StyleBuilder, thus we should have access to StyleBuilder's protected def builder inside AutoStyle. The additional StyleProp self-type should not be taking away this capability that was granted by direct inheritance.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions