Skip to content

Commit

Permalink
fix: Allow as as an infix type in non context bound types
Browse files Browse the repository at this point in the history
  • Loading branch information
KacperFKorban committed Oct 28, 2024
1 parent dd37f07 commit a399900
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
22 changes: 13 additions & 9 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ object Parsers {
enum IntoOK:
case Yes, No, Nested

enum InContextBound:
case Yes, No

type StageKind = Int
object StageKind {
val None = 0
Expand Down Expand Up @@ -1550,7 +1553,8 @@ object Parsers {
/** Same as [[typ]], but if this results in a wildcard it emits a syntax error and
* returns a tree for type `Any` instead.
*/
def toplevelTyp(intoOK: IntoOK = IntoOK.No): Tree = rejectWildcardType(typ(intoOK))
def toplevelTyp(intoOK: IntoOK = IntoOK.No, inContextBound: InContextBound = InContextBound.No): Tree =
rejectWildcardType(typ(intoOK, inContextBound))

private def getFunction(tree: Tree): Option[Function] = tree match {
case Parens(tree1) => getFunction(tree1)
Expand Down Expand Up @@ -1605,7 +1609,7 @@ object Parsers {
* IntoTargetType ::= Type
* | FunTypeArgs (‘=>’ | ‘?=>’) IntoType
*/
def typ(intoOK: IntoOK = IntoOK.No): Tree =
def typ(intoOK: IntoOK = IntoOK.No, inContextBound: InContextBound = InContextBound.No): Tree =
val start = in.offset
var imods = Modifiers()
val erasedArgs: ListBuffer[Boolean] = ListBuffer()
Expand Down Expand Up @@ -1754,7 +1758,7 @@ object Parsers {
val tuple = atSpan(start):
makeTupleOrParens(args.mapConserve(convertToElem))
typeRest:
infixTypeRest:
infixTypeRest(inContextBound):
refinedTypeRest:
withTypeRest:
annotTypeRest:
Expand All @@ -1777,7 +1781,7 @@ object Parsers {
else if isIntoPrefix then
PrefixOp(typeIdent(), typ(IntoOK.Nested))
else
typeRest(infixType())
typeRest(infixType(inContextBound))
end typ

private def makeKindProjectorTypeDef(name: TypeName): TypeDef = {
Expand Down Expand Up @@ -1832,13 +1836,13 @@ object Parsers {
/** InfixType ::= RefinedType {id [nl] RefinedType}
* | RefinedType `^` // under capture checking
*/
def infixType(): Tree = infixTypeRest(refinedType())
def infixType(inContextBound: InContextBound = InContextBound.No): Tree = infixTypeRest(inContextBound)(refinedType())

def infixTypeRest(t: Tree, operand: Location => Tree = refinedTypeFn): Tree =
def infixTypeRest(inContextBound: InContextBound = InContextBound.No)(t: Tree, operand: Location => Tree = refinedTypeFn): Tree =
infixOps(t, canStartInfixTypeTokens, operand, Location.ElseWhere, ParseKind.Type,
isOperator = !followingIsVararg()
&& !isPureArrow
&& !(isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`))
&& !(isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`) && inContextBound == InContextBound.Yes)
&& nextCanFollowOperator(canStartInfixTypeTokens))

/** RefinedType ::= WithType {[nl] Refinement} [`^` CaptureSet]
Expand Down Expand Up @@ -2229,7 +2233,7 @@ object Parsers {

/** ContextBound ::= Type [`as` id] */
def contextBound(pname: TypeName): Tree =
val t = toplevelTyp()
val t = toplevelTyp(inContextBound = InContextBound.Yes)
val ownName =
if isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`) then
in.nextToken()
Expand Down Expand Up @@ -4207,7 +4211,7 @@ object Parsers {
else constrApp() match
case parent: Apply => parent :: moreConstrApps()
case parent if in.isIdent && newSyntaxAllowed =>
infixTypeRest(parent, _ => annotType1()) :: Nil
infixTypeRest()(parent, _ => annotType1()) :: Nil
case parent => parent :: moreConstrApps()

// The term parameters and parent references */
Expand Down
20 changes: 20 additions & 0 deletions tests/pos/i21769.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//> using scala 3.nightly

infix trait as[From, To]

val conv: (String as Int) = ???
given instance: (String as Int) = ???
def test(ev: (String as Int)) = ???

class F

class K extends (F as K)

class TC1[X]

def doSth[X: TC1 as tc] = ???

class TC2[X]:
type Self = X

def doSth2[X: {TC1 as tc1, TC2 as tc2}](x: tc2.Self) = ???

0 comments on commit a399900

Please sign in to comment.