@@ -3730,9 +3730,47 @@ object Types extends TypeUtils {
3730
3730
def integrate (tparams : List [ParamInfo ], tp : Type )(using Context ): Type =
3731
3731
(tparams : @ unchecked) match {
3732
3732
case LambdaParam (lam, _) :: _ => tp.subst(lam, this ) // This is where the precondition is necessary.
3733
- case params : List [Symbol @ unchecked] => tp.subst (params, paramRefs)
3733
+ case params : List [Symbol @ unchecked] => IntegrateMap (params, paramRefs)(tp )
3734
3734
}
3735
3735
3736
+ /** A map that replaces references to symbols in `params` by the types in
3737
+ * `paramRefs`.
3738
+ *
3739
+ * It is similar to [[Substituters#subst ]] but avoids reloading denotations
3740
+ * of named types by overriding `derivedSelect`.
3741
+ *
3742
+ * This is needed because during integration, [[TermParamRef ]]s refer to a
3743
+ * [[LambdaType ]] that is not yet fully constructed, in particular for wich
3744
+ * `paramInfos` is `null`. In that case all [[TermParamRef ]]s have
3745
+ * [[NoType ]] as underlying type. Reloading denotions of selections
3746
+ * involving such [[TermParamRef ]]s in [[NamedType#withPrefix ]] could then
3747
+ * result in a [[NoDenotation ]], which would make later disambiguation of
3748
+ * overloads impossible. See `tests/pos/annot-17242.scala` for example.
3749
+ */
3750
+ private class IntegrateMap (from : List [Symbol ], to : List [Type ])(using Context ) extends TypeMap :
3751
+ override def apply (tp : Type ) =
3752
+ // Same implementation as in `SubstMap`, except the `derivedSelect` in
3753
+ // the `NamedType` case, and the default case that just calls `mapOver`.
3754
+ tp match
3755
+ case tp : NamedType =>
3756
+ val sym = tp.symbol
3757
+ var fs = from
3758
+ var ts = to
3759
+ while (fs.nonEmpty && ts.nonEmpty) {
3760
+ if (fs.head eq sym) return ts.head
3761
+ fs = fs.tail
3762
+ ts = ts.tail
3763
+ }
3764
+ if (tp.prefix `eq` NoPrefix ) tp
3765
+ else derivedSelect(tp, apply(tp.prefix))
3766
+ case _ : BoundType | _ : ThisType => tp
3767
+ case _ => mapOver(tp)
3768
+
3769
+ override final def derivedSelect (tp : NamedType , pre : Type ): Type =
3770
+ if tp.prefix eq pre then tp
3771
+ else if tp.symbol.exists then NamedType (pre, tp.name, tp.denot.asSeenFrom(pre))
3772
+ else NamedType (pre, tp.name)
3773
+
3736
3774
final def derivedLambdaType (paramNames : List [ThisName ] = this .paramNames,
3737
3775
paramInfos : List [PInfo ] = this .paramInfos,
3738
3776
resType : Type = this .resType)(using Context ): This =
@@ -5939,14 +5977,7 @@ object Types extends TypeUtils {
5939
5977
}
5940
5978
}
5941
5979
5942
- private def treeTypeMap = new TreeTypeMap (
5943
- typeMap = this ,
5944
- // Using `ConservativeTreeCopier` is needed when copying dependent annoted
5945
- // types, where we can refer to a previous parameter represented as
5946
- // `TermParamRef` that has no underlying type yet.
5947
- // See tests/pos/annot-17242.scala.
5948
- cpy = ConservativeTreeCopier ()
5949
- )
5980
+ private def treeTypeMap = new TreeTypeMap (typeMap = this )
5950
5981
5951
5982
def mapOver (syms : List [Symbol ]): List [Symbol ] = mapSymbols(syms, treeTypeMap)
5952
5983
0 commit comments