@@ -452,7 +452,7 @@ object Parsers {
452
452
if (isLeftAssoc(op1) != op2LeftAssoc)
453
453
syntaxError(MixedLeftAndRightAssociativeOps (op1, op2, op2LeftAssoc), offset)
454
454
455
- def reduceStack (base : List [OpInfo ], top : Tree , prec : Int , leftAssoc : Boolean , op2 : Name ): Tree = {
455
+ def reduceStack (base : List [OpInfo ], top : Tree , prec : Int , leftAssoc : Boolean , op2 : Name , isType : Boolean ): Tree = {
456
456
if (opStack != base && precedence(opStack.head.operator.name) == prec)
457
457
checkAssoc(opStack.head.offset, opStack.head.operator.name, op2, leftAssoc)
458
458
def recur (top : Tree ): Tree = {
@@ -464,7 +464,15 @@ object Parsers {
464
464
opStack = opStack.tail
465
465
recur {
466
466
atPos(opInfo.operator.pos union opInfo.operand.pos union top.pos) {
467
- InfixOp (opInfo.operand, opInfo.operator, top)
467
+ val op = opInfo.operator
468
+ val l = opInfo.operand
469
+ val r = top
470
+ if (isType && ! op.isBackquoted && op.name == tpnme.raw.BAR ) {
471
+ OrTypeTree (checkAndOrArgument(l), checkAndOrArgument(r))
472
+ } else if (isType && ! op.isBackquoted && op.name == tpnme.raw.AMP ) {
473
+ AndTypeTree (checkAndOrArgument(l), checkAndOrArgument(r))
474
+ } else
475
+ InfixOp (l, op, r)
468
476
}
469
477
}
470
478
}
@@ -488,20 +496,20 @@ object Parsers {
488
496
var top = first
489
497
while (isIdent && isOperator) {
490
498
val op = if (isType) typeIdent() else termIdent()
491
- top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name), op.name)
499
+ top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name), op.name, isType )
492
500
opStack = OpInfo (top, op, in.offset) :: opStack
493
501
newLineOptWhenFollowing(canStartOperand)
494
502
if (maybePostfix && ! canStartOperand(in.token)) {
495
503
val topInfo = opStack.head
496
504
opStack = opStack.tail
497
- val od = reduceStack(base, topInfo.operand, 0 , true , in.name)
505
+ val od = reduceStack(base, topInfo.operand, 0 , true , in.name, isType )
498
506
return atPos(startOffset(od), topInfo.offset) {
499
507
PostfixOp (od, topInfo.operator)
500
508
}
501
509
}
502
510
top = operand()
503
511
}
504
- reduceStack(base, top, 0 , true , in.name)
512
+ reduceStack(base, top, 0 , true , in.name, isType )
505
513
}
506
514
507
515
/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */
@@ -709,15 +717,7 @@ object Parsers {
709
717
/** Same as [[typ ]], but if this results in a wildcard it emits a syntax error and
710
718
* returns a tree for type `Any` instead.
711
719
*/
712
- def toplevelTyp (): Tree = {
713
- val t = typ()
714
- findWildcardType(t) match {
715
- case Some (wildcardPos) =>
716
- syntaxError(UnboundWildcardType (), wildcardPos)
717
- scalaAny
718
- case None => t
719
- }
720
- }
720
+ def toplevelTyp (): Tree = checkWildcard(typ())
721
721
722
722
/** Type ::= [FunArgMods] FunArgTypes `=>' Type
723
723
* | HkTypeParamClause `->' Type
@@ -768,9 +768,16 @@ object Parsers {
768
768
accept(RPAREN )
769
769
if (imods.is(Implicit ) || isValParamList || in.token == ARROW ) functionRest(ts)
770
770
else {
771
- for (t <- ts)
772
- if (t.isInstanceOf [ByNameTypeTree ])
773
- syntaxError(ByNameParameterNotSupported ())
771
+ val ts1 =
772
+ for (t <- ts) yield {
773
+ t match {
774
+ case t@ ByNameTypeTree (t1) =>
775
+ syntaxError(ByNameParameterNotSupported (t), t.pos)
776
+ t1
777
+ case _ =>
778
+ t
779
+ }
780
+ }
774
781
val tuple = atPos(start) { makeTupleOrParens(ts) }
775
782
infixTypeRest(
776
783
refinedTypeRest(
@@ -784,7 +791,7 @@ object Parsers {
784
791
val start = in.offset
785
792
val tparams = typeParamClause(ParamOwner .TypeParam )
786
793
if (in.token == ARROW )
787
- atPos(start, in.skipToken())(LambdaTypeTree (tparams, typ ()))
794
+ atPos(start, in.skipToken())(LambdaTypeTree (tparams, toplevelTyp ()))
788
795
else { accept(ARROW ); typ() }
789
796
}
790
797
else infixType()
@@ -822,7 +829,7 @@ object Parsers {
822
829
823
830
def refinedTypeRest (t : Tree ): Tree = {
824
831
newLineOptWhenFollowedBy(LBRACE )
825
- if (in.token == LBRACE ) refinedTypeRest(atPos(startOffset(t)) { RefinedTypeTree (t , refinement()) })
832
+ if (in.token == LBRACE ) refinedTypeRest(atPos(startOffset(t)) { RefinedTypeTree (checkWildcard(t) , refinement()) })
826
833
else t
827
834
}
828
835
@@ -835,7 +842,7 @@ object Parsers {
835
842
if (ctx.settings.strict.value)
836
843
deprecationWarning(DeprecatedWithOperator ())
837
844
in.nextToken()
838
- AndTypeTree (t, withType())
845
+ AndTypeTree (checkAndOrArgument(t), checkAndOrArgument( withType() ))
839
846
}
840
847
else t
841
848
@@ -886,7 +893,7 @@ object Parsers {
886
893
private def simpleTypeRest (t : Tree ): Tree = in.token match {
887
894
case HASH => simpleTypeRest(typeProjection(t))
888
895
case LBRACKET => simpleTypeRest(atPos(startOffset(t)) {
889
- AppliedTypeTree (t , typeArgs(namedOK = false , wildOK = true )) })
896
+ AppliedTypeTree (checkWildcard(t) , typeArgs(namedOK = false , wildOK = true )) })
890
897
case _ => t
891
898
}
892
899
@@ -917,7 +924,7 @@ object Parsers {
917
924
else Nil
918
925
first :: rest
919
926
}
920
- def typParser () = if (wildOK) typ() else toplevelTyp( )
927
+ def typParser () = checkWildcard( typ(), wildOK )
921
928
if (namedOK && in.token == IDENTIFIER )
922
929
typParser() match {
923
930
case Ident (name) if in.token == EQUALS =>
@@ -1001,17 +1008,46 @@ object Parsers {
1001
1008
else if (location == Location .InPattern ) refinedType()
1002
1009
else infixType()
1003
1010
1004
- /** Checks whether `t` is a wildcard type.
1005
- * If it is, returns the [[Position ]] where the wildcard occurs .
1011
+ /** Checks whether `t` represents a non-value type (wildcard types, or ByNameTypeTree) .
1012
+ * If it is, returns the [[Tree ]] which immediately represents the non-value type .
1006
1013
*/
1007
1014
@ tailrec
1008
- private final def findWildcardType (t : Tree ): Option [Position ] = t match {
1009
- case TypeBoundsTree (_, _) => Some (t.pos)
1010
- case Parens (t1) => findWildcardType(t1)
1011
- case Annotated (t1, _) => findWildcardType(t1)
1015
+ private final def findNonValueTypeTree (t : Tree , alsoNonValue : Boolean ): Option [Tree ] = t match {
1016
+ case TypeBoundsTree (_, _) => Some (t)
1017
+ case ByNameTypeTree (_) if alsoNonValue => Some (t)
1018
+ case Parens (t1) => findNonValueTypeTree(t1, alsoNonValue)
1019
+ case Annotated (t1, _) => findNonValueTypeTree(t1, alsoNonValue)
1012
1020
case _ => None
1013
1021
}
1014
1022
1023
+ def rejectWildcard (t : Tree , fallbackTree : Tree ): Tree =
1024
+ findNonValueTypeTree(t, false ) match {
1025
+ case Some (wildcardTree) =>
1026
+ syntaxError(UnboundWildcardType (), wildcardTree.pos)
1027
+ fallbackTree
1028
+ case None => t
1029
+ }
1030
+
1031
+
1032
+ def checkWildcard (t : Tree , wildOK : Boolean = false , fallbackTree : Tree = scalaAny): Tree =
1033
+ if (wildOK)
1034
+ t
1035
+ else
1036
+ rejectWildcard(t, fallbackTree)
1037
+
1038
+ def checkAndOrArgument (t : Tree ): Tree =
1039
+ findNonValueTypeTree(t, true ) match {
1040
+ case Some (typTree) =>
1041
+ typTree match {
1042
+ case typTree : TypeBoundsTree =>
1043
+ syntaxError(UnboundWildcardType (), typTree.pos)
1044
+ case typTree : ByNameTypeTree =>
1045
+ syntaxError(ByNameParameterNotSupported (typTree), typTree.pos)
1046
+ }
1047
+ scalaAny
1048
+ case None => t
1049
+ }
1050
+
1015
1051
/* ----------- EXPRESSIONS ------------------------------------------------ */
1016
1052
1017
1053
/** EqualsExpr ::= `=' Expr
@@ -2148,7 +2184,7 @@ object Parsers {
2148
2184
in.token match {
2149
2185
case EQUALS =>
2150
2186
in.nextToken()
2151
- TypeDef (name, lambdaAbstract(tparams, typ ())).withMods(mods).setComment(in.getDocComment(start))
2187
+ TypeDef (name, lambdaAbstract(tparams, toplevelTyp ())).withMods(mods).setComment(in.getDocComment(start))
2152
2188
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF =>
2153
2189
TypeDef (name, lambdaAbstract(tparams, typeBounds())).withMods(mods).setComment(in.getDocComment(start))
2154
2190
case _ =>
@@ -2276,7 +2312,8 @@ object Parsers {
2276
2312
/** ConstrApp ::= SimpleType {ParArgumentExprs}
2277
2313
*/
2278
2314
val constrApp = () => {
2279
- val t = annotType()
2315
+ // Using Ident(nme.ERROR) to avoid causing cascade errors on non-user-written code
2316
+ val t = checkWildcard(annotType(), fallbackTree = Ident (nme.ERROR ))
2280
2317
if (in.token == LPAREN ) parArgumentExprss(wrapNew(t))
2281
2318
else t
2282
2319
}
0 commit comments