-
Notifications
You must be signed in to change notification settings - Fork 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
[WIP] Context Bounds for Polymorphic Functions #21643
base: main
Are you sure you want to change the base?
[WIP] Context Bounds for Polymorphic Functions #21643
Conversation
@odersky Could you take a look and see if there is something fundamentally wrong with this approach? On a slightly different note: |
@@ -1717,7 +1717,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer | |||
typedFunctionType(desugar.makeFunctionWithValDefs(tree, pt), pt) | |||
else | |||
val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure) | |||
val result = typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funSym.typeRef), args :+ body), pt) | |||
val args1 = args.mapConserve { | |||
case cb: untpd.ContextBoundTypeTree => typed(cb) |
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 think that won't do anything since args1
gets typed below as a list of untyped type trees. So typing it here beforehand should be redundant.
@@ -1926,8 +1930,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer | |||
|
|||
def typedPolyFunction(tree: untpd.PolyFunction, pt: Type)(using Context): Tree = | |||
val tree1 = desugar.normalizePolyFunction(tree) | |||
if (ctx.mode is Mode.Type) typed(desugar.makePolyFunctionType(tree1), pt) | |||
else typedPolyFunctionValue(tree1, pt) | |||
val tree2 = if Feature.enabled(Feature.modularity) then desugar.expandPolyFunctionContextBounds(tree1) |
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.
maybe roll expandPolyFunctionContextBounds
into normalizePolyFunction
?
|
||
val less8 = [X: {Ord, Show as show}] => (x: X, y: X) => summon[Ord[X]].compare(x, y) < 0 | ||
|
||
val less9 = [X: {Ord as ord, Show as show}] => (x: X, y: X) => ord.compare(x, y) < 0 |
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.
We should have tests that compare these polyfunction values with their expected types. E.g.
val _: [X: {Ord as ord, Show}] => (x: X, y: X) => Boolean = less7
Also we should have use aliases in some parts of these types and see whether it still works.
/** Desugar [T_1 : B_1, ..., T_N : B_N] => (P_1, ..., P_M) => R | ||
* Into [T_1, ..., T_N] => (P_1, ..., P_M) => (B_1, ..., B_N) ?=> R | ||
*/ | ||
def expandPolyFunctionContextBounds(tree: PolyFunction)(using Context): PolyFunction = |
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 was wondering whether we could re-use some of the code that desugars context bounds in methods. But maybe not. In any case, need to check that all applicable cases there are also present here.
About aliases: type Cmp[X] = (x: X, y: X) => Ord[X] ?=> Boolean
type Comparer2 = [X: Ord] => Cmp[X] The tricky part is, say you have val f = [X; Ord] => (x: X, y: X) => Ord[X] ?=> true Does |
Also, we don't need to put this modularity anymore since SIP 64 got accepted. |
@odersky I'm not entirely sure that I understand your aliases example. e.g. [X: Ord] => (x: X, y: X) => Ord[X] ?=> Boolean
===>(desugar)
[X] => (x: X, y: X) => ?=> Ord[X] => Ord[X] ?=> Boolean
===>(normalize)
[X] => (x: X, y: X) => => Ord[X] ?=> Boolean |
Well, does |
It doesn't hold now. I'll try moving the expansion later, to be able to use some type info then. |
…ns to reuse some of the existing context bound expansion
Implement the
#6
point form SIP-64 i.e.6. Context Bounds for Polymorphic Functions
Currently, context bounds can be used in methods, but not in function types or function literals. It would be nice propose to drop this irregularity and allow context bounds also in these places. Example:
The expansion of such context bounds is analogous to the expansion in method types, except that instead of adding a using clause in a method, we insert a context function type.
For instance, the
type
andval
definitions above would expand toThe expansion of using clauses does look inside alias types. For instance,
here is a variation of the previous example that uses a parameterized type alias:
The expansion of the right hand side of
Comparer2
expands theCmp[X]
aliasand then inserts the context function at the same place as what's done for
Comparer
.Open questions:
[X: Ord] => Cmp[X]
be accepted as a correct poly function, since it eventually will have term parameters?Currently missing: