Skip to content

fix: erase unresolved generic field type to its bound in field-get assign - #2888

Open
obus-globus wants to merge 1 commit into
skylot:masterfrom
obus-globus:fix/raw-generic-field-erase
Open

fix: erase unresolved generic field type to its bound in field-get assign#2888
obus-globus wants to merge 1 commit into
skylot:masterfrom
obus-globus:fix/raw-generic-field-erase

Conversation

@obus-globus

Copy link
Copy Markdown
Contributor

NOTE: This is what one may call "AI slop". Feel free to close this PR if it's not up to your quality standards or even if you just aren't interested in reviewing it. I use these changes downstream on an APK and thought I might as well make a PR offering to upstream them, as your CONTRIBUTING.md doesn't say anything discouraging this.

Description

Reading a generic field through a raw instance type and null-checking it emitted == 0 instead of == null (with a type inference failed warning), for both a type-variable field (T) and arrays of one (T[]).

When the field's type variable can't be resolved from the raw instance type, getResultType returned it unchanged, leaving an out-of-scope type variable that type propagation rejects, so the compared 0 literal kept its unknown type. Erase the unresolved variable to its leftmost bound (like javac), arrays element-wise, falling back to Object when unbounded or when the bound is itself a type variable. This mirrors the extend-type handling in FixTypesVisitor, rather than the straight-to-Object erasure in checkRawType, so a T extends Number field stays usable as a Number.

Includes an integration test.

Fixes #2886

}

private ArgType getResultType(ArgType instanceType) {
ArgType resultGeneric = root.getTypeUtils().replaceClassGenerics(instanceType, initType);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Support for missing generic types (raw and wildcard (<?>)) should be done inside TypeUtils.replaceClassGenerics method.
This will resolve many other issues and not only with field types.
But such task can be hard one, you can try to solve it, I also will try to look into this.

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.

Agreed, replaceClassGenerics is the right home for this in general.

I tried it there (erase to the declared bound when a variable can't be resolved from the instance), but it regresses TestTypeResolver12: a null return there can't tell the class's own in-scope T (WeakReference<T> read inside TestCls<T>, must stay T) from an out-of-scope raw-instance variable that should be erased, so erasing both breaks multi-variable inference. The field-get bound has that context; replaceClassGenerics doesn't.

Not sure how to continue here, let me know if you need something.

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.

[core] generic field read through a raw type is compared to 0 instead of null

2 participants