@@ -1990,169 +1990,186 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
1990
1990
}
1991
1991
}
1992
1992
1993
- def adaptNoArgs (wtp : Type ): Tree = wtp match {
1994
- case wtp : ExprType =>
1995
- adaptInterpolated(tree.withType(wtp.resultType), pt)
1996
- case wtp : ImplicitMethodType if constrainResult(wtp, followAlias(pt)) =>
1997
- val tvarsToInstantiate = tvarsInParams(tree)
1998
- wtp.paramInfos.foreach(instantiateSelected(_, tvarsToInstantiate))
1999
- val constr = ctx.typerState.constraint
2000
- def addImplicitArgs (implicit ctx : Context ) = {
2001
- val errors = new mutable.ListBuffer [() => String ]
2002
- def implicitArgError (msg : => String ) = {
2003
- errors += (() => msg)
2004
- EmptyTree
2005
- }
2006
- def issueErrors () = {
2007
- for (err <- errors) ctx.error(err(), tree.pos.endPos)
2008
- tree.withType(wtp.resultType)
2009
- }
2010
- val args = (wtp.paramNames, wtp.paramInfos).zipped map { (pname, formal) =>
2011
- def implicitArgError (msg : String => String ) =
2012
- errors += (() => msg(em " parameter $pname of $methodStr" ))
2013
- if (errors.nonEmpty) EmptyTree
2014
- else inferImplicitArg(formal, implicitArgError, tree.pos.endPos)
2015
- }
2016
- if (errors.nonEmpty) {
2017
- // If there are several arguments, some arguments might already
2018
- // have influenced the context, binding variables, but later ones
2019
- // might fail. In that case the constraint needs to be reset.
2020
- ctx.typerState.constraint = constr
2021
-
2022
- // If method has default params, fall back to regular application
2023
- // where all inferred implicits are passed as named args.
2024
- if (tree.symbol.hasDefaultParams) {
2025
- val namedArgs = (wtp.paramNames, args).zipped.flatMap { (pname, arg) =>
2026
- arg match {
2027
- case EmptyTree => Nil
2028
- case _ => untpd.NamedArg (pname, untpd.TypedSplice (arg)) :: Nil
2029
- }
2030
- }
2031
- tryEither { implicit ctx =>
2032
- typed(untpd.Apply (untpd.TypedSplice (tree), namedArgs), pt)
2033
- } { (_, _) =>
2034
- issueErrors()
2035
- }
2036
- } else issueErrors()
2037
- }
2038
- else adapt(tpd.Apply (tree, args), pt)
1993
+ def adaptNoArgsImplicitMethod (wtp : ImplicitMethodType ): Tree = {
1994
+ val tvarsToInstantiate = tvarsInParams(tree)
1995
+ wtp.paramInfos.foreach(instantiateSelected(_, tvarsToInstantiate))
1996
+ val constr = ctx.typerState.constraint
1997
+ def addImplicitArgs (implicit ctx : Context ) = {
1998
+ val errors = new mutable.ListBuffer [() => String ]
1999
+ def implicitArgError (msg : => String ) = {
2000
+ errors += (() => msg)
2001
+ EmptyTree
2039
2002
}
2040
- addImplicitArgs(argCtx(tree))
2041
- case wtp : MethodType if ! pt.isInstanceOf [SingletonType ] =>
2042
- // Follow proxies and approximate type paramrefs by their upper bound
2043
- // in the current constraint in order to figure out robustly
2044
- // whether an expected type is some sort of function type.
2045
- def underlyingApplied (tp : Type ): Type = tp.stripTypeVar match {
2046
- case tp : RefinedType => tp
2047
- case tp : AppliedType => tp
2048
- case tp : TypeParamRef => underlyingApplied(ctx.typeComparer.bounds(tp).hi)
2049
- case tp : TypeProxy => underlyingApplied(tp.superType)
2050
- case _ => tp
2003
+ def issueErrors () = {
2004
+ for (err <- errors) ctx.error(err(), tree.pos.endPos)
2005
+ tree.withType(wtp.resultType)
2051
2006
}
2052
- val ptNorm = underlyingApplied(pt)
2053
- val arity =
2054
- if (defn.isFunctionType(ptNorm))
2055
- if (! isFullyDefined(pt, ForceDegree .none) && isFullyDefined(wtp, ForceDegree .none))
2056
- // if method type is fully defined, but expected type is not,
2057
- // prioritize method parameter types as parameter types of the eta-expanded closure
2058
- 0
2059
- else defn.functionArity(ptNorm)
2060
- else {
2061
- val nparams = wtp.paramInfos.length
2062
- if (nparams > 0 || pt.eq(AnyFunctionProto )) nparams
2063
- else - 1 // no eta expansion in this case
2064
- }
2065
-
2066
- /** A synthetic apply should be eta-expanded if it is the apply of an implicit function
2067
- * class, and the expected type is a function type. This rule is needed so we can pass
2068
- * an implicit function to a regular function type. So the following is OK
2069
- *
2070
- * val f: implicit A => B = ???
2071
- * val g: A => B = f
2072
- *
2073
- * and the last line expands to
2074
- *
2075
- * val g: A => B = (x$0: A) => f.apply(x$0)
2076
- *
2077
- * One could be tempted not to eta expand the rhs, but that would violate the invariant
2078
- * that expressions of implicit function types are always implicit closures, which is
2079
- * exploited by ShortcutImplicits.
2080
- *
2081
- * On the other hand, the following would give an error if there is no implicit
2082
- * instance of A available.
2083
- *
2084
- * val x: AnyRef = f
2085
- *
2086
- * That's intentional, we want to fail here, otherwise some unsuccesful implicit searches
2087
- * would go undetected.
2088
- *
2089
- * Examples for these cases are found in run/implicitFuns.scala and neg/i2006.scala.
2090
- */
2091
- def isExpandableApply =
2092
- defn.isImplicitFunctionClass(tree.symbol.maybeOwner) && defn.isFunctionType(ptNorm)
2093
-
2094
- /** Is reference to this symbol `f` automatically expanded to `f()`? */
2095
- def isAutoApplied (sym : Symbol ): Boolean = {
2096
- sym.isConstructor ||
2097
- sym.matchNullaryLoosely ||
2098
- ctx.testScala2Mode(em " ${sym.showLocated} requires () argument " , tree.pos,
2099
- patch(tree.pos.endPos, " ()" ))
2007
+ val args = (wtp.paramNames, wtp.paramInfos).zipped map { (pname, formal) =>
2008
+ def implicitArgError (msg : String => String ) =
2009
+ errors += (() => msg(em " parameter $pname of $methodStr" ))
2010
+ if (errors.nonEmpty) EmptyTree
2011
+ else inferImplicitArg(formal, implicitArgError, tree.pos.endPos)
2100
2012
}
2013
+ if (errors.nonEmpty) {
2014
+ // If there are several arguments, some arguments might already
2015
+ // have influenced the context, binding variables, but later ones
2016
+ // might fail. In that case the constraint needs to be reset.
2017
+ ctx.typerState.constraint = constr
2018
+
2019
+ // If method has default params, fall back to regular application
2020
+ // where all inferred implicits are passed as named args.
2021
+ if (tree.symbol.hasDefaultParams) {
2022
+ val namedArgs = (wtp.paramNames, args).zipped.flatMap { (pname, arg) =>
2023
+ arg match {
2024
+ case EmptyTree => Nil
2025
+ case _ => untpd.NamedArg (pname, untpd.TypedSplice (arg)) :: Nil
2026
+ }
2027
+ }
2028
+ tryEither { implicit ctx =>
2029
+ typed(untpd.Apply (untpd.TypedSplice (tree), namedArgs), pt)
2030
+ } { (_, _) =>
2031
+ issueErrors()
2032
+ }
2033
+ } else issueErrors()
2034
+ }
2035
+ else adapt(tpd.Apply (tree, args), pt)
2036
+ }
2037
+ addImplicitArgs(argCtx(tree))
2038
+ }
2039
+
2040
+ /** A synthetic apply should be eta-expanded if it is the apply of an implicit function
2041
+ * class, and the expected type is a function type. This rule is needed so we can pass
2042
+ * an implicit function to a regular function type. So the following is OK
2043
+ *
2044
+ * val f: implicit A => B = ???
2045
+ * val g: A => B = f
2046
+ *
2047
+ * and the last line expands to
2048
+ *
2049
+ * val g: A => B = (x$0: A) => f.apply(x$0)
2050
+ *
2051
+ * One could be tempted not to eta expand the rhs, but that would violate the invariant
2052
+ * that expressions of implicit function types are always implicit closures, which is
2053
+ * exploited by ShortcutImplicits.
2054
+ *
2055
+ * On the other hand, the following would give an error if there is no implicit
2056
+ * instance of A available.
2057
+ *
2058
+ * val x: AnyRef = f
2059
+ *
2060
+ * That's intentional, we want to fail here, otherwise some unsuccesful implicit searches
2061
+ * would go undetected.
2062
+ *
2063
+ * Examples for these cases are found in run/implicitFuns.scala and neg/i2006.scala.
2064
+ */
2065
+ def adaptNoArgsUnappliedMethod (wtp : MethodType , functionExpected : Boolean , arity : Int ): Tree = {
2066
+ def isExpandableApply =
2067
+ defn.isImplicitFunctionClass(tree.symbol.maybeOwner) && functionExpected
2068
+
2069
+ /** Is reference to this symbol `f` automatically expanded to `f()`? */
2070
+ def isAutoApplied (sym : Symbol ): Boolean = {
2071
+ sym.isConstructor ||
2072
+ sym.matchNullaryLoosely ||
2073
+ ctx.testScala2Mode(em " ${sym.showLocated} requires () argument " , tree.pos,
2074
+ patch(tree.pos.endPos, " ()" ))
2075
+ }
2076
+
2077
+ // Reasons NOT to eta expand:
2078
+ // - we reference a constructor
2079
+ // - we are in a pattern
2080
+ // - the current tree is a synthetic apply which is not expandable (eta-expasion would simply undo that)
2081
+ if (arity >= 0 &&
2082
+ ! tree.symbol.isConstructor &&
2083
+ ! ctx.mode.is(Mode .Pattern ) &&
2084
+ ! (isSyntheticApply(tree) && ! isExpandableApply))
2085
+ typed(etaExpand(tree, wtp, arity), pt)
2086
+ else if (wtp.paramInfos.isEmpty && isAutoApplied(tree.symbol))
2087
+ adaptInterpolated(tpd.Apply (tree, Nil ), pt)
2088
+ else if (wtp.isImplicit)
2089
+ err.typeMismatch(tree, pt)
2090
+ else
2091
+ missingArgs(wtp)
2092
+ }
2101
2093
2102
- // Reasons NOT to eta expand:
2103
- // - we reference a constructor
2104
- // - we are in a pattern
2105
- // - the current tree is a synthetic apply which is not expandable (eta-expasion would simply undo that)
2106
- if (arity >= 0 &&
2107
- ! tree.symbol.isConstructor &&
2108
- ! ctx.mode.is(Mode .Pattern ) &&
2109
- ! (isSyntheticApply(tree) && ! isExpandableApply))
2110
- typed(etaExpand(tree, wtp, arity), pt)
2111
- else if (wtp.paramInfos.isEmpty && isAutoApplied(tree.symbol))
2112
- adaptInterpolated(tpd.Apply (tree, Nil ), pt)
2113
- else if (wtp.isImplicit)
2114
- err.typeMismatch(tree, pt)
2094
+ def adaptNoArgsOther (wtp : Type ) = {
2095
+ ctx.typeComparer.GADTused = false
2096
+ if (defn.isImplicitFunctionClass(wtp.underlyingClassRef(refinementOK = false ).classSymbol) &&
2097
+ ! untpd.isImplicitClosure(tree) &&
2098
+ ! isApplyProto(pt) &&
2099
+ ! ctx.isAfterTyper) {
2100
+ typr.println(i " insert apply on implicit $tree" )
2101
+ typed(untpd.Select (untpd.TypedSplice (tree), nme.apply), pt)
2102
+ }
2103
+ else if (ctx.mode is Mode .Pattern ) {
2104
+ checkEqualityEvidence(tree, pt)
2105
+ tree
2106
+ }
2107
+ else if (tree.tpe <:< pt) {
2108
+ if (pt.hasAnnotation(defn.InlineParamAnnot ))
2109
+ checkInlineConformant(tree, " argument to inline parameter" )
2110
+ if (Inliner .hasBodyToInline(tree.symbol) &&
2111
+ ! ctx.owner.ownersIterator.exists(_.isInlineMethod) &&
2112
+ ! ctx.settings.YnoInline .value &&
2113
+ ! ctx.isAfterTyper &&
2114
+ ! ctx.reporter.hasErrors)
2115
+ adapt(Inliner .inlineCall(tree, pt), pt)
2116
+ else if (ctx.typeComparer.GADTused && pt.isValueType)
2117
+ // Insert an explicit cast, so that -Ycheck in later phases succeeds.
2118
+ // I suspect, but am not 100% sure that this might affect inferred types,
2119
+ // if the expected type is a supertype of the GADT bound. It would be good to come
2120
+ // up with a test case for this.
2121
+ tree.asInstance(pt)
2115
2122
else
2116
- missingArgs(wtp)
2117
- case _ =>
2118
- ctx.typeComparer.GADTused = false
2119
- if (defn.isImplicitFunctionClass(wtp.underlyingClassRef(refinementOK = false ).classSymbol) &&
2120
- ! untpd.isImplicitClosure(tree) &&
2121
- ! isApplyProto(pt) &&
2122
- ! ctx.isAfterTyper) {
2123
- typr.println(i " insert apply on implicit $tree" )
2124
- typed(untpd.Select (untpd.TypedSplice (tree), nme.apply), pt)
2125
- }
2126
- else if (ctx.mode is Mode .Pattern ) {
2127
- checkEqualityEvidence(tree, pt)
2128
2123
tree
2129
- }
2130
- else if (tree.tpe <:< pt) {
2131
- if (pt.hasAnnotation(defn.InlineParamAnnot ))
2132
- checkInlineConformant(tree, " argument to inline parameter" )
2133
- if (Inliner .hasBodyToInline(tree.symbol) &&
2134
- ! ctx.owner.ownersIterator.exists(_.isInlineMethod) &&
2135
- ! ctx.settings.YnoInline .value &&
2136
- ! ctx.isAfterTyper &&
2137
- ! ctx.reporter.hasErrors)
2138
- adapt(Inliner .inlineCall(tree, pt), pt)
2139
- else if (ctx.typeComparer.GADTused && pt.isValueType)
2140
- // Insert an explicit cast, so that -Ycheck in later phases succeeds.
2141
- // I suspect, but am not 100% sure that this might affect inferred types,
2142
- // if the expected type is a supertype of the GADT bound. It would be good to come
2143
- // up with a test case for this.
2144
- tree.asInstance(pt)
2145
- else
2146
- tree
2147
- }
2148
- else wtp match {
2149
- case wtp : MethodType => missingArgs(wtp)
2150
- case _ =>
2151
- typr.println(i " adapt to subtype ${tree.tpe} !<:< $pt" )
2152
- // typr.println(TypeComparer.explained(implicit ctx => tree.tpe <:< pt))
2153
- adaptToSubType(wtp)
2154
- }
2124
+ }
2125
+ else wtp match {
2126
+ case wtp : MethodType => missingArgs(wtp)
2127
+ case _ =>
2128
+ typr.println(i " adapt to subtype ${tree.tpe} !<:< $pt" )
2129
+ // typr.println(TypeComparer.explained(implicit ctx => tree.tpe <:< pt))
2130
+ adaptToSubType(wtp)
2131
+ }
2155
2132
}
2133
+
2134
+ // Follow proxies and approximate type paramrefs by their upper bound
2135
+ // in the current constraint in order to figure out robustly
2136
+ // whether an expected type is some sort of function type.
2137
+ def underlyingApplied (tp : Type ): Type = tp.stripTypeVar match {
2138
+ case tp : RefinedType => tp
2139
+ case tp : AppliedType => tp
2140
+ case tp : TypeParamRef => underlyingApplied(ctx.typeComparer.bounds(tp).hi)
2141
+ case tp : TypeProxy => underlyingApplied(tp.superType)
2142
+ case _ => tp
2143
+ }
2144
+
2145
+ def adaptNoArgs (wtp : Type ): Tree = {
2146
+ val ptNorm = underlyingApplied(pt)
2147
+ val functionExpected = defn.isFunctionType(ptNorm)
2148
+ wtp match {
2149
+ case wtp : ExprType =>
2150
+ adaptInterpolated(tree.withType(wtp.resultType), pt)
2151
+ case wtp : ImplicitMethodType
2152
+ if constrainResult(wtp, followAlias(pt)) || ! functionExpected =>
2153
+ adaptNoArgsImplicitMethod(wtp)
2154
+ case wtp : MethodType if ! pt.isInstanceOf [SingletonType ] =>
2155
+ val arity =
2156
+ if (functionExpected)
2157
+ if (! isFullyDefined(pt, ForceDegree .none) && isFullyDefined(wtp, ForceDegree .none))
2158
+ // if method type is fully defined, but expected type is not,
2159
+ // prioritize method parameter types as parameter types of the eta-expanded closure
2160
+ 0
2161
+ else defn.functionArity(ptNorm)
2162
+ else {
2163
+ val nparams = wtp.paramInfos.length
2164
+ if (nparams > 0 || pt.eq(AnyFunctionProto )) nparams
2165
+ else - 1 // no eta expansion in this case
2166
+ }
2167
+ adaptNoArgsUnappliedMethod(wtp, functionExpected, arity)
2168
+ case _ =>
2169
+ adaptNoArgsOther(wtp)
2170
+ }
2171
+ }
2172
+
2156
2173
/** Adapt an expression of constant type to a different constant type `tpe`. */
2157
2174
def adaptConstant (tree : Tree , tpe : ConstantType ): Tree = {
2158
2175
def lit = Literal (tpe.value).withPos(tree.pos)
0 commit comments