Skip to content

Commit

Permalink
Backport "fix: Allow as as an infix type in non context bound types…
Browse files Browse the repository at this point in the history
…" to 3.6.2 (#21901)

Backports #21849 to the 3.6.2 branch.

PR submitted by the release tooling.
[skip ci]
  • Loading branch information
WojciechMazur authored Nov 8, 2024
2 parents 087fd92 + 07583a1 commit b9696fe
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
19 changes: 10 additions & 9 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,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: Boolean = false): Tree =
rejectWildcardType(typ(intoOK, inContextBound))

private def getFunction(tree: Tree): Option[Function] = tree match {
case Parens(tree1) => getFunction(tree1)
Expand Down Expand Up @@ -1594,7 +1595,7 @@ object Parsers {
* IntoTargetType ::= Type
* | FunTypeArgs (‘=>’ | ‘?=>’) IntoType
*/
def typ(intoOK: IntoOK = IntoOK.No): Tree =
def typ(intoOK: IntoOK = IntoOK.No, inContextBound: Boolean = false): Tree =
val start = in.offset
var imods = Modifiers()
val erasedArgs: ListBuffer[Boolean] = ListBuffer()
Expand Down Expand Up @@ -1743,7 +1744,7 @@ object Parsers {
val tuple = atSpan(start):
makeTupleOrParens(args.mapConserve(convertToElem))
typeRest:
infixTypeRest:
infixTypeRest(inContextBound):
refinedTypeRest:
withTypeRest:
annotTypeRest:
Expand Down Expand Up @@ -1772,7 +1773,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 @@ -1827,13 +1828,13 @@ object Parsers {
/** InfixType ::= RefinedType {id [nl] RefinedType}
* | RefinedType `^` // under capture checking
*/
def infixType(): Tree = infixTypeRest(refinedType())
def infixType(inContextBound: Boolean = false): Tree = infixTypeRest(inContextBound)(refinedType())

def infixTypeRest(t: Tree, operand: Location => Tree = refinedTypeFn): Tree =
def infixTypeRest(inContextBound: Boolean = false)(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)
&& nextCanFollowOperator(canStartInfixTypeTokens))

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

/** ContextBound ::= Type [`as` id] */
def contextBound(pname: TypeName): Tree =
val t = toplevelTyp()
val t = toplevelTyp(inContextBound = true)
val ownName =
if isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`) then
in.nextToken()
Expand Down Expand Up @@ -4209,7 +4210,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
19 changes: 19 additions & 0 deletions tests/pos/i21769.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

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 b9696fe

Please sign in to comment.