Skip to content

Map context bounds to context parameters #8055

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

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
bef5da3
Revert "Convert more conditional given instances to new syntax"
odersky Jan 16, 2020
31c9f08
Revert "Tweak syntax of conditions in given instances"
odersky Jan 16, 2020
dd6b326
Revert "Fix #7788: Add new syntax for conditional given instances"
odersky Jan 16, 2020
ff4c2e0
Go back to `given ... as` for instances
odersky Jan 16, 2020
15df4a2
Update semanticDb check files
odersky Jan 16, 2020
d95fd15
Change to ?=> for context functions
odersky Jan 17, 2020
594c9d6
Use `with` for context parameters
odersky Jan 17, 2020
ec853d1
Adapt printing of context functions to new syntax
odersky Jan 17, 2020
ff90919
Switch to `with` syntax for context parameters
odersky Jan 18, 2020
fc76dc8
Specify and describe new indentation rules
odersky Jan 18, 2020
d7c67bd
Adapt printing of context parameters and arguments to new syntax
odersky Jan 18, 2020
7561634
More indentation doc changes
odersky Jan 18, 2020
3e993d0
Restore blog post to original form
odersky Jan 18, 2020
aeabb14
Restore currently valid doc pages to original form
odersky Jan 18, 2020
6005868
Update docs to `given` ... `with` syntax
odersky Jan 18, 2020
80a5b71
Update comment on tooling
odersky Jan 18, 2020
f9e20cf
Some doc fixes
odersky Jan 19, 2020
398c8ce
Imlement new import seclectors for givens
odersky Jan 19, 2020
2ff0b4c
Fix typo
odersky Jan 20, 2020
ca5c8ae
Allow normal parameter clauses after context parameters.
odersky Jan 20, 2020
5fca977
Doc fixes
odersky Jan 21, 2020
9b34638
Map context bounds to context parameters
odersky Jan 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,10 @@ object desugar {
val epbuf = ListBuffer[ValDef]()
def desugarContextBounds(rhs: Tree): Tree = rhs match {
case ContextBounds(tbounds, cxbounds) =>
epbuf ++= makeImplicitParameters(cxbounds, Implicit, forPrimaryConstructor = isPrimaryConstructor)
val iflag = cxbounds match
case (_: untpd.Function) :: Nil => Implicit // it's a view bound
case _ => Given
epbuf ++= makeImplicitParameters(cxbounds, iflag, forPrimaryConstructor = isPrimaryConstructor)
tbounds
case LambdaTypeTree(tparams, body) =>
cpy.LambdaTypeTree(rhs)(tparams, desugarContextBounds(body))
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def makeAndType(left: Tree, right: Tree)(implicit ctx: Context): AppliedTypeTree =
AppliedTypeTree(ref(defn.andType.typeRef), left :: right :: Nil)

def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = EmptyModifiers, isBackquoted: Boolean = false)(implicit ctx: Context): ValDef = {
def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers, isBackquoted: Boolean = false)(implicit ctx: Context): ValDef = {
val vdef = ValDef(pname, tpe, EmptyTree)
if (isBackquoted) vdef.pushAttachment(Backquoted, ())
vdef.withMods(mods | Param)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ object StdNames {
val array_length : N = "array_length"
val array_update : N = "array_update"
val arraycopy: N = "arraycopy"
val as: N = "as"
val asTerm: N = "asTerm"
val asModule: N = "asModule"
val asMethod: N = "asMethod"
Expand Down
247 changes: 127 additions & 120 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,11 @@ object Scanners {
this.copyFrom(prev)
}

/** - Join CASE + CLASS => CASECLASS, CASE + OBJECT => CASEOBJECT, SEMI + ELSE => ELSE, COLON + <EOL> => COLONEOL
/** - Join CASE + CLASS => CASECLASS,
* CASE + OBJECT => CASEOBJECT,
* SEMI + ELSE => ELSE,
* COLON + <EOL> => COLONEOL
* DOT + WITH => DOTWITH
* - Insert missing OUTDENTs at EOF
*/
def postProcessToken(): Unit = {
Expand All @@ -619,6 +623,10 @@ object Scanners {
} else if (token == EOF) { // e.g. when the REPL is parsing "val List(x, y, _*,"
/* skip the trailing comma */
} else reset()
case DOT =>
lookahead()
if token == WITH then fuse(DOTWITH)
else reset()
case COLON =>
if colonSyntax then observeColonEOL()
case EOF | RBRACE =>
Expand Down Expand Up @@ -1301,8 +1309,8 @@ object Scanners {

override def toString: String =
showTokenDetailed(token) + {
if identifierTokens.contains(token) then name
else if literalTokens.contains(token) then strVal
if identifierTokens.contains(token) then s" $name"
else if literalTokens.contains(token) then s" $strVal"
else ""
}

Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Tokens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ object Tokens extends TokensCommon {
/** special symbols */
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
final val NEWLINES = 79; enter(NEWLINES, "end of statement", "new lines")
final val COLONEOL = 88; enter(COLONEOL, ":", ": at eol")

/** special keywords */
final val USCORE = 73; enter(USCORE, "_")
Expand All @@ -200,14 +199,18 @@ object Tokens extends TokensCommon {
final val HASH = 82; enter(HASH, "#")
final val VIEWBOUND = 84; enter(VIEWBOUND, "<%")
final val TLARROW = 85; enter(TLARROW, "=>>")
final val CTXARROW = 86; enter(CTXARROW, "?=>")

final val QUOTE = 87; enter(QUOTE, "'")

final val QUOTE = 86; enter(QUOTE, "'")
final val COLONEOL = 88; enter(COLONEOL, ":", ": at eol")
final val DOTWITH = 89; enter(DOTWITH, ".with")

/** XML mode */
final val XMLSTART = 98; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate

final val alphaKeywords: TokenSet = tokenRange(IF, MACRO)
final val symbolicKeywords: TokenSet = tokenRange(USCORE, TLARROW)
final val symbolicKeywords: TokenSet = tokenRange(USCORE, CTXARROW)
final val keywords: TokenSet = alphaKeywords | symbolicKeywords

final val allTokens: TokenSet = tokenRange(minToken, maxToken)
Expand Down
22 changes: 11 additions & 11 deletions compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
else simpleNameString(tsym)
}

private def arrow(isGiven: Boolean): String =
if isGiven then "?=>" else "=>"

override def toText(tp: Type): Text = controlled {
def toTextTuple(args: List[Type]): Text =
"(" ~ argsText(args) ~ ")"
Expand All @@ -145,19 +148,19 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
atPrec(InfixPrec) { argText(args.head) }
else
"("
~ keywordText("given ").provided(isGiven)
~ keywordText("erased ").provided(isErased)
~ argsText(args.init)
~ ")"
argStr ~ " => " ~ argText(args.last)
argStr ~ " " ~ arrow(isGiven) ~ " " ~ argText(args.last)
}

def toTextDependentFunction(appType: MethodType): Text =
"("
~ keywordText("given ").provided(appType.isImplicitMethod)
~ keywordText("erased ").provided(appType.isErasedMethod)
~ paramsText(appType)
~ ") => "
~ ") "
~ arrow(appType.isImplicitMethod)
~ " "
~ toText(appType.resultType)

def isInfixType(tp: Type): Boolean = tp match {
Expand Down Expand Up @@ -386,8 +389,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
keywordStr("${") ~ toTextGlobal(args, ", ") ~ keywordStr("}")
else
toTextLocal(fun)
~ ("." ~ keywordText("with")).provided(app.isGivenApply && !homogenizedView)
~ "("
~ keywordText("given ").provided(app.isGivenApply && !homogenizedView)
~ toTextGlobal(args, ", ")
~ ")"
case tree: TypeApply =>
Expand Down Expand Up @@ -577,12 +580,11 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case (arg @ ValDef(_, tpt, _)) :: Nil if tpt.isEmpty => argToText(arg)
case _ =>
"("
~ keywordText("given ").provided(isGiven)
~ keywordText("erased ").provided(isErased)
~ Text(args.map(argToText), ", ")
~ ")"
}
argsText ~ " => " ~ toText(body)
argsText ~ " " ~ arrow(isGiven) ~ " " ~ toText(body)
case PolyFunction(targs, body) =>
val targsText = "[" ~ Text(targs.map((arg: Tree) => toText(arg)), ", ") ~ "]"
changePrec(GlobalPrec) {
Expand Down Expand Up @@ -770,10 +772,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}

private def paramsText[T>: Untyped](params: List[ValDef[T]]) =
"("
~ keywordText("given ").provided(params.nonEmpty && params.head.mods.is(Given))
~ toText(params, ", ")
~ ")"
keywordText(" with ").provided(params.nonEmpty && params.head.mods.is(Given))
~ "(" ~ toText(params, ", ") ~ ")"

protected def defDefToText[T >: Untyped](tree: DefDef[T]): Text = {
import untpd.{modsDeco => _}
Expand Down
12 changes: 11 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2650,7 +2650,17 @@ class Typer extends Namer
else
tree
else if (wtp.isContextualMethod)
adaptNoArgs(wtp) // insert arguments implicitly
def isContextBoundParams = wtp.stripPoly match
case MethodType(EvidenceParamName(_) :: _) => true
case _ => false
if ctx.scala2CompatMode && isContextBoundParams then
ctx.migrationWarning(
em"""Context bounds will map to context parameters.
|A `with` clause is needed to pass explicit arguments to them""", tree.sourcePos)
patch(Span(tree.span.end), ".with")
tree
else
adaptNoArgs(wtp) // insert arguments implicitly
else if (tree.symbol.isPrimaryConstructor && tree.symbol.info.firstParamTypes.isEmpty)
readapt(tree.appliedToNone) // insert () to primary constructors
else
Expand Down
2 changes: 1 addition & 1 deletion compiler/test-resources/repl/3932
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
scala> def fun[T](x: T): (given List[T]) => Int = ???
def fun[T](x: T): (given List[T]) => Int
def fun[T](x: T): (List[T]) ?=> Int
Loading