@@ -17,6 +17,7 @@ import reporting.trace as log
17
17
import Errors ._
18
18
19
19
import scala .collection .mutable
20
+ import scala .collection .immutable
20
21
import scala .annotation .tailrec
21
22
22
23
object Semantic {
@@ -410,8 +411,8 @@ object Semantic {
410
411
def select (f : Symbol , source : Tree ): Contextual [Result ] =
411
412
value.select(f, source) ++ errors
412
413
413
- def call (meth : Symbol , args : List [ArgInfo ], superType : Type , source : Tree ): Contextual [Result ] =
414
- value.call(meth, args, superType, source) ++ errors
414
+ def call (meth : Symbol , args : List [ArgInfo ], receiver : Type , superType : Type , source : Tree ): Contextual [Result ] =
415
+ value.call(meth, args, receiver, superType, source) ++ errors
415
416
416
417
def callConstructor (ctor : Symbol , args : List [ArgInfo ], source : Tree ): Contextual [Result ] =
417
418
value.callConstructor(ctor, args, source) ++ errors
@@ -587,7 +588,7 @@ object Semantic {
587
588
}
588
589
}
589
590
590
- def call (meth : Symbol , args : List [ArgInfo ], superType : Type , source : Tree , needResolve : Boolean = true ): Contextual [Result ] = log(" call " + meth.show + " , args = " + args, printer, (_ : Result ).show) {
591
+ def call (meth : Symbol , args : List [ArgInfo ], receiver : Type , superType : Type , source : Tree , needResolve : Boolean = true ): Contextual [Result ] = log(" call " + meth.show + " , args = " + args, printer, (_ : Result ).show) {
591
592
def checkArgs = args.flatMap(_.promote)
592
593
593
594
def isSyntheticApply (meth : Symbol ) =
@@ -600,6 +601,25 @@ object Semantic {
600
601
|| (meth eq defn.Object_ne )
601
602
|| (meth eq defn.Any_isInstanceOf )
602
603
604
+ def checkArgsWithParametricity () =
605
+ val methodType = atPhaseBeforeTransforms { meth.info.stripPoly }
606
+ var allArgsPromote = true
607
+ var singleParamSet = immutable.HashSet .from(methodType.paramInfoss.flatten.map(_.repeatedToSingle))
608
+ val errors = methodType.paramInfoss.flatten.zip(args).flatMap { (info, arg) =>
609
+ val singleInfo = info.repeatedToSingle
610
+ val isMatchable = defn.NothingType <:< singleInfo && singleInfo <:< defn.MatchableType
611
+ val isTypeParam = singleInfo.isInstanceOf [TypeParamRef ]
612
+ val otherParamContains = singleParamSet.exists( param => { param != singleInfo && param.typeSymbol != defn.ClassTagClass && singleInfo.occursIn(param) } )
613
+ val errors = arg.promote
614
+ allArgsPromote = allArgsPromote && errors.isEmpty
615
+ // A non-hot method argument is allowed if the corresponding parameter type is a
616
+ // type parameter T with Any as its upper bound and Nothing as its lower bound.
617
+ // the other arguments should either correspond to a parameter type that is T
618
+ // or that does not contain T as a component.
619
+ if isTypeParam && ! isMatchable && ! otherParamContains then Nil else errors
620
+ }
621
+ (errors, allArgsPromote)
622
+
603
623
// fast track if the current object is already initialized
604
624
if promoted.isCurrentObjectPromoted then Result (Hot , Nil )
605
625
else if isAlwaysSafe(meth) then Result (Hot , Nil )
@@ -610,7 +630,14 @@ object Semantic {
610
630
val klass = meth.owner.companionClass.asClass
611
631
instantiate(klass, klass.primaryConstructor, args, source)
612
632
else
613
- Result (Hot , checkArgs)
633
+ if meth.isStatic || receiver.isSingleton then
634
+ val (errors, allArgsPromote) = checkArgsWithParametricity()
635
+ if allArgsPromote || errors.nonEmpty then
636
+ Result (Hot , errors)
637
+ else
638
+ Result (Cold , errors)
639
+ else
640
+ Result (Hot , checkArgs)
614
641
615
642
case Cold =>
616
643
val error = CallCold (meth, source, trace.toVector)
@@ -666,7 +693,7 @@ object Semantic {
666
693
}
667
694
668
695
case RefSet (refs) =>
669
- val resList = refs.map(_.call(meth, args, superType, source))
696
+ val resList = refs.map(_.call(meth, args, receiver, superType, source))
670
697
val value2 = resList.map(_.value).join
671
698
val errors = resList.flatMap(_.errors)
672
699
Result (value2, errors)
@@ -946,7 +973,7 @@ object Semantic {
946
973
locally {
947
974
given Trace = trace2
948
975
val args = member.info.paramInfoss.flatten.map(_ => ArgInfo (Hot , EmptyTree ))
949
- val res = warm.call(member, args, superType = NoType , source = member.defTree)
976
+ val res = warm.call(member, args, receiver = NoType , superType = NoType , source = member.defTree)
950
977
buffer ++= res.ensureHot(msg, source).errors
951
978
}
952
979
else
@@ -1126,14 +1153,14 @@ object Semantic {
1126
1153
case Select (supert : Super , _) =>
1127
1154
val SuperType (thisTp, superTp) = supert.tpe
1128
1155
val thisValue2 = resolveThis(thisTp.classSymbol.asClass, thisV, klass, ref)
1129
- Result (thisValue2, errors).call(ref.symbol, args, superTp, expr)
1156
+ Result (thisValue2, errors).call(ref.symbol, args, thisTp, superTp, expr)
1130
1157
1131
1158
case Select (qual, _) =>
1132
1159
val res = eval(qual, thisV, klass) ++ errors
1133
1160
if ref.symbol.isConstructor then
1134
1161
res.callConstructor(ref.symbol, args, source = expr)
1135
1162
else
1136
- res.call(ref.symbol, args, superType = NoType , source = expr)
1163
+ res.call(ref.symbol, args, receiver = qual.tpe, superType = NoType , source = expr)
1137
1164
1138
1165
case id : Ident =>
1139
1166
id.tpe match
@@ -1142,13 +1169,13 @@ object Semantic {
1142
1169
val enclosingClass = id.symbol.owner.enclosingClass.asClass
1143
1170
val thisValue2 = resolveThis(enclosingClass, thisV, klass, id)
1144
1171
// local methods are not a member, but we can reuse the method `call`
1145
- thisValue2.call(id.symbol, args, superType = NoType , expr, needResolve = false )
1172
+ thisValue2.call(id.symbol, args, receiver = NoType , superType = NoType , expr, needResolve = false )
1146
1173
case TermRef (prefix, _) =>
1147
1174
val res = cases(prefix, thisV, klass, id) ++ errors
1148
1175
if id.symbol.isConstructor then
1149
1176
res.callConstructor(id.symbol, args, source = expr)
1150
1177
else
1151
- res.call(id.symbol, args, superType = NoType , source = expr)
1178
+ res.call(id.symbol, args, receiver = prefix, superType = NoType , source = expr)
1152
1179
1153
1180
case Select (qualifier, name) =>
1154
1181
val qualRes = eval(qualifier, thisV, klass)
0 commit comments