summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-03-17 17:16:28 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2016-03-26 22:54:07 -0700
commit040c0434d456dd75a174147d8a0c4cab37266ba6 (patch)
treef5e0dd086c2610d5d56dd9701028e11665ac2671 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parenta2795ba77c0e7b56b0a522eae0cca298af0ac1f1 (diff)
downloadscala-040c0434d456dd75a174147d8a0c4cab37266ba6.tar.gz
scala-040c0434d456dd75a174147d8a0c4cab37266ba6.tar.bz2
scala-040c0434d456dd75a174147d8a0c4cab37266ba6.zip
More fixes based on feedback by Lukas
Crucially, the fully-defined expected type must be checked for conformance to the original expected type!! The logic in adaptToSam that checks whether pt is fully defined probably needs some more thought. See pos/t8310 for a good test case. Argument type checking is a challenge, as we first check against a lenient pt (this lenient expected type has wildcards, and thus is not fully defined, but we should still consider sam adaptation a success even if we end up with wildcards for some unknown type parameters, they should be determined later).
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala28
1 files changed, 14 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index f581eab00f..4f006fe9a9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2726,7 +2726,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
*
* ```
* new S {
- * <static> def apply$body(p1: T1, ..., pN: TN): T = body
+ * def apply$body(p1: T1, ..., pN: TN): T = body
* def apply(p1: T1', ..., pN: TN'): T' = apply$body(p1,..., pN)
* }
* ```
@@ -2737,27 +2737,28 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
* The types T1' ... TN' and T' are derived from the method signature of the sam method,
* as seen from the fully defined `samClassTpFullyDefined`.
*
- * The function's body is put in a static method in the class definition to enforce scoping.
+ * The function's body is put in a (static) method in the class definition to enforce scoping.
* S's members should not be in scope in `body`. (Putting it in the block outside the class runs into implementation problems described below)
*
* The restriction on implicit arguments (neither S's constructor, nor sam may take an implicit argument list),
- * is largely to keep the implementation of type inference (the computation of `samClassTpFullyDefined`) simple.
+ * is to keep the implementation of type inference (the computation of `samClassTpFullyDefined`) simple.
+ *
+ * Impl notes:
+ * - `fun` has a FunctionType, but the expected type `pt` is some SAM type -- let's remedy that
+ * - `fun` is fully attributed, so we'll have to wrangle some symbols into shape (owner change, vparam syms)
+ * - after experimentation, it works best to type check function literals fully first and then adapt to a sam type,
+ * as opposed to a sam-specific code paths earlier on in type checking (in typedFunction).
+ * For one, we want to emit the same bytecode regardless of whether the expected
+ * function type is a built-in FunctionN or some SAM type
*
*/
def adaptToSAM(sam: Symbol, fun: Function, pt: Type, mode: Mode): Tree = {
- // `fun` has a FunctionType, but the expected type `pt` is some SAM type -- let's remedy that
- // `fun` is fully attributed, so we'll have to wrangle some symbols into shape (owner change, vparam syms)
- // I tried very hard to leave `fun` untyped and rework everything into the right shape and type check once,
- // but couldn't make it work due to retyping that happens down the line
- // (implicit conversion retries/retypechecking, CBN transform, super call arg context nesting weirdness)
-
- def funTpMatchesExpected(pt: Type): Boolean = isFullyDefined(pt) && {
- // what's the signature of the method that we should actually be overriding?
+ def fullyDefinedMeetsExpectedFunTp(pt: Type): Boolean = isFullyDefined(pt) && {
val samMethType = pt memberInfo sam
fun.tpe <:< functionType(samMethType.paramTypes, samMethType.resultType)
}
- if (funTpMatchesExpected(pt)) fun.setType(pt)
+ if (fullyDefinedMeetsExpectedFunTp(pt)) fun.setType(pt)
else try {
val samClassSym = pt.typeSymbol
@@ -2786,9 +2787,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
debuglog(s"sam infer: $pt --> ${appliedType(samTyCon, targs)} by ${fun.tpe} <:< $samInfoWithTVars --> $targs for $tparams")
- // a fully defined samClassTp
val ptFullyDefined = appliedType(samTyCon, targs)
- if (funTpMatchesExpected(ptFullyDefined)) {
+ if (ptFullyDefined <:< pt && fullyDefinedMeetsExpectedFunTp(ptFullyDefined)) {
debuglog(s"sam fully defined expected type: $ptFullyDefined from $pt for ${fun.tpe}")
fun.setType(ptFullyDefined)
} else {