From e84c6ee87aa7c98669ab433cfde3acfc1732acc7 Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 13 Dec 2022 12:43:12 +0100 Subject: [PATCH] Handle context function arguments in overloading resolution Fixes #16506 We now handle the cases where an argument of an overloaded method is a context closure. The closure must be given implicitly. It cannot be inferred since at the time where the argument is typed, there is no expected expected type to expand it to a context closure. --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 5 ++++- .../src/dotty/tools/dotc/typer/Applications.scala | 6 ++++-- tests/pos/i16506.scala | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i16506.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index ba00689f5c36..1097cb0129f3 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1464,7 +1464,10 @@ object desugar { val param = makeSyntheticParameter( tpt = if params.exists(_.tpt.isEmpty) then TypeTree() - else Tuple(params.map(_.tpt))) + else Tuple(params.map(_.tpt)), + flags = + if params.nonEmpty && params.head.mods.is(Given) then SyntheticTermParam | Given + else SyntheticTermParam) def selector(n: Int) = if (isGenericTuple) Apply(Select(refOfDef(param), nme.apply), Literal(Constant(n))) else Select(refOfDef(param), nme.selectorName(n)) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 20ae81a74655..35b8b1f9719d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1923,7 +1923,9 @@ trait Applications extends Compatibility { /** The shape of given tree as a type; cannot handle named arguments. */ def typeShape(tree: untpd.Tree): Type = tree match { case untpd.Function(args, body) => - defn.FunctionOf(args map Function.const(defn.AnyType), typeShape(body)) + defn.FunctionOf( + args.map(Function.const(defn.AnyType)), typeShape(body), + isContextual = untpd.isContextualClosure(tree)) case Match(EmptyTree, _) => defn.PartialFunctionClass.typeRef.appliedTo(defn.AnyType :: defn.NothingType :: Nil) case _ => @@ -2232,7 +2234,7 @@ trait Applications extends Compatibility { false val commonFormal = if (isPartial) defn.PartialFunctionOf(commonParamTypes.head, WildcardType) - else defn.FunctionOf(commonParamTypes, WildcardType) + else defn.FunctionOf(commonParamTypes, WildcardType, isContextual = untpd.isContextualClosure(arg)) overload.println(i"pretype arg $arg with expected type $commonFormal") if (commonParamTypes.forall(isFullyDefined(_, ForceDegree.flipBottom))) withMode(Mode.ImplicitsEnabled) { diff --git a/tests/pos/i16506.scala b/tests/pos/i16506.scala new file mode 100644 index 000000000000..2f3cea682e44 --- /dev/null +++ b/tests/pos/i16506.scala @@ -0,0 +1,14 @@ +import scala.annotation.targetName + +trait Ctx + +def foo(f: Ctx => Int) = ??? + +@targetName("fooContextual") +def foo(f: Ctx ?=> Int) = ??? + +def bar1 = foo(ctx => 123) +def bar2 = foo((ctx: Ctx) => 123) +def bar3 = foo(ctx ?=> 123) +def bar4 = foo((ctx: Ctx) ?=> 123) +// def bar5 = foo(123) does not work