@@ -80,25 +80,34 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
80
80
81
81
object transformTypes extends TreeTraverser :
82
82
83
- class SubstParams (from : List [Symbol ], to : MethodOrPoly )(using Context )
83
+ // Substitute parameter symbols in `from` to paramRefs in corresponding
84
+ // method or poly types `to`. We use a single BiTypeMap to do everything.
85
+ class SubstParams (from : List [List [Symbol ]], to : List [LambdaType ])(using Context )
84
86
extends DeepTypeMap , BiTypeMap :
85
- private val paramRefs = to.paramRefs
86
- private val fromRefs = from.map(_.namedType)
87
87
88
88
def apply (t : Type ): Type = t match
89
89
case t : NamedType =>
90
90
val sym = t.symbol
91
- def recur (from : List [Symbol ], to : List [Type ]): Type =
92
- if from.isEmpty then t
93
- else if sym eq from.head then to.head
94
- else recur(from.tail, to.tail)
95
- recur(from, paramRefs)
91
+ def outer (froms : List [List [Symbol ]], tos : List [LambdaType ]): Type =
92
+ def inner (from : List [Symbol ], to : List [ParamRef ]): Type =
93
+ if from.isEmpty then outer(froms.tail, tos.tail)
94
+ else if sym eq from.head then to.head
95
+ else inner(from.tail, to.tail)
96
+ if tos.isEmpty then t
97
+ else inner(froms.head, tos.head.paramRefs)
98
+ outer(from, to)
96
99
case _ =>
97
100
mapOver(t)
98
101
99
102
def inverse (t : Type ): Type = t match
100
- case t : ParamRef if t.binder eq to => fromRefs(t.paramNum)
101
- case _ => mapOver(t)
103
+ case t : ParamRef =>
104
+ def recur (from : List [LambdaType ], to : List [List [Symbol ]]): Type =
105
+ if from.isEmpty then t
106
+ else if t.binder eq from.head then to.head(t.paramNum).namedType
107
+ else recur(from.tail, to.tail)
108
+ recur(to, from)
109
+ case _ =>
110
+ mapOver(t)
102
111
end SubstParams
103
112
104
113
def traverse (tree : Tree )(using Context ) =
@@ -108,27 +117,37 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
108
117
transformType(tree.tpe, tree.isInstanceOf [InferredTypeTree ]).rememberFor(tree)
109
118
case tree : ValOrDefDef =>
110
119
val sym = tree.symbol
111
- def integrateRT (restp : Type , info : Type , psymss : List [List [Symbol ]], pinfoss : List [List [Type ]]): Type = info match
112
- case mt : MethodOrPoly =>
113
- val psyms = psymss.head
114
- val subst = SubstParams (psyms, mt)
115
- mt.derivedLambdaType(
116
- paramInfos =
117
- if psyms.exists(isUpdated) then pinfoss.head.asInstanceOf [List [mt.PInfo ]]
118
- else mt.paramInfos,
119
- resType = integrateRT(
120
- subst(restp), mt.resType, psymss.tail, pinfoss.tail.nestedMap(subst)))
121
- case info : ExprType =>
122
- info.derivedExprType(resType = restp)
123
- case _ =>
124
- restp
120
+
121
+ // replace an existing symbol info with inferred types
122
+ def integrateRT (
123
+ info : Type , // symbol info to replace
124
+ psymss : List [List [Symbol ]], // the local (type and trem) parameter symbols corresponding to `info`
125
+ prevPsymss : List [List [Symbol ]], // the local parameter symbols seen previously in reverse order
126
+ prevLambdas : List [LambdaType ] // the outer method and polytypes generated previously in reverse order
127
+ ): Type =
128
+ info match
129
+ case mt : MethodOrPoly =>
130
+ val psyms = psymss.head
131
+ mt.companion(mt.paramNames)(
132
+ mt1 =>
133
+ if ! psyms.exists(isUpdated) && ! mt.isParamDependent && prevLambdas.isEmpty then
134
+ mt.paramInfos
135
+ else
136
+ val subst = SubstParams (psyms :: prevPsymss, mt1 :: prevLambdas)
137
+ psyms.map(psym => subst(psym.info).asInstanceOf [mt.PInfo ]),
138
+ mt1 =>
139
+ integrateRT(mt.resType, psymss.tail, psyms :: prevPsymss, mt1 :: prevLambdas)
140
+ )
141
+ case info : ExprType =>
142
+ info.derivedExprType(resType =
143
+ integrateRT(info.resType, psymss, prevPsymss, prevLambdas))
144
+ case _ =>
145
+ val restp = knownType(tree.tpt)
146
+ if prevLambdas.isEmpty then restp
147
+ else SubstParams (prevPsymss, prevLambdas)(restp)
148
+
125
149
if tree.tpt.hasAttachment(RecheckedType ) && ! sym.isConstructor then
126
- val newInfo = integrateRT(
127
- knownType(tree.tpt),
128
- sym.info,
129
- sym.paramSymss,
130
- sym.paramSymss.nestedMap(_.info)
131
- )
150
+ val newInfo = integrateRT(sym.info, sym.paramSymss, Nil , Nil )
132
151
.showing(i " update info $sym: ${sym.info} --> $result" , recheckr)
133
152
if newInfo ne sym.info then
134
153
val completer = new LazyType :
0 commit comments