Skip to content

Commit a4b1709

Browse files
committed
Check for illegal wildcards in TypeAssigner
Drop previous checking in Parser. The idea is that the parser should follow the syntax. Checking conditions that are not reflected in the syntax should come later.
1 parent f4d02de commit a4b1709

File tree

5 files changed

+24
-22
lines changed

5 files changed

+24
-22
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class Definitions {
153153
sym
154154
}
155155

156+
private def enterBinaryAlias(name: TypeName, op: (Type, Type) => Type): TypeSymbol =
157+
enterAliasType(name,
158+
HKTypeLambda(TypeBounds.empty :: TypeBounds.empty :: Nil)(
159+
tl => op(tl.paramRefs(0), tl.paramRefs(1))))
160+
156161
private def enterPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int,
157162
resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags,
158163
useCompleter: Boolean = false) = {
@@ -322,6 +327,9 @@ class Definitions {
322327
}
323328
def AnyKindType: TypeRef = AnyKindClass.typeRef
324329

330+
lazy val andType: TypeSymbol = enterBinaryAlias(tpnme.AND, AndType(_, _))
331+
lazy val orType: TypeSymbol = enterBinaryAlias(tpnme.OR, OrType(_, _))
332+
325333
/** Marker method to indicate an argument to a call-by-name parameter.
326334
* Created by byNameClosures and elimByName, eliminated by Erasure,
327335
*/
@@ -1326,6 +1334,8 @@ class Definitions {
13261334
AnyClass,
13271335
AnyRefAlias,
13281336
AnyKindClass,
1337+
andType,
1338+
orType,
13291339
RepeatedParamClass,
13301340
ByNameParamClass2x,
13311341
AnyValClass,

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,9 @@ object Parsers {
492492
val l = opInfo.operand
493493
val r = top
494494
if (isType && !op.isBackquoted && op.name == tpnme.raw.BAR) {
495-
OrTypeTree(checkAndOrArgument(l), checkAndOrArgument(r))
495+
OrTypeTree(l, r)
496496
} else if (isType && !op.isBackquoted && op.name == tpnme.raw.AMP) {
497-
AndTypeTree(checkAndOrArgument(l), checkAndOrArgument(r))
497+
AndTypeTree(l, r)
498498
} else
499499
InfixOp(l, op, r)
500500
}
@@ -830,7 +830,7 @@ object Parsers {
830830
t
831831
}
832832
}
833-
val tuple = atSpan(start) { makeTupleOrParens(ts) }
833+
val tuple = atSpan(start) { makeTupleOrParens(ts1) }
834834
infixTypeRest(
835835
refinedTypeRest(
836836
withTypeRest(
@@ -898,7 +898,7 @@ object Parsers {
898898
if (ctx.settings.strict.value)
899899
deprecationWarning(DeprecatedWithOperator())
900900
in.nextToken()
901-
AndTypeTree(checkAndOrArgument(t), checkAndOrArgument(withType()))
901+
AndTypeTree(t, withType())
902902
}
903903
else t
904904

@@ -1091,19 +1091,6 @@ object Parsers {
10911091
else
10921092
rejectWildcard(t, fallbackTree)
10931093

1094-
def checkAndOrArgument(t: Tree): Tree =
1095-
findNonValueTypeTree(t, true) match {
1096-
case Some(typTree) =>
1097-
typTree match {
1098-
case typTree: TypeBoundsTree =>
1099-
syntaxError(UnboundWildcardType(), typTree.span)
1100-
case typTree: ByNameTypeTree =>
1101-
syntaxError(ByNameParameterNotSupported(typTree), typTree.span)
1102-
}
1103-
scalaAny
1104-
case None => t
1105-
}
1106-
11071094
/* ----------- EXPRESSIONS ------------------------------------------------ */
11081095

11091096
/** EqualsExpr ::= `=' Expr

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ object Checking {
9292
checkValidIfApply(ctx.addMode(Mode.AllowLambdaWildcardApply))
9393
}
9494

95+
def checkNoWildcard(tree: Tree)(implicit ctx: Context): Tree = tree.tpe match {
96+
case tpe: TypeBounds => errorTree(tree, "no wildcard type allowed here")
97+
case _ => tree
98+
}
99+
95100
/** Check that kind of `arg` has the same outline as the kind of paramBounds.
96101
* E.g. if `paramBounds` has kind * -> *, `arg` must have that kind as well,
97102
* and analogously for all other kinds. This kind checking does not take into account

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import ast.Trees._
1313
import NameOps._
1414
import collection.mutable
1515
import reporting.diagnostic.messages._
16-
import Checking.checkNoPrivateLeaks
16+
import Checking.{checkNoPrivateLeaks, checkNoWildcard}
1717

1818
trait TypeAssigner {
1919
import tpd._
@@ -519,10 +519,10 @@ trait TypeAssigner {
519519
tree.withType(ref.tpe)
520520

521521
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree =
522-
tree.withType(AndType(left.tpe, right.tpe))
522+
tree.withType(AndType(checkNoWildcard(left).tpe, checkNoWildcard(right).tpe))
523523

524524
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree =
525-
tree.withType(OrType(left.tpe, right.tpe))
525+
tree.withType(OrType(checkNoWildcard(left).tpe, checkNoWildcard(right).tpe))
526526

527527
/** Assign type of RefinedType.
528528
* Refinements are typed as if they were members of refinement class `refineCls`.

tests/neg/i4373.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ object Test {
4141

4242
type T19 = (_ with Int) @ annotation.tailrec // error
4343
type T20 = (Int with _) @ annotation.tailrec // error
44-
type T21 = Int @ (_ with annotation.tailrec) // error // error
45-
type T22 = Int @ (annotation.tailrec with _) // error // error
44+
type T21 = Int @ (_ with annotation.tailrec) // error
45+
type T22 = Int @ (annotation.tailrec with _) // error
4646

4747
type T23 = (_ & Int) @ annotation.tailrec // error
4848
type T24 = (Int & _) @ annotation.tailrec // error

0 commit comments

Comments
 (0)