diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2015-11-17 23:41:02 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2015-11-18 03:32:01 +0100 |
commit | 7d76151109db168d025dfc0f6501fa7694e17053 (patch) | |
tree | 2cc70c0eadab25304c03aa2d494097e60bac077a /src/dotty/tools/dotc/typer/Applications.scala | |
parent | 945334c8affd0dc5067316447e8384f1ea7025ad (diff) | |
download | dotty-7d76151109db168d025dfc0f6501fa7694e17053.tar.gz dotty-7d76151109db168d025dfc0f6501fa7694e17053.tar.bz2 dotty-7d76151109db168d025dfc0f6501fa7694e17053.zip |
Fix ambiguity errors with polymorphic implicits
Previously, `isAsSpecific(alt1, tp1, alt2, tp2)` did not handle
having `tp2` be a polymorphic non-method type like `[A]Foo[A]`.
Also update the documentation of `isAsSpecific` to account for this
change, the new documentation is based on SLS ยง 6.26.3 but
adapted to reflect the code.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 64047cc1e..c57dd7aab 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -848,11 +848,19 @@ trait Applications extends Compatibility { self: Typer => else (sym1 is Module) && isDerived(sym1.companionClass, sym2) /** Is alternative `alt1` with type `tp1` as specific as alternative - * `alt2` with type `tp2` ? This is the case if + * `alt2` with type `tp2` ? * - * 1. `tp2` is a method or poly type but `tp1` isn't, or `tp1` is nullary. - * 2. `tp2` and `tp1` are method or poly types and `tp2` can be applied to the parameters of `tp1`. - * 3. Neither `tp1` nor `tp2` are method or poly types and `tp1` is compatible with `tp2`. + * 1. A method `alt1` of type (p1: T1, ..., pn: Tn)U is as specific as `alt2` + * if `alt2` is applicable to arguments (p1, ..., pn) of types T1,...,Tn + * or if `alt1` is nullary. + * 2. A polymorphic member of type [a1 >: L1 <: U1, ..., an >: Ln <: Un]T is as + * specific as `alt2` of type `tp2` if T is as specific as `tp2` under the + * assumption that for i = 1,...,n each ai is an abstract type name bounded + * from below by Li and from above by Ui. + * 3. A member of any other type `tp1` is: + * a. always as specific as a method or a polymorphic method. + * b. as specific as a member of any other type `tp2` if `tp1` is compatible + * with `tp2`. */ def isAsSpecific(alt1: TermRef, tp1: Type, alt2: TermRef, tp2: Type): Boolean = ctx.traceIndented(i"isAsSpecific $tp1 $tp2", overload) { tp1 match { case tp1: PolyType => @@ -870,8 +878,17 @@ trait Applications extends Compatibility { self: Typer => tp1.paramTypes.isEmpty && tp2.isInstanceOf[MethodOrPoly] case _ => tp2 match { - case tp2: MethodOrPoly => true - case _ => isCompatible(tp1, tp2) + case tp2: MethodType => true + case tp2: PolyType if tp2.isPolymorphicMethodType => true + case tp2: PolyType => + val nestedCtx = ctx.fresh.setExploreTyperState + + { + implicit val ctx: Context = nestedCtx + isCompatible(tp1, constrained(tp2).resultType) + } + case _ => + isCompatible(tp1, tp2) } }} |