Skip to content

Commit cf59585

Browse files
committed
Allow renamings as N in context bounds
1 parent 89e91ae commit cf59585

File tree

6 files changed

+48
-25
lines changed

6 files changed

+48
-25
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,16 +238,19 @@ object desugar {
238238
var useParamName = Feature.enabled(Feature.modularity)
239239
for bound <- cxbounds do
240240
val paramName =
241-
if useParamName then
242-
useParamName = false
243-
tparam.name.toTermName
244-
else
245-
seenContextBounds += 1 // Start at 1 like FreshNameCreator.
246-
ContextBoundParamName(EmptyTermName, seenContextBounds)
241+
bound match
242+
case ContextBoundTypeTree(_, _, ownName) if !ownName.isEmpty =>
243+
ownName
244+
case _ if useParamName =>
245+
tparam.name.toTermName
246+
case _ =>
247+
seenContextBounds += 1 // Start at 1 like FreshNameCreator.
248+
ContextBoundParamName(EmptyTermName, seenContextBounds)
247249
// Just like with `makeSyntheticParameter` on nameless parameters of
248250
// using clauses, we only need names that are unique among the
249251
// parameters of the method since shadowing does not affect
250252
// implicit resolution in Scala 3.
253+
useParamName = false
251254
val evidenceParam = ValDef(paramName, bound, EmptyTree).withFlags(flags)
252255
evidenceParam.pushAttachment(ContextBoundParam, ())
253256
evidenceParamBuf += evidenceParam

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
118118
case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @constructorOnly src: SourceFile) extends TypTree
119119
case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @constructorOnly src: SourceFile) extends DefTree
120120
case class ExtMethods(paramss: List[ParamClause], methods: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree
121-
case class ContextBoundTypeTree(tycon: Tree, paramName: TypeName)(implicit @constructorOnly src: SourceFile) extends Tree
121+
case class ContextBoundTypeTree(tycon: Tree, paramName: TypeName, ownName: TermName)(implicit @constructorOnly src: SourceFile) extends Tree
122122
case class MacroTree(expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree
123123

124124
case class ImportSelector(imported: Ident, renamed: Tree = EmptyTree, bound: Tree = EmptyTree)(implicit @constructorOnly src: SourceFile) extends Tree {
@@ -678,9 +678,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
678678
def ExtMethods(tree: Tree)(paramss: List[ParamClause], methods: List[Tree])(using Context): Tree = tree match
679679
case tree: ExtMethods if (paramss eq tree.paramss) && (methods == tree.methods) => tree
680680
case _ => finalize(tree, untpd.ExtMethods(paramss, methods)(tree.source))
681-
def ContextBoundTypeTree(tree: Tree)(tycon: Tree, paramName: TypeName)(using Context): Tree = tree match
682-
case tree: ContextBoundTypeTree if (tycon eq tree.tycon) && paramName == tree.paramName => tree
683-
case _ => finalize(tree, untpd.ContextBoundTypeTree(tycon, paramName)(tree.source))
681+
def ContextBoundTypeTree(tree: Tree)(tycon: Tree, paramName: TypeName, ownName: TermName)(using Context): Tree = tree match
682+
case tree: ContextBoundTypeTree if (tycon eq tree.tycon) && paramName == tree.paramName && ownName == tree.ownName => tree
683+
case _ => finalize(tree, untpd.ContextBoundTypeTree(tycon, paramName, ownName)(tree.source))
684684
def ImportSelector(tree: Tree)(imported: Ident, renamed: Tree, bound: Tree)(using Context): Tree = tree match {
685685
case tree: ImportSelector if (imported eq tree.imported) && (renamed eq tree.renamed) && (bound eq tree.bound) => tree
686686
case _ => finalize(tree, untpd.ImportSelector(imported, renamed, bound)(tree.source))
@@ -746,8 +746,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
746746
cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs))
747747
case ExtMethods(paramss, methods) =>
748748
cpy.ExtMethods(tree)(transformParamss(paramss), transformSub(methods))
749-
case ContextBoundTypeTree(tycon, paramName) =>
750-
cpy.ContextBoundTypeTree(tree)(transform(tycon), paramName)
749+
case ContextBoundTypeTree(tycon, paramName, ownName) =>
750+
cpy.ContextBoundTypeTree(tree)(transform(tycon), paramName, ownName)
751751
case ImportSelector(imported, renamed, bound) =>
752752
cpy.ImportSelector(tree)(transformSub(imported), transform(renamed), transform(bound))
753753
case Number(_, _) | TypedSplice(_) =>
@@ -803,7 +803,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
803803
this(this(this(x, pats), tpt), rhs)
804804
case ExtMethods(paramss, methods) =>
805805
this(paramss.foldLeft(x)(apply), methods)
806-
case ContextBoundTypeTree(tycon, paramName) =>
806+
case ContextBoundTypeTree(tycon, paramName, ownName) =>
807807
this(x, tycon)
808808
case ImportSelector(imported, renamed, bound) =>
809809
this(this(this(x, imported), renamed), bound)

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,9 @@ object Parsers {
17861786

17871787
def infixTypeRest(t: Tree, operand: Location => Tree = refinedTypeFn): Tree =
17881788
infixOps(t, canStartInfixTypeTokens, operand, Location.ElseWhere, ParseKind.Type,
1789-
isOperator = !followingIsVararg() && !isPureArrow && !isIdent(nme.as)
1789+
isOperator = !followingIsVararg()
1790+
&& !isPureArrow
1791+
&& !(isIdent(nme.as) && in.featureEnabled(Feature.modularity))
17901792
&& nextCanFollowOperator(canStartInfixTypeTokens))
17911793

17921794
/** RefinedType ::= WithType {[nl] Refinement} [`^` CaptureSet]
@@ -2158,7 +2160,7 @@ object Parsers {
21582160
if (in.token == tok) { in.nextToken(); toplevelTyp() }
21592161
else EmptyTree
21602162

2161-
/** TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type}
2163+
/** TypeParamBounds ::= TypeBounds {`<%' Type} [`:` ContextBounds]
21622164
*/
21632165
def typeParamBounds(pname: TypeName): Tree = {
21642166
val t = typeBounds()
@@ -2169,8 +2171,16 @@ object Parsers {
21692171

21702172
/** ContextBound ::= Type [`as` id] */
21712173
def contextBound(pname: TypeName): Tree =
2172-
ContextBoundTypeTree(toplevelTyp(), pname)
2174+
val t = toplevelTyp()
2175+
val ownName =
2176+
if isIdent(nme.as) && in.featureEnabled(Feature.modularity) then
2177+
in.nextToken()
2178+
ident()
2179+
else EmptyTermName
2180+
ContextBoundTypeTree(t, pname, ownName)
21732181

2182+
/** ContextBounds ::= ContextBound | `{` ContextBound {`,` ContextBound} `}`
2183+
*/
21742184
def contextBounds(pname: TypeName): List[Tree] =
21752185
if in.isColon then
21762186
in.nextToken()

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
373373
changePrec(GlobalPrec) { keywordStr("for ") ~ Text(enums map enumText, "; ") ~ sep ~ toText(expr) }
374374

375375
def cxBoundToText(bound: untpd.Tree): Text = bound match { // DD
376-
case ContextBoundTypeTree(tpt, _) => " : " ~ toText(tpt)
376+
case ContextBoundTypeTree(tpt, _, _) => " : " ~ toText(tpt)
377377
case untpd.Function(_, tpt) => " <% " ~ toText(tpt)
378378
}
379379

@@ -729,9 +729,18 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
729729
case GenAlias(pat, expr) =>
730730
toText(pat) ~ " = " ~ toText(expr)
731731
case ContextBounds(bounds, cxBounds) =>
732-
cxBounds.foldLeft(toText(bounds)) {(t, cxb) =>
733-
t ~ cxBoundToText(cxb)
734-
}
732+
if Feature.enabled(Feature.modularity) then
733+
def boundsText(bounds: Tree) = bounds match
734+
case ContextBoundTypeTree(tpt, _, ownName) =>
735+
toText(tpt) ~ (" as " ~ toText(ownName) `provided` !ownName.isEmpty)
736+
case bounds => toText(bounds)
737+
cxBounds match
738+
case bound :: Nil => ": " ~ boundsText(bound)
739+
case _ => ": {" ~ Text(cxBounds.map(boundsText), ", ") ~ "}"
740+
else
741+
cxBounds.foldLeft(toText(bounds)) {(t, cxb) =>
742+
t ~ cxBoundToText(cxb)
743+
}
735744
case PatDef(mods, pats, tpt, rhs) =>
736745
modText(mods, NoSymbol, keywordStr("val"), isType = false) ~~
737746
toText(pats, ", ") ~ optAscription(tpt) ~ optText(rhs)(" = " ~ _)
@@ -776,8 +785,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
776785
prefix ~~ idx.toString ~~ "|" ~~ tpeText ~~ "|" ~~ argsText ~~ "|" ~~ contentText ~~ postfix
777786
case CapturesAndResult(refs, parent) =>
778787
changePrec(GlobalPrec)("^{" ~ Text(refs.map(toText), ", ") ~ "}" ~ toText(parent))
779-
case ContextBoundTypeTree(tycon, pname) =>
780-
toText(pname) ~ " is " ~ toText(tycon)
788+
case ContextBoundTypeTree(tycon, pname, ownName) =>
789+
toText(pname) ~ " is " ~ toText(tycon) ~ (" as " ~ toText(ownName) `provided` !ownName.isEmpty)
781790
case _ =>
782791
tree.fallbackToText(this)
783792
}

docs/_docs/internals/syntax.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,9 @@ IntoTargetType ::= Type
221221
TypeArgs ::= ‘[’ Types ‘]’ ts
222222
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> ds
223223
TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi)
224-
TypeParamBounds ::= TypeBounds {‘:’ Type} ContextBounds(typeBounds, tps)
224+
TypeParamBounds ::= TypeBounds [‘:’ ContextBounds] ContextBounds(typeBounds, tps)
225+
ContextBounds ::= ContextBound | '{' ContextBound {',' ContextBound} '}'
226+
ContextBound ::= Type ['as' id]
225227
Types ::= Type {‘,’ Type}
226228
```
227229

tests/pos/FromString.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@ given Int is FromString = _.toInt
88

99
given Double is FromString = _.toDouble
1010

11-
def add[N: {FromString, Numeric}](a: String, b: String): N =
12-
val num = summon[Numeric[N]]
11+
def add[N: {FromString, Numeric as num}](a: String, b: String): N =
1312
num.plus(N.fromString(a), N.fromString(b))

0 commit comments

Comments
 (0)