diff options
author | odersky <odersky@gmail.com> | 2016-12-03 11:40:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-03 11:40:02 +0100 |
commit | 9ceed9213497597de8895c83bdf0cc4d5597b150 (patch) | |
tree | 5bce4cd1d04ccdb47ae7d69b5071438ab5902d6d /compiler/src/dotty/tools/dotc/typer/Typer.scala | |
parent | 8288a3462353de80d8295bbd1f69afe141b2ed4c (diff) | |
parent | d8f5c6c5b57b0688a2024fedc26104540234739c (diff) | |
download | dotty-9ceed9213497597de8895c83bdf0cc4d5597b150.tar.gz dotty-9ceed9213497597de8895c83bdf0cc4d5597b150.tar.bz2 dotty-9ceed9213497597de8895c83bdf0cc4d5597b150.zip |
Merge pull request #1658 from dotty-staging/fix-#1639
Fix #1639: Changes around implicits and apply methods
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/typer/Typer.scala | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 4ec1c460f..94b13b22b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1613,18 +1613,34 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit * `fallBack`. * * 1st strategy: Try to insert `.apply` so that the result conforms to prototype `pt`. + * This strategy is not tried if the prototype represents already + * another `.apply` or `.apply()` selection. * 2nd strategy: If tree is a select `qual.name`, try to insert an implicit conversion * around the qualifier part `qual` so that the result conforms to the expected type * with wildcard result type. */ - def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType)(fallBack: (Tree, TyperState) => Tree)(implicit ctx: Context): Tree = - tryEither { implicit ctx => + def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType)(fallBack: => Tree)(implicit ctx: Context): Tree = { + + /** Is `pt` a prototype of an `apply` selection, or a parameterless function yielding one? */ + def isApplyProto(pt: Type): Boolean = pt match { + case pt: SelectionProto => pt.name == nme.apply + case pt: FunProto => pt.args.isEmpty && isApplyProto(pt.resultType) + case pt: IgnoredProto => isApplyProto(pt.ignored) + case _ => false + } + + def tryApply(implicit ctx: Context) = { val sel = typedSelect(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt) if (sel.tpe.isError) sel else adapt(sel, pt) - } { (failedTree, failedState) => - tryInsertImplicitOnQualifier(tree, pt).getOrElse(fallBack(failedTree, failedState)) } + def tryImplicit = + tryInsertImplicitOnQualifier(tree, pt).getOrElse(fallBack) + + if (isApplyProto(pt)) tryImplicit + else tryEither(tryApply(_))((_, _) => tryImplicit) + } + /** If this tree is a select node `qual.name`, try to insert an implicit conversion * `c` around `qual` so that `c(qual).name` conforms to `pt`. */ @@ -1716,7 +1732,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def hasEmptyParams(denot: SingleDenotation) = denot.info.paramTypess == ListOfNil pt match { case pt: FunProto => - tryInsertApplyOrImplicit(tree, pt)((_, _) => noMatches) + tryInsertApplyOrImplicit(tree, pt)(noMatches) case _ => if (altDenots exists (_.info.paramTypess == ListOfNil)) typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt) @@ -1755,7 +1771,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case Apply(_, _) => " more" case _ => "" } - (_, _) => errorTree(tree, em"$methodStr does not take$more parameters") + errorTree(tree, em"$methodStr does not take$more parameters") } } @@ -1974,9 +1990,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case pt: FunProto => adaptToArgs(wtp, pt) case pt: PolyProto => - tryInsertApplyOrImplicit(tree, pt) { - (_, _) => tree // error will be reported in typedTypeApply - } + tryInsertApplyOrImplicit(tree, pt)(tree) // error will be reported in typedTypeApply case _ => if (ctx.mode is Mode.Type) adaptType(tree.tpe) else adaptNoArgs(wtp) |