@@ -71,10 +71,17 @@ object RefChecks {
71
71
}
72
72
}
73
73
74
- /** Check that self type of this class conforms to self types of parents */
75
- private def checkSelfType (clazz : Symbol )(implicit ctx : Context ): Unit = clazz.info match {
74
+ /** Check that final and sealed restrictions on class parents
75
+ * and that self type of this class conforms to self types of parents.
76
+ */
77
+ private def checkParents (clazz : Symbol )(implicit ctx : Context ): Unit = clazz.info match {
76
78
case cinfo : ClassInfo =>
77
79
for (parent <- cinfo.classParents) {
80
+ val pclazz = parent.classSymbol
81
+ if (pclazz.is(Final ))
82
+ ctx.error(d " cannot extend final $pclazz" , clazz.pos)
83
+ if (pclazz.is(Sealed ) && pclazz.associatedFile != clazz.associatedFile)
84
+ ctx.error(d " cannot extend sealed $pclazz in different compilation unit " , clazz.pos)
78
85
val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol)
79
86
if (pself.exists && ! (cinfo.selfType <:< pself))
80
87
ctx.error(d " illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}" , clazz.pos)
@@ -648,13 +655,27 @@ object RefChecks {
648
655
}
649
656
650
657
/** Verify classes extending AnyVal meet the requirements */
651
- private def checkAnyValSubclass (clazz : Symbol )(implicit ctx : Context ) =
658
+ private def checkDerivedValueClass (clazz : Symbol , stats : List [Tree ])(implicit ctx : Context ) = {
659
+ def checkValueClassMember (stat : Tree ) = stat match {
660
+ case _ : ValDef if ! stat.symbol.is(ParamAccessor ) =>
661
+ ctx.error(s " value class may not define non-parameter field " , stat.pos)
662
+ case _ : DefDef if stat.symbol.isConstructor =>
663
+ ctx.error(s " value class may not define secondary constructor " , stat.pos)
664
+ case _ : MemberDef | _ : Import | EmptyTree =>
665
+ // ok
666
+ case _ =>
667
+ ctx.error(s " value class may not contain initialization statements " , stat.pos)
668
+ }
652
669
if (isDerivedValueClass(clazz)) {
653
670
if (clazz.is(Trait ))
654
671
ctx.error(" Only classes (not traits) are allowed to extend AnyVal" , clazz.pos)
655
- else if (clazz.is(Abstract ))
672
+ if (clazz.is(Abstract ))
656
673
ctx.error(" `abstract' modifier cannot be used with value classes" , clazz.pos)
674
+ if (! clazz.isStatic)
675
+ ctx.error(" value class cannot be an inner class" , clazz.pos)
676
+ stats.foreach(checkValueClassMember)
657
677
}
678
+ }
658
679
659
680
type LevelAndIndex = immutable.Map [Symbol , (LevelInfo , Int )]
660
681
@@ -701,7 +722,7 @@ import RefChecks._
701
722
* - only one overloaded alternative defines default arguments
702
723
* - applyDynamic methods are not overloaded
703
724
* - all overrides conform to rules laid down by `checkAllOverrides`.
704
- * - any value classes conform to rules laid down by `checkAnyValSubClass `.
725
+ * - any value classes conform to rules laid down by `checkDerivedValueClass `.
705
726
* - this(...) constructor calls do not forward reference other definitions in their block (not even lazy vals).
706
727
* - no forward reference in a local block jumps over a non-lazy val definition.
707
728
* - a class and its companion object do not both define a class or module with the same name.
@@ -768,10 +789,10 @@ class RefChecks extends MiniPhase { thisTransformer =>
768
789
override def transformTemplate (tree : Template )(implicit ctx : Context , info : TransformerInfo ) = {
769
790
val cls = ctx.owner
770
791
checkOverloadedRestrictions(cls)
771
- checkSelfType (cls)
792
+ checkParents (cls)
772
793
checkCompanionNameClashes(cls)
773
794
checkAllOverrides(cls)
774
- checkAnyValSubclass (cls)
795
+ checkDerivedValueClass (cls, tree.body )
775
796
tree
776
797
}
777
798
0 commit comments