@@ -22,10 +22,10 @@ import NameKinds.DefaultGetterName
2222import ProtoTypes ._
2323import Inferencing ._
2424import transform .TypeUtils ._
25- import Nullables .given
25+ import Nullables .{ postProcessByNameArgs , given }
2626
2727import collection .mutable
28- import config .Printers .{overload , typr , unapp , nullables }
28+ import config .Printers .{overload , typr , unapp }
2929import TypeApplications ._
3030
3131import reporting .diagnostic .Message
@@ -1047,73 +1047,6 @@ trait Applications extends Compatibility {
10471047 tree
10481048 }
10491049
1050- /** Post process all arguments to by-name parameters by removing any not-null
1051- * info that was used when typing them. Concretely:
1052- * If an argument corresponds to a call-by-name parameter, drop all
1053- * embedded not-null assertions of the form `x.$asInstanceOf[x.type & T]`
1054- * where `x` is a reference to a mutable variable. If the argument still typechecks
1055- * with the removed assertions and is still compatible with the formal parameter,
1056- * keep it. Otherwise issue an error that the call-by-name argument was typed using
1057- * flow assumptions about mutable variables and suggest that it is enclosed
1058- * in a `byName(...)` call instead.
1059- */
1060- private def postProcessByNameArgs (fn : TermRef , app : Tree )(given ctx : Context ): Tree =
1061- fn.widen match
1062- case mt : MethodType if mt.paramInfos.exists(_.isInstanceOf [ExprType ]) =>
1063- app match
1064- case Apply (fn, args) =>
1065- val dropNotNull = new TreeMap with
1066- override def transform (t : Tree )(given Context ) = t match
1067- case AssertNotNull (t0) if t0.symbol.is(Mutable ) =>
1068- nullables.println(i " dropping $t" )
1069- transform(t0)
1070- case t : ValDef if ! t.symbol.is(Lazy ) => super .transform(t)
1071- case t : MemberDef =>
1072- // stop here since embedded references to mutable variables would be
1073- // out of order, so they would not asserted ot be not-null anyway.
1074- // @see Nullables.usedOutOfOrder
1075- t
1076- case _ => super .transform(t)
1077-
1078- object retyper extends ReTyper with
1079- override def typedUnadapted (t : untpd.Tree , pt : Type , locked : TypeVars )(implicit ctx : Context ): Tree = t match
1080- case t : ValDef if ! t.symbol.is(Lazy ) => super .typedUnadapted(t, pt, locked)
1081- case t : MemberDef => promote(t)
1082- case _ => super .typedUnadapted(t, pt, locked)
1083-
1084- def postProcess (formal : Type , arg : Tree ): Tree =
1085- val arg1 = dropNotNull.transform(arg)
1086- if arg1 eq arg then arg
1087- else
1088- val nestedCtx = ctx.fresh.setNewTyperState()
1089- val arg2 = retyper.typed(arg1, formal)(given nestedCtx )
1090- if nestedCtx.reporter.hasErrors || ! (arg2.tpe <:< formal) then
1091- ctx.error(em """ This argument was typed using flow assumptions about mutable variables
1092- |but it is passed to a by-name parameter where such flow assumptions are unsound.
1093- |Wrapping the argument in `byName(...)` fixes the problem by disabling the flow assumptions.
1094- |
1095- |`byName` needs to be imported from the `scala.compiletime` package. """ ,
1096- arg.sourcePos)
1097- arg
1098- else
1099- nestedCtx.typerState.commit()
1100- arg2
1101-
1102- def recur (formals : List [Type ], args : List [Tree ]): List [Tree ] = (formals, args) match
1103- case (formal :: formalsRest, arg :: argsRest) =>
1104- val arg1 = postProcess(formal.widenExpr.repeatedToSingle, arg)
1105- val argsRest1 = recur(
1106- if formal.isRepeatedParam then formals else formalsRest,
1107- argsRest)
1108- if (arg1 eq arg) && (argsRest1 eq argsRest) then args
1109- else arg1 :: argsRest1
1110- case _ => args
1111-
1112- tpd.cpy.Apply (app)(fn, recur(mt.paramInfos, args))
1113- case _ => app
1114- case _ => app
1115- end postProcessByNameArgs
1116-
11171050 def typedUnApply (tree : untpd.Apply , selType : Type )(implicit ctx : Context ): Tree = {
11181051 record(" typedUnApply" )
11191052 val Apply (qual, args) = tree
0 commit comments