-
Notifications
You must be signed in to change notification settings - Fork 1
Review/5108 #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Review/5108 #20
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -538,7 +538,7 @@ trait Implicits { | |
private def checkCompatibility(fast: Boolean, tp0: Type, pt0: Type): Boolean = { | ||
@tailrec def loop(tp: Type, pt: Type): Boolean = tp match { | ||
case mt @ MethodType(params, restpe) => | ||
if (mt.isImplicit) | ||
if (mt.isImplicit) // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The crux: this will now unwrap all implicit method types to get to the result type, so the following works:
|
||
loop(restpe, pt) | ||
else pt match { | ||
case tr @ TypeRef(pre, sym, args) => | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,7 +148,7 @@ trait Infer extends Checkable { | |
} | ||
|
||
def skipImplicit(tp: Type) = tp match { | ||
case mt: MethodType if mt.isImplicit => mt.resultType | ||
case mt: MethodType if mt.isImplicit => mt.resultType // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It is also called from
However, AFAICT the call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain the issue here a little more for me? If I try,
(ie. your second example but with the first parameter list not implicit) I see the exact same error as with both parameter lists implicit,
Are you saying the the call to
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, my reading of this code is that Looks like |
||
case _ => tp | ||
} | ||
|
||
|
@@ -163,7 +163,7 @@ trait Infer extends Checkable { | |
logResult(sm"""|Normalizing PolyType in infer: | ||
| was: $restpe | ||
| now""")(normalize(restpe)) | ||
case mt @ MethodType(_, restpe) if mt.isImplicit => normalize(restpe) | ||
case mt @ MethodType(_, restpe) if mt.isImplicit => normalize(restpe) // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM, will recurse to strip off all implicit param lists. |
||
case mt @ MethodType(_, restpe) if !mt.isDependentMethodType => | ||
if (phase.erasedTypes) FunctionClass(mt.params.length).tpe | ||
else functionType(mt.paramTypes, normalize(restpe)) | ||
|
@@ -366,7 +366,7 @@ trait Infer extends Checkable { | |
// optimize type variables wrt to the implicit formals only; ignore the result type. | ||
// See test pos/jesper.scala | ||
def variance = restpe match { | ||
case mt: MethodType if mt.isImplicit && isFullyDefined(pt) => MethodType(mt.params, AnyTpe) | ||
case mt: MethodType if mt.isImplicit && isFullyDefined(pt) => MethodType(mt.params, AnyTpe) // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM, we'll ignore all implicit param lists, rather than the only one, when approximating the type used to calculate the variance (and direction of solving) of the type params |
||
case _ => restpe | ||
} | ||
def solve() = solvedTypes(tvars, tparams, tparams map varianceInType(variance), upper = false, lubDepth(restpe :: pt :: Nil)) | ||
|
@@ -811,21 +811,21 @@ trait Infer extends Checkable { | |
def onRight = ftpe2 match { | ||
case OverloadedType(pre, alts) => alts forall (alt => isAsSpecific(ftpe1, pre memberType alt)) | ||
case et: ExistentialType => et.withTypeVars(isAsSpecific(ftpe1, _)) | ||
case mt @ MethodType(_, restpe) => !mt.isImplicit || isAsSpecific(ftpe1, restpe) | ||
case mt @ MethodType(_, restpe) => !mt.isImplicit || isAsSpecific(ftpe1, restpe) // | ||
case NullaryMethodType(res) => isAsSpecific(ftpe1, res) | ||
case PolyType(tparams, NullaryMethodType(restpe)) => isAsSpecific(ftpe1, PolyType(tparams, restpe)) | ||
case PolyType(tparams, mt @ MethodType(_, restpe)) => !mt.isImplicit || isAsSpecific(ftpe1, PolyType(tparams, restpe)) | ||
case PolyType(tparams, mt @ MethodType(_, restpe)) => !mt.isImplicit || isAsSpecific(ftpe1, PolyType(tparams, restpe)) // | ||
case _ => isAsSpecificValueType(ftpe1, ftpe2, Nil, Nil) | ||
} | ||
ftpe1 match { | ||
case OverloadedType(pre, alts) => alts exists (alt => isAsSpecific(pre memberType alt, ftpe2)) | ||
case et: ExistentialType => isAsSpecific(et.skolemizeExistential, ftpe2) | ||
case NullaryMethodType(restpe) => isAsSpecific(restpe, ftpe2) | ||
case mt @ MethodType(_, restpe) if mt.isImplicit => isAsSpecific(restpe, ftpe2) | ||
case mt @ MethodType(_, restpe) if mt.isImplicit => isAsSpecific(restpe, ftpe2) // | ||
case mt @ MethodType(_, _) if bothAreVarargs => checkIsApplicable(mt.paramTypes mapConserve repeatedToSingle) | ||
case mt @ MethodType(params, _) if params.nonEmpty => checkIsApplicable(mt.paramTypes) | ||
case PolyType(tparams, NullaryMethodType(restpe)) => isAsSpecific(PolyType(tparams, restpe), ftpe2) | ||
case PolyType(tparams, mt @ MethodType(_, restpe)) if mt.isImplicit => isAsSpecific(PolyType(tparams, restpe), ftpe2) | ||
case PolyType(tparams, mt @ MethodType(_, restpe)) if mt.isImplicit => isAsSpecific(PolyType(tparams, restpe), ftpe2) // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With a test to show that overload resolution behaves the same for 1 and N implicit param lists (ie, it ignores the implicit params) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you say a little more about the overloading scenario you would expect to distinguish these two implementations? I've tried the following,
and both appear to compile the same way with both implementations. |
||
case PolyType(_, mt @ MethodType(params, _)) if params.nonEmpty => checkIsApplicable(mt.paramTypes) | ||
case ErrorType => true | ||
case _ => onRight | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1165,7 +1165,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper | |
notifyUndetparamsAdded(tparams1) | ||
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt, original) | ||
|
||
case mt: MethodType if mode.typingExprNotFunNotLhs && mt.isImplicit => // (4.1) | ||
case mt: MethodType if mode.typingExprNotFunNotLhs && mt.isImplicit => // (4.1) // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM, adaptation should happen one param lists at a time. |
||
adaptToImplicitMethod(mt) | ||
case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode && !treeInfo.isMacroApplicationOrBlock(tree) => | ||
instantiateToMethodType(mt) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1079,7 +1079,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") | |
val context = doLocateContext(pos) | ||
val shouldTypeQualifier = tree0.tpe match { | ||
case null => true | ||
case mt: MethodType => mt.isImplicit | ||
case mt: MethodType => mt.isImplicit // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure, probably okay. |
||
case _ => false | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -268,7 +268,7 @@ abstract class TreeInfo { | |
def mayBeVarGetter(sym: Symbol): Boolean = sym.info match { | ||
case NullaryMethodType(_) => sym.owner.isClass && !sym.isStable | ||
case PolyType(_, NullaryMethodType(_)) => sym.owner.isClass && !sym.isStable | ||
case mt @ MethodType(_, _) => mt.isImplicit && sym.owner.isClass && !sym.isStable | ||
case mt @ MethodType(_, _) => mt.isImplicit && sym.owner.isClass && !sym.isStable // | ||
case _ => false | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, here's a test case:
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4025,7 +4025,7 @@ trait Types | |
} | ||
|
||
def isImplicitMethodType(tp: Type) = tp match { | ||
case mt: MethodType => mt.isImplicit | ||
case mt: MethodType => mt.isImplicit // | ||
case _ => false | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM |
||
|
||
|
@@ -4219,7 +4219,7 @@ trait Types | |
tp2 match { | ||
case mt2 @ MethodType(params2, res2) => | ||
// sameLength(params1, params2) was used directly as pre-screening optimization (now done by matchesQuantified -- is that ok, performancewise?) | ||
mt1.isImplicit == mt2.isImplicit && | ||
mt1.isImplicit == mt2.isImplicit && // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existing implementation looks suspicious to me, it allows one to override a method without the
My intuition is that |
||
matchingParams(params1, params2, mt1.isJava, mt2.isJava) && | ||
matchesQuantified(params1, params2, res1, res2) | ||
case NullaryMethodType(res2) => | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,7 +157,7 @@ trait TypeComparers { | |
private def isSameMethodType(mt1: MethodType, mt2: MethodType) = ( | ||
isSameTypes(mt1.paramTypes, mt2.paramTypes) | ||
&& (mt1.resultType =:= mt2.resultType.substSym(mt2.params, mt1.params)) | ||
&& (mt1.isImplicit == mt2.isImplicit) | ||
&& (mt1.isImplicit == mt2.isImplicit) // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM, this will recurse as needed. |
||
) | ||
|
||
private def equalTypeParamsAndResult(tparams1: List[Symbol], res1: Type, tparams2: List[Symbol], res2: Type) = { | ||
|
@@ -489,7 +489,7 @@ trait TypeComparers { | |
val params2 = mt2.params | ||
val res2 = mt2.resultType | ||
(sameLength(params1, params2) && | ||
mt1.isImplicit == mt2.isImplicit && | ||
mt1.isImplicit == mt2.isImplicit && // | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM
|
||
matchingParams(params1, params2, mt1.isJava, mt2.isJava) && | ||
isSubType(res1.substSym(params1, params2), res2, depth)) | ||
// TODO: if mt1.params.isEmpty, consider NullaryMethodType? | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package test | ||
|
||
object Test { | ||
// A couple of type classes with type members ... | ||
trait Foo[T] { | ||
type A | ||
} | ||
|
||
object Foo { | ||
implicit val fooIS = new Foo[Int] { type A = String } | ||
} | ||
|
||
trait Bar[T] { | ||
type B | ||
val value: B | ||
} | ||
|
||
object Bar { | ||
implicit val barSB = new Bar[String] { | ||
type B = Boolean | ||
val value = true | ||
} | ||
} | ||
|
||
def run[T](t: T)(implicit foo: Foo[T])(bar: Bar[foo.A]): bar.B = bar.value | ||
|
||
val value = run(23) | ||
assert(value: Boolean) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks okay, could do with a test: