-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Replace ShortcutImplicits #8386
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
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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
145 changes: 145 additions & 0 deletions
145
compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala
This file contains hidden or 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,145 @@ | ||
package dotty.tools | ||
package dotc | ||
package transform | ||
|
||
import core._ | ||
import Contexts._, Symbols._, Types._, Annotations._, Constants._ | ||
import StdNames.nme | ||
import ast.untpd | ||
import ast.tpd._ | ||
import config.Config | ||
|
||
object ContextFunctionResults: | ||
|
||
/** Annotate methods that have context function result types directly matched by context | ||
* closures on their right-hand side. Parameters to such closures will be integrated | ||
* as additional method parameters in erasure. | ||
*/ | ||
def annotateContextResults(mdef: DefDef)(using Context): Unit = | ||
def contextResultCount(rhs: Tree, tp: Type): Int = tp match | ||
case defn.ContextFunctionType(_, resTpe, _) => | ||
rhs match | ||
case closureDef(meth) => 1 + contextResultCount(meth.rhs, resTpe) | ||
case _ => 0 | ||
case _ => 0 | ||
|
||
val meth = mdef.symbol | ||
|
||
// Disable context result annotations for anonymous functions | ||
// and for implementations of PolyFunction | ||
def disabled = | ||
meth.isAnonymousFunction | ||
|| meth.name == nme.apply | ||
&& meth.owner.isAnonymousClass | ||
&& meth.owner.info.parents.exists(_.isRef(defn.PolyFunctionClass)) | ||
|
||
val count = contextResultCount(mdef.rhs, mdef.tpt.tpe) | ||
|
||
if Config.flattenContextFunctionResults && count != 0 && !disabled then | ||
val countAnnot = Annotation(defn.ContextResultCountAnnot, Literal(Constant(count))) | ||
mdef.symbol.addAnnotation(countAnnot) | ||
end annotateContextResults | ||
|
||
/** The argument of a ContextResultCount annotation, or 0 if none exists. | ||
* See PostTyper#annotateContextResults. | ||
*/ | ||
def contextResultCount(sym: Symbol)(using Context): Int = | ||
sym.getAnnotation(defn.ContextResultCountAnnot) match | ||
case Some(annot) => | ||
val ast.Trees.Literal(Constant(crCount: Int)) :: Nil: @unchecked = annot.arguments | ||
crCount | ||
case none => 0 | ||
|
||
/** Turn the first `crCount` context function types in the result type of `tp` | ||
* into the curried method types. | ||
*/ | ||
def integrateContextResults(tp: Type, crCount: Int)(using Context): Type = | ||
if crCount == 0 then tp | ||
else tp match | ||
case ExprType(rt) => | ||
integrateContextResults(rt, crCount) | ||
case tp: MethodOrPoly => | ||
tp.derivedLambdaType(resType = integrateContextResults(tp.resType, crCount)) | ||
case defn.ContextFunctionType(argTypes, resType, isErased) => | ||
val methodType: MethodTypeCompanion = | ||
if isErased then ErasedMethodType else MethodType | ||
methodType(argTypes, integrateContextResults(resType, crCount - 1)) | ||
|
||
/** The total number of parameters of method `sym`, not counting | ||
* erased parameters, but including context result parameters. | ||
*/ | ||
def totalParamCount(sym: Symbol)(using Context): Int = | ||
|
||
def contextParamCount(tp: Type, crCount: Int): Int = | ||
if crCount == 0 then 0 | ||
else | ||
val defn.ContextFunctionType(params, resTpe, isErased): @unchecked = tp | ||
val rest = contextParamCount(resTpe, crCount - 1) | ||
if isErased then rest else params.length + rest | ||
|
||
def normalParamCount(tp: Type): Int = tp.widenExpr.stripPoly match | ||
case mt @ MethodType(pnames) => | ||
val rest = normalParamCount(mt.resType) | ||
if mt.isErasedMethod then rest else pnames.length + rest | ||
case _ => contextParamCount(tp, contextResultCount(sym)) | ||
|
||
normalParamCount(sym.info) | ||
end totalParamCount | ||
|
||
/** The rightmost context function type in the result type of `meth` | ||
* that represents `paramCount` curried, non-erased parameters that | ||
* are included in the `contextResultCount` of `meth`. | ||
* Example: | ||
* | ||
* Say we have `def m(x: A): B ?=> (C1, C2, C3) ?=> D ?=> E ?=> F`, | ||
* paramCount == 4, and the contextResultCount of `m` is 3. | ||
* Then we return the type `(C1, C2, C3) ?=> D ?=> E ?=> F`, since this | ||
* type covers the 4 rightmost parameters C1, C2, C3 and D before the | ||
* contextResultCount runs out at E ?=> F. | ||
* Erased parameters are ignored; they contribute nothing to the | ||
* parameter count. | ||
*/ | ||
def contextFunctionResultTypeCovering(meth: Symbol, paramCount: Int)(using ctx: Context) = | ||
given Context = ctx.withPhase(ctx.erasurePhase) | ||
|
||
// Recursive instances return pairs of context types and the | ||
// # of parameters they represent. | ||
def missingCR(tp: Type, crCount: Int): (Type, Int) = | ||
if crCount == 0 then (tp, 0) | ||
else | ||
val defn.ContextFunctionType(formals, resTpe, isErased): @unchecked = tp | ||
val result @ (rt, nparams) = missingCR(resTpe, crCount - 1) | ||
assert(nparams <= paramCount) | ||
if nparams == paramCount || isErased then result | ||
else (tp, nparams + formals.length) | ||
missingCR(meth.info.finalResultType, contextResultCount(meth))._1 | ||
end contextFunctionResultTypeCovering | ||
|
||
/** Should selection `tree` be eliminated since it refers to an `apply` | ||
* node of a context function type whose parameters will end up being | ||
* integrated in the preceding method? | ||
* @param `n` the select nodes seen in previous recursive iterations of this method | ||
*/ | ||
def integrateSelect(tree: untpd.Tree, n: Int = 0)(using ctx: Context): Boolean = | ||
if ctx.erasedTypes then | ||
integrateSelect(tree, n)(using ctx.withPhase(ctx.erasurePhase)) | ||
else tree match | ||
case Select(qual, name) => | ||
if name == nme.apply && defn.isContextFunctionClass(tree.symbol.maybeOwner) then | ||
integrateSelect(qual, n + 1) | ||
else | ||
n > 0 && contextResultCount(tree.symbol) >= n | ||
case Ident(name) => | ||
n > 0 && contextResultCount(tree.symbol) >= n | ||
case Apply(fn, args) => | ||
integrateSelect(fn, n) | ||
case TypeApply(fn, _) => | ||
integrateSelect(fn, n) | ||
case Block(_, expr) => | ||
integrateSelect(expr, n) | ||
case Inlined(_, _, expr) => | ||
integrateSelect(expr, n) | ||
case _ => | ||
false | ||
|
||
end ContextFunctionResults |
Oops, something went wrong.
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.
I think this object belongs at
Types.scala
.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.
One can debate this. I put it next to
isContextFunctionType
andasContextFunctionType
, since it is related.