Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle context function arguments in overloading resolution #16511

Merged
merged 1 commit into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 _ =>
Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions tests/pos/i16506.scala
Original file line number Diff line number Diff line change
@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about

def f1: Ctx => Int = ???
def f2: Ctx ?=> Int = ???

def bar6 = foo(f1)
def bar7 = foo(f2)

?
Unfortunately bar7 doesn't compile:

19 |def bar7 = foo(f2)
   |               ^^
   |               Found:    (Ctx) ?=> Int
   |               Required: Ctx => <?>

Isn't this a separate case from bar5 as f2 is already known to be a context function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, no. If we expanded bar7 it would look like this:

foo(ctx ?=> f2(using ctx)

So when we see f2 we immediately apply it to a Context argument which is missing, so compilation fails. That's baked in, and I think it will be impossible to change. We exploit this uniformity in our compilation scheme for context functions to make them more efficient.