@@ -1990,169 +1990,186 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
19901990 }
19911991 }
19921992
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
20392002 }
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)
20512006 }
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)
21002012 }
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+ }
21012093
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)
21152122 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)
21282123 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+ }
21552132 }
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+
21562173 /** Adapt an expression of constant type to a different constant type `tpe`. */
21572174 def adaptConstant (tree : Tree , tpe : ConstantType ): Tree = {
21582175 def lit = Literal (tpe.value).withPos(tree.pos)
0 commit comments