Skip to content

Fix #10888: Avoid A.this.B for Java inner classes #11006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 15, 2021

Conversation

liufengyun
Copy link
Contributor

Fix #10888: Avoid A.this.B for Java inner classes

For Java inner classes, we should use A#B instead of A.this.B.

Co-authored-by: Guillaume Martres [email protected]

@liufengyun liufengyun force-pushed the fix-10888 branch 3 times, most recently from c4508d5 to a6eb9f8 Compare January 7, 2021 14:35
@liufengyun
Copy link
Contributor Author

@smarter Could you have a look at the last commit? It took a while to find out the root cause.

// not a `JavaArrayType`.

val annot = atPhase(erasurePhase.next) { cls.getAnnotation(annotCls) }
val arg = annot.get.argument(0).get
Copy link
Member

Choose a reason for hiding this comment

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

It's important to run this line at erasure, otherwise we're not forcing the annotation tree at the erasure phase. But also, why is this test suddenly failing after the change you made? They don't seem related at all, and based on the comment you added I would expect it to fail before too. If you're not sure what's going on let me know and I can try to have a look.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know why it's not failing before. But the subtyping trace and debugging tells that Array[String] =:= Array[String] is false after erasure due to the cause in the commit message. Just running the subtyping in an early phase is enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@smarter: I've just updated the code so that we only do subtyping test before erasure. If it's green, then please have a look if you have clue why it's not failing before.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From the investigation so far, the changes in ClassfileParser have changed subtyping path for Array[String] <:< Array[String].

Previously, it does not touch the line TypeComparer.compareAppliedType2, now it reaches that line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After some further investigation, we know why it accidentally works before: before the change the two Array[String] and Array[String] point to the same object, thus they go through the short-cut tp1 eq tp2 in TypeComparer, thus never reaches the line TypeComparer.compareAppliedType2.

The changes in ClassfileParser somehow changes the caching behavior.

liufengyun and others added 2 commits February 15, 2021 14:59
For Java inner classes, we should use `A#B` instead of `A.this.B`.

Co-authored-by: Guillaume Martres <[email protected]>
We have the following subtyping result:

```scala
 Subtype trace:
    ==> Array#262[String#810] <:< Array#262[String#810]
	==> Array#262[String#810] <:< Array#262[String#810] recur
	<== Array#262[String#810] <:< Array#262[String#810] recur  = false
    <== Array#262[String#810] <:< Array#262[String#810]   = false
```

In `TypeComparer.compareAppliedType2`, the method just returns false
because `typcon2.typeParams` is empty:

```
  def compareAppliedType2(tp2: AppliedType, tycon2: Type, args2: List[Type]): Boolean = {
    val tparams = tycon2.typeParams
    if (tparams.isEmpty) return false
```

The reason why `ftypcon1.typeParams` is empty is because we are
running the subtyping check after erasure. The following code works
without any problem:

```scala
  atPhase(typerPhase) { arrayOfString =:= arg.tpe }
```

Before the change the two `Array[String]` and `Array[String]` point to
the same object, thus they go through the short-cut `tp1 eq tp2` in
`TypeComparer`, thus never reaches the line
`TypeComparer.compareAppliedType2`.
smarter
smarter previously approved these changes Feb 15, 2021
Copy link
Member

@smarter smarter left a comment

Choose a reason for hiding this comment

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

Thanks for looking into it, makes sense, LGTM!

@smarter
Copy link
Member

smarter commented Feb 15, 2021

Oh, looks like there's a failed test:

-- [E007] Type Mismatch Error: tests/pos/i5655/S_2.scala:4:41 ----------------------------------------------------------
4 |    val ab: J_1#A[String]#B[String] = j.m()
Compilation failed for: 'tests/pos/i5655'                                       
  |                                      ^^^^^
  |                                      Found:    J_1#A[?]#B[String]
  |                                      Required: J_1#A[String]#B[String]

Corresponding PR is #5656

The commits 5cf9e0b incorrectly throw the prefix away
and construct the type from the symbol by ignoring
type parameters of generic classes.

As prefix is already in the "inner normal form",
it suffices to select member on it. The commit 22ab968
calls `processInner`, which is effectively an no-op.

Also found that we should reset `skiptvs` in reading
method parameter and result types.
@liufengyun liufengyun merged commit 2da2c0b into scala:master Feb 15, 2021
@liufengyun liufengyun deleted the fix-10888 branch February 15, 2021 19:16
@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 2023
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.

exception caught when loading class C: Cyclic reference involving class C
3 participants