@@ -8,7 +8,7 @@ import Symbols.*, Types.*, Contexts.*, Flags.*, Names.*, NameOps.*, NameKinds.*
8
8
import StdNames .* , Denotations .* , Phases .* , SymDenotations .*
9
9
import NameKinds .DefaultGetterName
10
10
import util .Spans .*
11
- import scala .collection .mutable
11
+ import scala .collection .{ mutable , immutable }
12
12
import ast .*
13
13
import MegaPhase .*
14
14
import config .Printers .{checks , noPrinter , capt }
@@ -368,6 +368,52 @@ object RefChecks {
368
368
&& atPhase(typerPhase):
369
369
loop(member.info.paramInfoss, other.info.paramInfoss)
370
370
371
+ /** A map of all occurrences of `into` in a member type.
372
+ * Key: number of parameter carrying `into` annotation(s)
373
+ * Value: A list of all depths of into annotations, where each
374
+ * function arrow increases the depth.
375
+ * Example:
376
+ * def foo(x: into A, y: => [X] => into (x: X) => into B): C
377
+ * produces the map
378
+ * (0 -> List(0), 1 -> List(1, 2))
379
+ */
380
+ type IntoOccurrenceMap = immutable.Map [Int , List [Int ]]
381
+
382
+ def intoOccurrences (tp : Type ): IntoOccurrenceMap =
383
+
384
+ def traverseInfo (depth : Int , tp : Type ): List [Int ] = tp match
385
+ case AnnotatedType (tp, annot) if annot.symbol == defn.IntoParamAnnot =>
386
+ depth :: traverseInfo(depth, tp)
387
+ case AppliedType (tycon, arg :: Nil ) if tycon.typeSymbol == defn.RepeatedParamClass =>
388
+ traverseInfo(depth, arg)
389
+ case defn.FunctionOf (_, resType, _) =>
390
+ traverseInfo(depth + 1 , resType)
391
+ case RefinedType (parent, rname, mt : MethodOrPoly ) =>
392
+ traverseInfo(depth, mt)
393
+ case tp : MethodOrPoly =>
394
+ traverseInfo(depth + 1 , tp.resType)
395
+ case tp : ExprType =>
396
+ traverseInfo(depth, tp.resType)
397
+ case _ =>
398
+ Nil
399
+
400
+ def traverseParams (n : Int , formals : List [Type ], acc : IntoOccurrenceMap ): IntoOccurrenceMap =
401
+ if formals.isEmpty then acc
402
+ else
403
+ val occs = traverseInfo(0 , formals.head)
404
+ traverseParams(n + 1 , formals.tail, if occs.isEmpty then acc else acc + (n -> occs))
405
+
406
+ def traverse (n : Int , tp : Type , acc : IntoOccurrenceMap ): IntoOccurrenceMap = tp match
407
+ case tp : PolyType =>
408
+ traverse(n, tp.resType, acc)
409
+ case tp : MethodType =>
410
+ traverse(n + tp.paramInfos.length, tp.resType, traverseParams(n, tp.paramInfos, acc))
411
+ case _ =>
412
+ acc
413
+
414
+ traverse(0 , tp, immutable.Map .empty)
415
+ end intoOccurrences
416
+
371
417
val checker =
372
418
if makeOverridingPairsChecker == null then OverridingPairsChecker (clazz, self)
373
419
else makeOverridingPairsChecker(clazz, self)
@@ -572,6 +618,8 @@ object RefChecks {
572
618
overrideError(i " needs to be declared with @targetName( ${" \" " }${other.targetName}${" \" " }) so that external names match " )
573
619
else
574
620
overrideError(" cannot have a @targetName annotation since external names would be different" )
621
+ else if intoOccurrences(memberTp(self)) != intoOccurrences(otherTp(self)) then
622
+ overrideError(" has different occurrences of `into` modifiers" , compareTypes = true )
575
623
else if other.is(ParamAccessor ) && ! isInheritedAccessor(member, other) then // (1.12)
576
624
report.errorOrMigrationWarning(
577
625
em " cannot override val parameter ${other.showLocated}" ,
@@ -1002,9 +1050,9 @@ object RefChecks {
1002
1050
end checkNoPrivateOverrides
1003
1051
1004
1052
def checkVolatile (sym : Symbol )(using Context ): Unit =
1005
- if sym.isVolatile && ! sym.is(Mutable ) then
1053
+ if sym.isVolatile && ! sym.is(Mutable ) then
1006
1054
report.warning(VolatileOnVal (), sym.srcPos)
1007
-
1055
+
1008
1056
/** Check that unary method definition do not receive parameters.
1009
1057
* They can only receive inferred parameters such as type parameters and implicit parameters.
1010
1058
*/
0 commit comments