@@ -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
*/
@@ -406,6 +407,43 @@ object Checking {
406
407
notPrivate.errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) }
407
408
info
408
409
}
410
+
411
+ /** Verify classes extending AnyVal meet the requirements */
412
+ def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) = {
413
+ def checkValueClassMember (stat : Tree ) = stat match {
414
+ case _ : ValDef if ! stat.symbol.is(ParamAccessor ) =>
415
+ ctx.error(s " value class may not define non-parameter field " , stat.pos)
416
+ case d : DefDef if d.symbol.isConstructor =>
417
+ ctx.error(s " value class may not define secondary constructor " , stat.pos)
418
+ case _ : MemberDef | _ : Import | EmptyTree =>
419
+ // ok
420
+ case _ =>
421
+ ctx.error(s " value class may not contain initialization statements " , stat.pos)
422
+ }
423
+ if (isDerivedValueClass(clazz)) {
424
+ if (clazz.is(Trait ))
425
+ ctx.error(" Only classes (not traits) are allowed to extend AnyVal" , clazz.pos)
426
+ if (clazz.is(Abstract ))
427
+ ctx.error(" `abstract' modifier cannot be used with value classes" , clazz.pos)
428
+ if (! clazz.isStatic)
429
+ ctx.error(s " value class may not be a ${if (clazz.owner.isTerm) " local class" else " member of another class" }" , clazz.pos)
430
+ if (isCyclic(clazz.asClass))
431
+ ctx.error(" value class cannot wrap itself" , clazz.pos)
432
+ else {
433
+ val clParamAccessors = clazz.asClass.paramAccessors.filter(_.isTerm)
434
+ clParamAccessors match {
435
+ case List (param) =>
436
+ if (param.is(Mutable ))
437
+ ctx.error(" value class parameter must not be a var" , param.pos)
438
+
439
+ case _ =>
440
+ ctx.error(" value class needs to have exactly one val parameter" , clazz.pos)
441
+ }
442
+ }
443
+ stats.foreach(checkValueClassMember)
444
+ }
445
+
446
+ }
409
447
}
410
448
411
449
trait Checking {
@@ -553,6 +591,10 @@ trait Checking {
553
591
errorTree(tpt, ex " Singleton type ${tpt.tpe} is not allowed $where" )
554
592
}
555
593
else tpt
594
+
595
+ /** Verify classes extending AnyVal meet the requirements */
596
+ def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) =
597
+ Checking .checkDerivedValueClass(clazz, stats)
556
598
}
557
599
558
600
trait NoChecking extends Checking {
@@ -568,4 +610,5 @@ trait NoChecking extends Checking {
568
610
override def checkParentCall (call : Tree , caller : ClassSymbol )(implicit ctx : Context ) = ()
569
611
override def checkSimpleKinded (tpt : Tree )(implicit ctx : Context ): Tree = tpt
570
612
override def checkNotSingleton (tpt : Tree , where : String )(implicit ctx : Context ): Tree = tpt
613
+ override def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) = ()
571
614
}
0 commit comments