@@ -35,12 +35,21 @@ 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 => normalizedCompatible(tp, pt, keepConstraint = false )
49+ case _ => testCompat
50+ }
51+ else ctx.test(implicit ctx => testCompat)
52+ }
4453
4554 private def disregardProto (pt : Type )(implicit ctx : Context ): Boolean = pt.dealias match {
4655 case _ : OrType => true
@@ -89,7 +98,7 @@ object ProtoTypes {
8998
9099 /** A trait for prototypes that match all types */
91100 trait MatchAlways extends ProtoType {
92- def isMatchedBy (tp1 : Type )(implicit ctx : Context ): Boolean = true
101+ def isMatchedBy (tp1 : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = true
93102 def map (tm : TypeMap )(implicit ctx : Context ): ProtoType = this
94103 def fold [T ](x : T , ta : TypeAccumulator [T ])(implicit ctx : Context ): T = x
95104 override def toString : String = getClass.toString
@@ -131,13 +140,13 @@ object ProtoTypes {
131140 case _ => false
132141 }
133142
134- override def isMatchedBy (tp1 : Type )(implicit ctx : Context ): Boolean = {
143+ override def isMatchedBy (tp1 : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
135144 name == nme.WILDCARD || hasUnknownMembers(tp1) ||
136145 {
137146 val mbr = if (privateOK) tp1.member(name) else tp1.nonPrivateMember(name)
138147 def qualifies (m : SingleDenotation ) =
139148 memberProto.isRef(defn.UnitClass ) ||
140- tp1.isValueType && compat.normalizedCompatible(NamedType (tp1, name, m), memberProto)
149+ tp1.isValueType && compat.normalizedCompatible(NamedType (tp1, name, m), memberProto, keepConstraint )
141150 // Note: can't use `m.info` here because if `m` is a method, `m.info`
142151 // loses knowledge about `m`'s default arguments.
143152 mbr match { // hasAltWith inlined for performance
@@ -234,8 +243,11 @@ object ProtoTypes {
234243 extends UncachedGroundType with ApplyingProto with FunOrPolyProto {
235244 override def resultType (implicit ctx : Context ): Type = resType
236245
237- def isMatchedBy (tp : Type )(implicit ctx : Context ): Boolean =
238- typer.isApplicable(tp, Nil , unforcedTypedArgs, resultType)
246+ def isMatchedBy (tp : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
247+ val args = unforcedTypedArgs
248+ def isPoly (tree : Tree ) = tree.tpe.widenSingleton.isInstanceOf [PolyType ]
249+ typer.isApplicable(tp, Nil , args, resultType, keepConstraint && ! args.exists(isPoly))
250+ }
239251
240252 def derivedFunProto (args : List [untpd.Tree ] = this .args, resultType : Type , typer : Typer = this .typer): FunProto =
241253 if ((args eq this .args) && (resultType eq this .resultType) && (typer eq this .typer)) this
@@ -379,7 +391,7 @@ object ProtoTypes {
379391
380392 override def resultType (implicit ctx : Context ): Type = resType
381393
382- def isMatchedBy (tp : Type )(implicit ctx : Context ): Boolean =
394+ def isMatchedBy (tp : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean =
383395 ctx.typer.isApplicable(tp, argType :: Nil , resultType) || {
384396 resType match {
385397 case SelectionProto (name : TermName , mbrType, _, _) =>
@@ -422,7 +434,7 @@ object ProtoTypes {
422434
423435 override def resultType (implicit ctx : Context ): Type = resType
424436
425- override def isMatchedBy (tp : Type )(implicit ctx : Context ): Boolean = {
437+ override def isMatchedBy (tp : Type , keepConstraint : Boolean )(implicit ctx : Context ): Boolean = {
426438 def isInstantiatable (tp : Type ) = tp.widen match {
427439 case tp : PolyType => tp.paramNames.length == targs.length
428440 case _ => false
0 commit comments