Skip to content

Commit a8afd92

Browse files
committed
Refinements to wildcard checking
Simplify and cover cases that were missing (see gadt-GadtStatic.scala).
1 parent a4b1709 commit a8afd92

File tree

2 files changed

+39
-46
lines changed

2 files changed

+39
-46
lines changed

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

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,19 @@ object Parsers {
423423
case _ => false
424424
}
425425

426+
def isWildcardType(t: Tree): Boolean = t match {
427+
case t: TypeBoundsTree => true
428+
case Parens(t1) => isWildcardType(t1)
429+
case _ => false
430+
}
431+
432+
def rejectWildcardType(t: Tree, fallbackTree: Tree = scalaAny): Tree =
433+
if (isWildcardType(t)) {
434+
syntaxError(UnboundWildcardType(), t.span)
435+
fallbackTree
436+
}
437+
else t
438+
426439
/* -------------- XML ---------------------------------------------------- */
427440

428441
/** the markup parser */
@@ -768,7 +781,7 @@ object Parsers {
768781
/** Same as [[typ]], but if this results in a wildcard it emits a syntax error and
769782
* returns a tree for type `Any` instead.
770783
*/
771-
def toplevelTyp(): Tree = checkWildcard(typ())
784+
def toplevelTyp(): Tree = rejectWildcardType(typ())
772785

773786
/** Type ::= FunTypeMods FunArgTypes `=>' Type
774787
* | HkTypeParamClause `->' Type
@@ -885,7 +898,7 @@ object Parsers {
885898

886899
def refinedTypeRest(t: Tree): Tree = {
887900
newLineOptWhenFollowedBy(LBRACE)
888-
if (in.token == LBRACE) refinedTypeRest(atSpan(startOffset(t)) { RefinedTypeTree(checkWildcard(t), refinement()) })
901+
if (in.token == LBRACE) refinedTypeRest(atSpan(startOffset(t)) { RefinedTypeTree(rejectWildcardType(t), refinement()) })
889902
else t
890903
}
891904

@@ -907,7 +920,10 @@ object Parsers {
907920
def annotType(): Tree = annotTypeRest(simpleType())
908921

909922
def annotTypeRest(t: Tree): Tree =
910-
if (in.token == AT) annotTypeRest(atSpan(startOffset(t)) { Annotated(t, annot()) })
923+
if (in.token == AT)
924+
annotTypeRest(atSpan(startOffset(t)) {
925+
Annotated(rejectWildcardType(t), annot())
926+
})
911927
else t
912928

913929
/** SimpleType ::= SimpleType TypeArgs
@@ -949,7 +965,7 @@ object Parsers {
949965
private def simpleTypeRest(t: Tree): Tree = in.token match {
950966
case HASH => simpleTypeRest(typeProjection(t))
951967
case LBRACKET => simpleTypeRest(atSpan(startOffset(t)) {
952-
AppliedTypeTree(checkWildcard(t), typeArgs(namedOK = false, wildOK = true)) })
968+
AppliedTypeTree(rejectWildcardType(t), typeArgs(namedOK = false, wildOK = true)) })
953969
case _ => t
954970
}
955971

@@ -959,18 +975,23 @@ object Parsers {
959975
atSpan(startOffset(t), startOffset(id)) { Select(t, id.name) }
960976
}
961977

962-
/** NamedTypeArg ::= id `=' Type
963-
*/
964-
val namedTypeArg: () => NamedArg = () => {
965-
val name = ident()
966-
accept(EQUALS)
967-
NamedArg(name.toTypeName, typ())
968-
}
969-
970978
/** ArgTypes ::= Type {`,' Type}
971979
* | NamedTypeArg {`,' NamedTypeArg}
980+
* NamedTypeArg ::= id `=' Type
972981
*/
973982
def argTypes(namedOK: Boolean, wildOK: Boolean): List[Tree] = {
983+
984+
def argType() = {
985+
val t = typ()
986+
if (wildOK) t else rejectWildcardType(t)
987+
}
988+
989+
def namedTypeArg() = {
990+
val name = ident()
991+
accept(EQUALS)
992+
NamedArg(name.toTypeName, argType())
993+
}
994+
974995
def otherArgs(first: Tree, arg: () => Tree): List[Tree] = {
975996
val rest =
976997
if (in.token == COMMA) {
@@ -980,16 +1001,15 @@ object Parsers {
9801001
else Nil
9811002
first :: rest
9821003
}
983-
def typParser() = checkWildcard(typ(), wildOK)
9841004
if (namedOK && in.token == IDENTIFIER)
985-
typParser() match {
1005+
argType() match {
9861006
case Ident(name) if in.token == EQUALS =>
9871007
in.nextToken()
988-
otherArgs(NamedArg(name, typ()), namedTypeArg)
1008+
otherArgs(NamedArg(name, argType()), () => namedTypeArg())
9891009
case firstArg =>
990-
otherArgs(firstArg, () => typ())
1010+
otherArgs(firstArg, () => argType())
9911011
}
992-
else commaSeparated(() => typParser())
1012+
else commaSeparated(() => argType())
9931013
}
9941014

9951015
/** FunArgType ::= Type | `=>' Type
@@ -1064,33 +1084,6 @@ object Parsers {
10641084
else if (location == Location.InPattern) refinedType()
10651085
else infixType()
10661086

1067-
/** Checks whether `t` represents a non-value type (wildcard types, or ByNameTypeTree).
1068-
* If it is, returns the [[Tree]] which immediately represents the non-value type.
1069-
*/
1070-
@tailrec
1071-
private final def findNonValueTypeTree(t: Tree, alsoNonValue: Boolean): Option[Tree] = t match {
1072-
case TypeBoundsTree(_, _) => Some(t)
1073-
case ByNameTypeTree(_) if alsoNonValue => Some(t)
1074-
case Parens(t1) => findNonValueTypeTree(t1, alsoNonValue)
1075-
case Annotated(t1, _) => findNonValueTypeTree(t1, alsoNonValue)
1076-
case _ => None
1077-
}
1078-
1079-
def rejectWildcard(t: Tree, fallbackTree: Tree): Tree =
1080-
findNonValueTypeTree(t, false) match {
1081-
case Some(wildcardTree) =>
1082-
syntaxError(UnboundWildcardType(), wildcardTree.span)
1083-
fallbackTree
1084-
case None => t
1085-
}
1086-
1087-
1088-
def checkWildcard(t: Tree, wildOK: Boolean = false, fallbackTree: Tree = scalaAny): Tree =
1089-
if (wildOK)
1090-
t
1091-
else
1092-
rejectWildcard(t, fallbackTree)
1093-
10941087
/* ----------- EXPRESSIONS ------------------------------------------------ */
10951088

10961089
/** EqualsExpr ::= `=' Expr
@@ -2567,7 +2560,7 @@ object Parsers {
25672560
*/
25682561
val constrApp: () => Tree = () => {
25692562
// Using Ident(nme.ERROR) to avoid causing cascade errors on non-user-written code
2570-
val t = checkWildcard(annotType(), fallbackTree = Ident(nme.ERROR))
2563+
val t = rejectWildcardType(annotType(), fallbackTree = Ident(nme.ERROR))
25712564
if (in.token == LPAREN) parArgumentExprss(wrapNew(t))
25722565
else t
25732566
}

tests/pos/gadt-GadtStlc.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ object GadtStlc {
119119
case Left(isv1) => progress(dapp.d2) match {
120120
case Right(r2) => Right(EApp2(isv1, r2))
121121
case Left(isv2) => followsIsLambda(isv1, dapp.d1) match {
122-
case _: ISLAMBDAC[x, e] => Right(EAppAbs[x, e, b, _](isv2))
122+
case _: ISLAMBDAC[x, e] => Right(EAppAbs[X = x, E = e, V2 = b](isv2))
123123
}
124124
}
125125
}

0 commit comments

Comments
 (0)