-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Fix #8861: Avoid parameters when instantiating closure results #8867
Merged
Merged
Changes from 8 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
39b9011
Make widenInferred work correctly for wildcard bounds
odersky 5709160
Use widenInferred for computing result types of vals and defs
odersky 35d143f
Simplify widenRHS
odersky c4c1f65
Move line to where it is needed
odersky 57c4982
Check ownerchain lengths when instantiating type variables
odersky 4ad6460
Better packaging of nesting level checking
odersky 9dd3d5c
Add more explanations, and another test case
odersky 1a25020
Drop debug println
odersky 7822d19
Update compiler/src/dotty/tools/dotc/core/Types.scala
odersky 202d862
Fix doc comment for nestingLevel
odersky e97b278
Fix nestingLevel so that it works for NoDenotation
odersky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
object Test { | ||
sealed trait Container { s => | ||
type A | ||
def visit[R](int: IntV & s.type => R, str: StrV & s.type => R): R | ||
} | ||
final class IntV extends Container { s => | ||
type A = Int | ||
val i: Int = 42 | ||
def visit[R](int: IntV & s.type => R, str: StrV & s.type => R): R = int(this) | ||
} | ||
final class StrV extends Container { s => | ||
type A = String | ||
val t: String = "hello" | ||
def visit[R](int: IntV & s.type => R, str: StrV & s.type => R): R = str(this) | ||
} | ||
|
||
def minimalOk[R](c: Container { type A = R }): R = c.visit[R]( | ||
int = vi => vi.i : vi.A, | ||
str = vs => vs.t : vs.A | ||
) | ||
def minimalFail[M](c: Container { type A = M }): M = c.visit( | ||
int = vi => vi.i : vi.A, | ||
str = vs => vs.t : vs.A // error | ||
) | ||
|
||
def main(args: Array[String]): Unit = { | ||
val e: Container { type A = String } = new StrV | ||
println(minimalOk(e)) // this one prints "hello" | ||
println(minimalFail(e)) // this one fails with ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
trait S { type N; def n: N } | ||
|
||
def newS[X](n: X): S { type N = X } = ??? | ||
|
||
def test = | ||
val ss: List[S] = ??? | ||
val cl1 = (s: S) => newS(s.n) | ||
val cl2: (s: S) => S { type N = s.N } = cl1 | ||
def f[R](cl: (s: S) => R) = cl | ||
val x = f(s => newS(s.n)) | ||
val x1: (s: S) => S = x | ||
// If the code in `tptProto` of Namer that refers to this | ||
// file is commented out, we see: | ||
// pickling difference for the result type of the closure argument | ||
// before pickling: S => S { type N = s.N } | ||
// after pickling : (s: S) => S { type N = s.N } | ||
|
||
ss.map(s => newS(s.n)) | ||
// If the code in `tptProto` of Namer that refers to this | ||
// file is commented out, we see a pickling difference like the one above. | ||
|
||
def g[R](cl: (s: S) => (S { type N = s.N }, R)) = ??? | ||
g(s => (newS(s.n), identity(1))) | ||
|
||
def h(cl: (s: S) => S { type N = s.N }) = ??? | ||
h(s => newS(s.n)) | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation of this method is inaccurate currently: NoSymbol.nestingLevel crashes because it has no owner:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was preferable to change the comment instead. So,
nestingLevel
of root is 0, and it's undefined for NoSymbol. We don't need it for NoSymbol, and the code is simpler that way.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In TypeVar#avoidCaptures we call
ref.symbol.maybeOwner.nestingLevel
, I think this will crash if ref happens to be a reference to a member of a structural type.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, ClassDenotation#nestingLevel does check if the owner exists, is that difference intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it more, the case of structural type member is interesting: it seems that their level should be the level of their underlying type, but then that means
nestingLevel
should be defined onType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, TypeVar#avoidCaptures only looks for TermRefs, and I think these TermRefs can never be structural members because a reference to such a member is never a stable path. So I think the current implementation is OK, but it's something to watch out for if Typevar#avoidCaptures is extended to do more checks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed
nestingLevel
to work forNoDenotation
as well. Structural type members would not have the formTermRef(NoPrefix, _)
, so we do not check their nestingLevel. It's true that we might also have to extend this to type members. That's part of #8900.