@@ -848,17 +848,22 @@ trait Applications extends Compatibility { self: Typer =>
848
848
else (sym1 is Module ) && isDerived(sym1.companionClass, sym2)
849
849
850
850
/** Is alternative `alt1` with type `tp1` as specific as alternative
851
- * `alt2` with type `tp2` ? This is the case if
851
+ * `alt2` with type `tp2` ?
852
852
*
853
- * 1. `tp2` is a method or poly type but `tp1` isn't, or `tp1` is nullary.
854
- * 2. `tp2` and `tp1` are method or poly types and `tp2` can be applied to the parameters of `tp1`.
855
- * 3. Neither `tp1` nor `tp2` are method or poly types and `tp1` is compatible with `tp2`.
853
+ * 1. A method `alt1` of type (p1: T1, ..., pn: Tn)U is as specific as `alt2`
854
+ * if `alt2` is applicable to arguments (p1, ..., pn) of types T1,...,Tn
855
+ * or if `alt1` is nullary.
856
+ * 2. A polymorphic member of type [a1 >: L1 <: U1, ..., an >: Ln <: Un]T is as
857
+ * specific as `alt2` of type `tp2` if T is as specific as `tp2` under the
858
+ * assumption that for i = 1,...,n each ai is an abstract type name bounded
859
+ * from below by Li and from above by Ui.
860
+ * 3. A member of any other type `tp1` is:
861
+ * a. always as specific as a method or a polymorphic method.
862
+ * b. as specific as a member of any other type `tp2` if `tp1` is compatible
863
+ * with `tp2`.
856
864
*/
857
865
def isAsSpecific (alt1 : TermRef , tp1 : Type , alt2 : TermRef , tp2 : Type ): Boolean = ctx.traceIndented(i " isAsSpecific $tp1 $tp2" , overload) { tp1 match {
858
- case tp1 : PolyType =>
859
- val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags , tp1.instantiateBounds)
860
- isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
861
- case tp1 : MethodType =>
866
+ case tp1 : MethodType => // (1)
862
867
def repeatedToSingle (tp : Type ): Type = tp match {
863
868
case tp @ ExprType (tp1) => tp.derivedExprType(repeatedToSingle(tp1))
864
869
case _ => if (tp.isRepeatedParam) tp.argTypesHi.head else tp
@@ -868,10 +873,22 @@ trait Applications extends Compatibility { self: Typer =>
868
873
else tp1.paramTypes
869
874
isApplicable(alt2, formals1, WildcardType ) ||
870
875
tp1.paramTypes.isEmpty && tp2.isInstanceOf [MethodOrPoly ]
871
- case _ =>
876
+ case tp1 : PolyType => // (2)
877
+ val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags , tp1.instantiateBounds)
878
+ isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
879
+ case _ => // (3)
872
880
tp2 match {
873
- case tp2 : MethodOrPoly => true
874
- case _ => isCompatible(tp1, tp2)
881
+ case tp2 : MethodType => true // (3a)
882
+ case tp2 : PolyType if tp2.isPolymorphicMethodType => true // (3a)
883
+ case tp2 : PolyType => // (3b)
884
+ val nestedCtx = ctx.fresh.setExploreTyperState
885
+
886
+ {
887
+ implicit val ctx : Context = nestedCtx
888
+ isCompatible(tp1, constrained(tp2).resultType)
889
+ }
890
+ case _ => // (3b)
891
+ isCompatible(tp1, tp2)
875
892
}
876
893
}}
877
894
0 commit comments