@@ -29,6 +29,7 @@ import ErrorReporting.{err, errorType}
29
29
import config .Printers .typr
30
30
import collection .mutable
31
31
import SymDenotations .NoCompleter
32
+ import dotty .tools .dotc .transform .ValueClasses ._
32
33
33
34
object Checking {
34
35
import tpd ._
@@ -56,7 +57,7 @@ object Checking {
56
57
checkBounds(args, poly.paramBounds, _.substParams(poly, _))
57
58
58
59
/** Check applied type trees for well-formedness. This means
59
- * - all arguments are within their corresponding bounds
60
+ * - all arguments are within their corresponding bounds
60
61
* - if type is a higher-kinded application with wildcard arguments,
61
62
* check that it or one of its supertypes can be reduced to a normal application.
62
63
* Unreducible applications correspond to general existentials, and we
@@ -88,12 +89,12 @@ object Checking {
88
89
checkWildcardHKApply(tp.superType, pos)
89
90
}
90
91
case _ =>
91
- }
92
+ }
92
93
def checkValidIfHKApply (implicit ctx : Context ): Unit =
93
94
checkWildcardHKApply(tycon.tpe.appliedTo(args.map(_.tpe)), tree.pos)
94
95
checkValidIfHKApply(ctx.addMode(Mode .AllowLambdaWildcardApply ))
95
96
}
96
-
97
+
97
98
/** Check that `tp` refers to a nonAbstract class
98
99
* and that the instance conforms to the self type of the created class.
99
100
*/
@@ -392,6 +393,43 @@ object Checking {
392
393
notPrivate.errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) }
393
394
info
394
395
}
396
+
397
+ /** Verify classes extending AnyVal meet the requirements */
398
+ def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) = {
399
+ def checkValueClassMember (stat : Tree ) = stat match {
400
+ case _ : ValDef if ! stat.symbol.is(ParamAccessor ) =>
401
+ ctx.error(s " value class may not define non-parameter field " , stat.pos)
402
+ case d : DefDef if d.symbol.isConstructor =>
403
+ ctx.error(s " value class may not define secondary constructor " , stat.pos)
404
+ case _ : MemberDef | _ : Import | EmptyTree =>
405
+ // ok
406
+ case _ =>
407
+ ctx.error(s " value class may not contain initialization statements " , stat.pos)
408
+ }
409
+ if (isDerivedValueClass(clazz)) {
410
+ if (clazz.is(Trait ))
411
+ ctx.error(" Only classes (not traits) are allowed to extend AnyVal" , clazz.pos)
412
+ if (clazz.is(Abstract ))
413
+ ctx.error(" `abstract' modifier cannot be used with value classes" , clazz.pos)
414
+ if (! clazz.isStatic)
415
+ ctx.error(s " value class may not be a ${if (clazz.owner.isTerm) " local class" else " member of another class" }" , clazz.pos)
416
+ if (isCyclic(clazz.asClass))
417
+ ctx.error(" value class cannot wrap itself" , clazz.pos)
418
+ else {
419
+ val clParamAccessors = clazz.asClass.paramAccessors.filter(_.isTerm)
420
+ clParamAccessors match {
421
+ case List (param) =>
422
+ if (param.is(Mutable ))
423
+ ctx.error(" value class parameter must not be a var" , param.pos)
424
+
425
+ case _ =>
426
+ ctx.error(" value class needs to have exactly one val parameter" , clazz.pos)
427
+ }
428
+ }
429
+ stats.foreach(checkValueClassMember)
430
+ }
431
+
432
+ }
395
433
}
396
434
397
435
trait Checking {
@@ -539,6 +577,10 @@ trait Checking {
539
577
errorTree(tpt, ex " Singleton type ${tpt.tpe} is not allowed $where" )
540
578
}
541
579
else tpt
580
+
581
+ /** Verify classes extending AnyVal meet the requirements */
582
+ def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) =
583
+ Checking .checkDerivedValueClass(clazz, stats)
542
584
}
543
585
544
586
trait NoChecking extends Checking {
@@ -554,4 +596,5 @@ trait NoChecking extends Checking {
554
596
override def checkParentCall (call : Tree , caller : ClassSymbol )(implicit ctx : Context ) = ()
555
597
override def checkSimpleKinded (tpt : Tree )(implicit ctx : Context ): Tree = tpt
556
598
override def checkNotSingleton (tpt : Tree , where : String )(implicit ctx : Context ): Tree = tpt
599
+ override def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) = ()
557
600
}
0 commit comments