Skip to content

Commit 3183c50

Browse files
committed
Fix #4373: reject wildcard types in syntactically invalid positions
Fix #4373. The testcase is from examples in #4373, variations and tests for types with wildcards.
1 parent 9177c15 commit 3183c50

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -468,9 +468,9 @@ object Parsers {
468468
val l = opInfo.operand
469469
val r = top
470470
if (isType && !op.isBackquoted && op.name == tpnme.raw.BAR) {
471-
OrTypeTree(l, r)
471+
OrTypeTree(checkWildcard(l), checkWildcard(r))
472472
} else if (isType && !op.isBackquoted && op.name == tpnme.raw.AMP) {
473-
AndTypeTree(l, r)
473+
AndTypeTree(checkWildcard(l), checkWildcard(r))
474474
} else
475475
InfixOp(l, op, r)
476476
}
@@ -784,7 +784,7 @@ object Parsers {
784784
val start = in.offset
785785
val tparams = typeParamClause(ParamOwner.TypeParam)
786786
if (in.token == ARROW)
787-
atPos(start, in.skipToken())(LambdaTypeTree(tparams, typ()))
787+
atPos(start, in.skipToken())(LambdaTypeTree(tparams, toplevelTyp()))
788788
else { accept(ARROW); typ() }
789789
}
790790
else infixType()
@@ -822,7 +822,7 @@ object Parsers {
822822

823823
def refinedTypeRest(t: Tree): Tree = {
824824
newLineOptWhenFollowedBy(LBRACE)
825-
if (in.token == LBRACE) refinedTypeRest(atPos(startOffset(t)) { RefinedTypeTree(t, refinement()) })
825+
if (in.token == LBRACE) refinedTypeRest(atPos(startOffset(t)) { RefinedTypeTree(checkWildcard(t), refinement()) })
826826
else t
827827
}
828828

@@ -886,7 +886,7 @@ object Parsers {
886886
private def simpleTypeRest(t: Tree): Tree = in.token match {
887887
case HASH => simpleTypeRest(typeProjection(t))
888888
case LBRACKET => simpleTypeRest(atPos(startOffset(t)) {
889-
AppliedTypeTree(t, typeArgs(namedOK = false, wildOK = true)) })
889+
AppliedTypeTree(checkWildcard(t), typeArgs(namedOK = false, wildOK = true)) })
890890
case _ => t
891891
}
892892

@@ -2159,7 +2159,7 @@ object Parsers {
21592159
in.token match {
21602160
case EQUALS =>
21612161
in.nextToken()
2162-
TypeDef(name, lambdaAbstract(tparams, typ())).withMods(mods).setComment(in.getDocComment(start))
2162+
TypeDef(name, lambdaAbstract(tparams, toplevelTyp())).withMods(mods).setComment(in.getDocComment(start))
21632163
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF =>
21642164
TypeDef(name, lambdaAbstract(tparams, typeBounds())).withMods(mods).setComment(in.getDocComment(start))
21652165
case _ =>
@@ -2287,7 +2287,7 @@ object Parsers {
22872287
/** ConstrApp ::= SimpleType {ParArgumentExprs}
22882288
*/
22892289
val constrApp = () => {
2290-
val t = annotType()
2290+
val t = checkWildcard(annotType())
22912291
if (in.token == LPAREN) parArgumentExprss(wrapNew(t))
22922292
else t
22932293
}

tests/neg/i4373.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
trait Base
2+
trait TypeConstr[X]
3+
4+
class X1[A >: _ | X1[_]] // error
5+
class X2[A >: _ & X2[_]] // error
6+
class X3[A >: X3[_] | _] // error
7+
class X4[A >: X4[_] & _] // error
8+
9+
class A1 extends _ // error
10+
class A2 extends _ with _ // error // error
11+
class A3 extends Base with _ // error
12+
class A4 extends _ with Base // error
13+
14+
object Test {
15+
type T1 = _ // error
16+
type T2 = _[Int] // error
17+
type T3 = _ { type S } // error
18+
type T4 = [X] => _ // error
19+
20+
// Open questions:
21+
type T5 = TypeConstr[_ { type S }] // error
22+
type T5 = TypeConstr[_[Int]] // error
23+
}

0 commit comments

Comments
 (0)