@@ -642,30 +642,49 @@ object ProtoTypes {
642642 def constrained (tl : TypeLambda )(using Context ): TypeLambda =
643643 constrained(tl, EmptyTree )._1
644644
645- def newTypeVar (bounds : TypeBounds )(using Context ): TypeVar = {
645+ /** A new type variable with given bounds for its origin.
646+ * @param represents If exists, the TermParamRef that the TypeVar represents
647+ * in the substitution generated by `resultTypeApprox`
648+ * If `represents` exists, it is stored in the result type of the PolyType
649+ * that backs the TypeVar, to be retrieved by `representedParamRef`.
650+ */
651+ def newTypeVar (bounds : TypeBounds , represents : Type = NoType )(using Context ): TypeVar = {
646652 val poly = PolyType (DepParamName .fresh().toTypeName :: Nil )(
647653 pt => bounds :: Nil ,
648- pt => defn.AnyType )
654+ pt => represents.orElse( defn.AnyType ) )
649655 constrained(poly, untpd.EmptyTree , alwaysAddTypeVars = true )
650656 ._2.head.tpe.asInstanceOf [TypeVar ]
651657 }
652658
653- /** Create a new TypeVar that represents a dependent method parameter singleton */
654- def newDepTypeVar (tp : Type )(using Context ): TypeVar =
655- newTypeVar(TypeBounds .upper(AndType (tp.widenExpr, defn.SingletonClass .typeRef)))
659+ /** If `tvar` represents a parameter of a dependent function generated
660+ * by `newDepVar` called from `resultTypeApprox, the term parameter reference
661+ * for which the variable was substituted. Otherwise, NoType.
662+ */
663+ def representedParamRef (tvar : TypeVar )(using Context ): Type =
664+ if tvar.origin.paramName.is(DepParamName ) then
665+ tvar.origin.binder.resultType match
666+ case ref : TermParamRef => ref
667+ case _ => NoType
668+ else NoType
669+
670+ /** Create a new TypeVar that represents a dependent method parameter singleton `ref` */
671+ def newDepTypeVar (ref : TermParamRef )(using Context ): TypeVar =
672+ newTypeVar(
673+ TypeBounds .upper(AndType (ref.underlying.widenExpr, defn.SingletonClass .typeRef)),
674+ ref)
656675
657676 /** The result type of `mt`, where all references to parameters of `mt` are
658677 * replaced by either wildcards or TypeParamRefs.
659678 */
660679 def resultTypeApprox (mt : MethodType , wildcardOnly : Boolean = false )(using Context ): Type =
661680 if mt.isResultDependent then
662- def replacement (tp : Type ) =
681+ def replacement (ref : TermParamRef ) =
663682 if wildcardOnly
664683 || ctx.mode.is(Mode .TypevarsMissContext )
665- || ! tp .widenExpr.isValueTypeOrWildcard
684+ || ! ref.underlying .widenExpr.isValueTypeOrWildcard
666685 then WildcardType
667- else newDepTypeVar(tp )
668- mt.resultType.substParams(mt, mt.paramInfos .map(replacement))
686+ else newDepTypeVar(ref )
687+ mt.resultType.substParams(mt, mt.paramRefs .map(replacement))
669688 else mt.resultType
670689
671690 /** The normalized form of a type
0 commit comments