Skip to content

Fix named-tuple pattern resolution under -Yexplicit-nulls#26233

Open
HarrisL2 wants to merge 1 commit into
scala:mainfrom
HarrisL2:named-tuple-explicit-null
Open

Fix named-tuple pattern resolution under -Yexplicit-nulls#26233
HarrisL2 wants to merge 1 commit into
scala:mainfrom
HarrisL2:named-tuple-explicit-null

Conversation

@HarrisL2
Copy link
Copy Markdown
Contributor

@HarrisL2 HarrisL2 commented Jun 4, 2026

Issue minimized from a run of the open community build with explicit nulls enabled by default from #25461

A named-tuple pattern fails to compile under -Yexplicit-nulls when the scrutinee comes from a Java-defined generic (e.g. java.util.stream.Stream), even though the identical code compiles without the flag. This PR strips nullability from the expected type before desugaring such patterns, scoped to named-tuple patterns only.

Reproduction

import java.util.stream.{Stream => JStream}

class Store
class OriginalPath

object Test:
  type SearchRootResult = (searchRoot: Store, originalPath: OriginalPath)

  def test(stream: JStream[SearchRootResult]): JStream[SearchRootResult] =
    stream.filter { case (searchRoot = sr) => sr.isInstanceOf[Store] }

Run with scalac Test.scala -Yexplicit-nulls

Fix

In Typer.typedTuple, strip nullability from the expected type before desugaring, but only for patterns that actually carry named elements:

  val pt =
    if ctx.mode.is(Mode.Pattern) && hasNamedArg(tree.trees)
    then pt0.stripNull()
    else pt0

I had a back and forth with the LLM for a justification:

Why unwrapping is sound

The change makes a local pt = pt0.stripNull() inside typedTuple, used only to desugar/type the pattern's sub-trees. A tuple pattern lowers to an unapply guarded by a non-null test:

// PatternMatcher.scala:496-497
if (scrutinee.info.isNotNull || nonNull(scrutinee)) unappPlan
else TestPlan(NonNullTest, scrutinee, ...)   // scrutinee ne null

So the bindings (sr) only ever run on non-null values.

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

Moderately, for generating a fix and the explanation

How was the solution tested?

New automated tests

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.

1 participant