@@ -35,12 +35,28 @@ object ProtoTypes {
3535 def isCompatible (tp : Type , pt : Type )(implicit ctx : Context ): Boolean =
3636 (tp.widenExpr relaxed_<:< pt.widenExpr) || viewExists(tp, pt)
3737
38- /** Test compatibility after normalization in a fresh typerstate. */
39- def normalizedCompatible (tp : Type , pt : Type )(implicit ctx : Context ): Boolean =
40- ctx.test { implicit ctx =>
38+ /** Test compatibility after normalization.
39+ * Do this in a fresh typerstate unless `keepConstraint` is true.
40+ */
41+ def normalizedCompatible (tp : Type , pt : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
42+ def testCompat (implicit ctx : Context ): Boolean = {
4143 val normTp = normalize(tp, pt)
4244 isCompatible(normTp, pt) || pt.isRef(defn.UnitClass ) && normTp.isParameterless
4345 }
46+ if (keepConstraint)
47+ tp.widenSingleton match {
48+ case poly : PolyType =>
49+ // We can't keep the constraint in this case, since we have to add type parameters
50+ // to it, but there's no place to associate them with type variables.
51+ // So we'd get a "inconsistent: no typevars were added to committable constraint"
52+ // assertion failure in `constrained`. To do better, we'd have to change the
53+ // constraint handling architecture so that some type parameters are committable
54+ // and others are not. But that's a whole different ballgame.
55+ normalizedCompatible(tp, pt, keepConstraint = false )
56+ case _ => testCompat
57+ }
58+ else ctx.test(implicit ctx => testCompat)
59+ }
4460
4561 private def disregardProto (pt : Type )(implicit ctx : Context ): Boolean = pt.dealias match {
4662 case _ : OrType => true
@@ -89,7 +105,7 @@ object ProtoTypes {
89105
90106 /** A trait for prototypes that match all types */
91107 trait MatchAlways extends ProtoType {
92- def isMatchedBy (tp1 : Type )(implicit ctx : Context ): Boolean = true
108+ def isMatchedBy (tp1 : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = true
93109 def map (tm : TypeMap )(implicit ctx : Context ): ProtoType = this
94110 def fold [T ](x : T , ta : TypeAccumulator [T ])(implicit ctx : Context ): T = x
95111 override def toString : String = getClass.toString
@@ -131,13 +147,13 @@ object ProtoTypes {
131147 case _ => false
132148 }
133149
134- override def isMatchedBy (tp1 : Type )(implicit ctx : Context ): Boolean = {
150+ override def isMatchedBy (tp1 : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
135151 name == nme.WILDCARD || hasUnknownMembers(tp1) ||
136152 {
137153 val mbr = if (privateOK) tp1.member(name) else tp1.nonPrivateMember(name)
138154 def qualifies (m : SingleDenotation ) =
139155 memberProto.isRef(defn.UnitClass ) ||
140- tp1.isValueType && compat.normalizedCompatible(NamedType (tp1, name, m), memberProto)
156+ tp1.isValueType && compat.normalizedCompatible(NamedType (tp1, name, m), memberProto, keepConstraint )
141157 // Note: can't use `m.info` here because if `m` is a method, `m.info`
142158 // loses knowledge about `m`'s default arguments.
143159 mbr match { // hasAltWith inlined for performance
@@ -234,8 +250,13 @@ object ProtoTypes {
234250 extends UncachedGroundType with ApplyingProto with FunOrPolyProto {
235251 override def resultType (implicit ctx : Context ): Type = resType
236252
237- def isMatchedBy (tp : Type )(implicit ctx : Context ): Boolean =
238- typer.isApplicable(tp, Nil , unforcedTypedArgs, resultType)
253+ def isMatchedBy (tp : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
254+ val args = unforcedTypedArgs
255+ def isPoly (tree : Tree ) = tree.tpe.widenSingleton.isInstanceOf [PolyType ]
256+ // See remark in normalizedCompatible for why we can't keep the constraint
257+ // if one of the arguments has a PolyType.
258+ typer.isApplicable(tp, Nil , args, resultType, keepConstraint && ! args.exists(isPoly))
259+ }
239260
240261 def derivedFunProto (args : List [untpd.Tree ] = this .args, resultType : Type , typer : Typer = this .typer): FunProto =
241262 if ((args eq this .args) && (resultType eq this .resultType) && (typer eq this .typer)) this
@@ -292,11 +313,13 @@ object ProtoTypes {
292313 * with unknown parameter types - this will then cause a
293314 * "missing parameter type" error
294315 */
295- private def typedArgs (force : Boolean ): List [Tree ] = {
296- if (state.typedArgs.size != args.length)
297- state.typedArgs = args.mapconserve(cacheTypedArg(_, typer.typed(_), force))
298- state.typedArgs
299- }
316+ private def typedArgs (force : Boolean ): List [Tree ] =
317+ if (state.typedArgs.size == args.length) state.typedArgs
318+ else {
319+ val args1 = args.mapconserve(cacheTypedArg(_, typer.typed(_), force))
320+ if (force || ! args1.contains(WildcardType )) state.typedArgs = args1
321+ args1
322+ }
300323
301324 def typedArgs : List [Tree ] = typedArgs(force = true )
302325 def unforcedTypedArgs : List [Tree ] = typedArgs(force = false )
@@ -379,7 +402,7 @@ object ProtoTypes {
379402
380403 override def resultType (implicit ctx : Context ): Type = resType
381404
382- def isMatchedBy (tp : Type )(implicit ctx : Context ): Boolean =
405+ def isMatchedBy (tp : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean =
383406 ctx.typer.isApplicable(tp, argType :: Nil , resultType) || {
384407 resType match {
385408 case SelectionProto (name : TermName , mbrType, _, _) =>
@@ -422,7 +445,7 @@ object ProtoTypes {
422445
423446 override def resultType (implicit ctx : Context ): Type = resType
424447
425- override def isMatchedBy (tp : Type )(implicit ctx : Context ): Boolean = {
448+ override def isMatchedBy (tp : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
426449 def isInstantiatable (tp : Type ) = tp.widen match {
427450 case tp : PolyType => tp.paramNames.length == targs.length
428451 case _ => false
0 commit comments