Skip to content

Commit 9a5bd70

Browse files
committed
Handle apply on ContextualMethodTypes created with -Yimplicit-as-given as if it was implicit
1 parent f7dc85b commit 9a5bd70

File tree

7 files changed

+30
-9
lines changed

7 files changed

+30
-9
lines changed

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
210210

211211
case class Given()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Given)
212212

213+
case class GivenFromImplicit()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Given | Flags.FromImplicit)
214+
213215
case class Erased()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Erased)
214216

215217
case class Final()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Final)

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ object Flags {
436436
/** Symbol is a constructor proxy (either companion, or apply method) */
437437
val (ConstructorProxy @ _, _, _) = newFlags(62, "<constructor proxy>") // (could be merged with Lifted)
438438

439+
/** Changed from implicit with -Yimplicits-as-given flags */
440+
val (FromImplicit @ _, _, _) = newFlags(63, "<from implicit>")
441+
439442
// --------- Combined Flag Sets and Conjunctions ----------------------
440443

441444
/** All possible flags */

compiler/src/dotty/tools/dotc/core/NamerOps.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ object NamerOps:
7878
case Nil =>
7979
resultType
8080
case TermSymbols(params) :: paramss1 =>
81-
val (isContextual, isImplicit) =
82-
if params.isEmpty then (false, false)
83-
else (params.head.is(Given), params.head.is(Implicit))
84-
val make = MethodType.companion(isContextual = isContextual, isImplicit = isImplicit)
81+
val (isContextual, isImplicit, fromImplicit) =
82+
if params.isEmpty then (false, false, false)
83+
else (params.head.is(Given), params.head.is(Implicit), params.head.is(FromImplicit))
84+
val make = MethodType.companion(isContextual = isContextual, isImplicit = isImplicit, fromImplicit = fromImplicit)
8585
if isJava then
8686
for param <- params do
8787
if param.info.isDirectRef(defn.ObjectClass) then param.info = defn.AnyType

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ object Types extends TypeUtils {
479479
/** Is this a Method or PolyType which has implicit or contextual parameters? */
480480
def isImplicitMethod: Boolean = false
481481

482+
def wasImplicitMethod: Boolean = false
483+
482484
/** Is this a Method or PolyType which has contextual parameters as first value parameter list? */
483485
def isContextualMethod: Boolean = false
484486

@@ -4104,7 +4106,10 @@ object Types extends TypeUtils {
41044106
paramInfos.exists(p => p.hasAnnotation(defn.ErasedParamAnnot))
41054107

41064108
final override def isContextualMethod: Boolean =
4107-
companion.eq(ContextualMethodType)
4109+
companion.eq(ContextualMethodType) || companion.eq(ContextualFromImplicitMethodType)
4110+
4111+
final override def wasImplicitMethod: Boolean =
4112+
companion.eq(ContextualFromImplicitMethodType)
41084113

41094114
def erasedParams(using Context): List[Boolean] =
41104115
paramInfos.map(p => p.hasAnnotation(defn.ErasedParamAnnot))
@@ -4209,14 +4214,16 @@ object Types extends TypeUtils {
42094214
}
42104215

42114216
object MethodType extends MethodTypeCompanion("MethodType") {
4212-
def companion(isContextual: Boolean = false, isImplicit: Boolean = false): MethodTypeCompanion =
4213-
if (isContextual) ContextualMethodType
4217+
def companion(isContextual: Boolean = false, isImplicit: Boolean = false, fromImplicit: Boolean = false): MethodTypeCompanion =
4218+
if (fromImplicit) ContextualFromImplicitMethodType
4219+
else if (isContextual) ContextualMethodType
42144220
else if (isImplicit) ImplicitMethodType
42154221
else MethodType
42164222
}
42174223

42184224
object ContextualMethodType extends MethodTypeCompanion("ContextualMethodType")
42194225
object ImplicitMethodType extends MethodTypeCompanion("ImplicitMethodType")
4226+
object ContextualFromImplicitMethodType extends MethodTypeCompanion("ContextualFromImplicitMethodType")
42204227

42214228
/** A ternary extractor for MethodType */
42224229
object MethodTpe {

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3283,7 +3283,7 @@ object Parsers {
32833283
private def modOfToken(tok: Int, name: Name): Mod = tok match {
32843284
case ABSTRACT => Mod.Abstract()
32853285
case FINAL => Mod.Final()
3286-
case IMPLICIT if ctx.settings.YimplicitAsGiven.value => Mod.Given()
3286+
case IMPLICIT if ctx.settings.YimplicitAsGiven.value => Mod.GivenFromImplicit()
32873287
case IMPLICIT => Mod.Implicit()
32883288
case GIVEN => Mod.Given()
32893289
case LAZY => Mod.Lazy()
@@ -3553,7 +3553,7 @@ object Parsers {
35533553

35543554
def paramMods() =
35553555
if in.token == IMPLICIT then
3556-
addParamMod(() => if (ctx.settings.YimplicitAsGiven.value) Mod.Given() else Mod.Implicit())
3556+
addParamMod(() => if (ctx.settings.YimplicitAsGiven.value) Mod.GivenFromImplicit() else Mod.Implicit())
35573557
else if isIdent(nme.using) then
35583558
if initialMods.is(Given) then
35593559
syntaxError(em"`using` is already implied here, should not be given explicitly", in.offset)

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4855,6 +4855,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
48554855
val isUsingApply = pt.applyKind == ApplyKind.Using
48564856
methType.isContextualMethod == isUsingApply
48574857
|| methType.isImplicitMethod && isUsingApply // for a transition allow `using` arguments for regular implicit parameters
4858+
|| methType.wasImplicitMethod && !isUsingApply
48584859

48594860
/** Check that `tree == x: pt` is typeable. Used when checking a pattern
48604861
* against a selector of type `pt`. This implementation accounts for

tests/pos/i22482.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//> using options -Yimplicit-as-given
2+
3+
def foo(implicit a: Int): Unit = ???
4+
def bar()(implicit a: Int) : Unit = ???
5+
6+
def main() =
7+
foo(0)
8+
bar()(0)

0 commit comments

Comments
 (0)