Skip to content

Fixes #25702: Avoid AnyClass fallback in requiredClass#26010

Open
soronpo wants to merge 3 commits into
scala:mainfrom
soronpo:claude/fix-scala-25702-rP5cf
Open

Fixes #25702: Avoid AnyClass fallback in requiredClass#26010
soronpo wants to merge 3 commits into
scala:mainfrom
soronpo:claude/fix-scala-25702-rP5cf

Conversation

@soronpo
Copy link
Copy Markdown
Contributor

@soronpo soronpo commented May 8, 2026

When requiredClass lookup didn't resolve to a class (because an intermediate package was missing on the classpath, e.g. a stale scala3-library without scala.caps.internal), it returned defn.AnyClass. Two consequences:

  • param.hasAnnotation(missingAnnot) matched for every annotation (every annotation derives from Any), and
  • the subsequent Annotation(missingAnnot, span) -> tpd.New crashed with assertion failed: asTerm called on not-a-Term val <none> because AnyClass has no primary constructor.

Return a fresh stub class with the requested name instead. Adds a unit test for the new behavior plus a neg regression test guarding the surrounding "missing-method" diagnostic.

Fixes #25702

How much have you relied on LLM-based tools in this contribution?

Extensively, but it's a small fix.

How was the solution tested?

New automated tests (including the issue's reproducer, if applicable)

claude added 3 commits May 8, 2026 13:52
When `requiredClass` lookup didn't resolve to a class (because an
intermediate package was missing on the classpath, e.g. a stale
`scala3-library` without `scala.caps.internal`), it returned
`defn.AnyClass`. Two consequences:

- `param.hasAnnotation(missingAnnot)` matched for every annotation
  (every annotation derives from `Any`), and
- the subsequent `Annotation(missingAnnot, span)` -> `tpd.New` crashed
  with `assertion failed: asTerm called on not-a-Term val <none>`
  because `AnyClass` has no primary constructor.

Return a fresh stub class with the requested name instead. Adds a
unit test for the new behavior plus a `neg` regression test guarding
the surrounding "missing-method" diagnostic.

https://claude.ai/code/session_01YbGL1r2aekT7qSTxtaQ4M8
The previous fix used a stub class as the fallback for *any* non-class
result of `requiredClass`, but that broke `requiredClass("scala.AnyRef")`
and `requiredClass("scala.EmptyTuple")` (and other type aliases): those
paths resolve to a real `TypeSymbol`, and downstream tests
(`tests/run-macros/requiredSymbols`, `i12417`, `i17257`,
`expr-mirror-info`, ...) relied on the historical `defn.AnyClass`
fallback for that case.

Restrict the new stub-class fallback to the case where `staticRef` itself
returns `MissingRef` — i.e. the path doesn't resolve at all. For paths
that resolve to a non-class symbol, keep the original `defn.AnyClass`
fallback. Update the unit test accordingly.

https://claude.ai/code/session_01YbGL1r2aekT7qSTxtaQ4M8
The previous attempts changed `requiredClass` to return a stub class
when the path didn't resolve, but every variant broke a different set
of callers — notably the Java `ClassfileParser` (which forces the
fallback symbol's owner chain in `innerType` and crashes on `NoSymbol`),
and macro tests that rely on `requiredClass("scala.AnyRef")` /
`requiredClass("scala.EmptyTuple")` returning `defn.AnyClass`.

Restore `requiredClass` to its original form and instead guard the
actual crash site: in `Types.MethodTypeCompanion.adaptParamInfo`, skip
the `param.hasAnnotation(cls)` check when `cls eq defn.AnyClass`. That
fallback means the annotation class wasn't found on the classpath; if
we let the check run, it would match every annotation (since they all
derive from `Any`) and then crash in `tpd.New` because `AnyClass` has
no primary constructor.

The unit test added previously asserted the now-reverted `requiredClass`
behaviour, so it's removed; `tests/neg/i25702.scala` keeps the
"missing-method" diagnostic from regressing.

https://claude.ai/code/session_01YbGL1r2aekT7qSTxtaQ4M8
@soronpo soronpo marked this pull request as ready for review May 8, 2026 20:52
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.

Compiler crash with assertion failed: asTerm called on not-a-Term val <none>

2 participants