Skip to content

Parse classfile generic parameters defined in supertype generic signature#26317

Open
SolalPirelli wants to merge 3 commits into
scala:mainfrom
dotty-staging:solal/26312
Open

Parse classfile generic parameters defined in supertype generic signature#26317
SolalPirelli wants to merge 3 commits into
scala:mainfrom
dotty-staging:solal/26312

Conversation

@SolalPirelli

Copy link
Copy Markdown
Contributor

Fixes #26312

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

Not at all

How was the solution tested?

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

Comment thread tests/neg/26312.check
@@ -0,0 +1,10 @@
-- [E173] Reference Error: tests/neg/26312/Use_2.scala:3:16 ------------------------------------------------------------

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without this fix, there's a nopos-error "broken classfile"

@SolalPirelli SolalPirelli requested a review from prolativ June 11, 2026 13:17
@scala scala deleted a comment from SolalPirelli Jun 12, 2026
// Warning: sigToType contains nested completers which might be forced in a later run!
// So local methods need their own ctx parameters.
def sig2type(tparams: immutable.Map[Name, Symbol], skiptvs: Boolean)(using Context): Type = {
def sig2type(tparams: immutable.Map[Name, Symbol], skiptvs: Boolean, isParent: Boolean = false)(using Context): Type = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just going to complain that the unfortunate thing about moving the definition of var tparams is that now var tparams is slightly more likely to be confused with tparams parameter of the methods sig2type and sig2typeBounds. Just after that I asked Claude for some help with the review and it spotted a different problem:

Consider this Java:

////////

public class Wrapper<A, B> { }

class Outer {
    public <Oth> Wrapper<Oth, Oth> make() {
        return new Wrapper<Oth, Oth>() { };  // anonymous class Outer$1
    }
}

////////

Outer$1's classfile signature would be something like:

LWrapper<TOth;TOth;>;

When the parser hits the 'L' case for Wrapper and enters processTypeArgs, it loops over the two type arguments calling sig2type(tparams, skiptvs, isParent) for each:

// First iteration: index at TOth;
sig2type(...) → tparams.get("Oth") == None → creates symbol S1, adds to classTParams

// Second iteration: index at TOth; again
sig2type(...) → tparams.get("Oth") == None  ← still None, tparams unchanged
             → creates symbol S2, enters S2 into owner.asClass again

Both S1 and S2 get entered into the owner class's scope under the same name Oth. Whether this actually causes a problem depends on how owner.asClass.enter handles duplicate names — it may silently overwrite or accumulate both, potentially confusing later type-checking of that class.

Unless I missed something, getting rid of tparams parameter in favour of referencing the tparams variable directly combined with updating tparams as well when classTParams is updated with a new symbol below should solve both problems a the same time.

Also, probably it would be worth to add a test for handling such a duplicate type param reference

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I forgot about that.

I tried refactoring the tparams stuff but it's quite confusing and a simple attempt causes a couple tests to fail with clearly generic type parameters related stuff. What exactly the two tparams are supposed to mean isn't obvious.

So I added an orElse(classTParams.get(n)) here instead, which fixes the problem without broader repercussions.

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.

Classfile parser breaks on nested generics in dependency of community build

2 participants