@@ -2649,12 +2649,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2649
2649
val ValDef (name, tpt, _) = vdef
2650
2650
checkNonRootName(vdef.name, vdef.nameSpan)
2651
2651
completeAnnotations(vdef, sym)
2652
- if ( sym.isOneOf( GivenOrImplicit )) checkImplicitConversionDefOK(sym)
2652
+ if sym.is( Implicit ) then checkImplicitConversionDefOK(sym)
2653
2653
if sym.is(Module ) then checkNoModuleClash(sym)
2654
2654
val tpt1 = checkSimpleKinded(typedType(tpt))
2655
2655
val rhs1 = vdef.rhs match {
2656
- case rhs @ Ident (nme.WILDCARD ) => rhs withType tpt1.tpe
2657
- case rhs => typedExpr(rhs, tpt1.tpe.widenExpr)
2656
+ case rhs @ Ident (nme.WILDCARD ) =>
2657
+ rhs.withType(tpt1.tpe)
2658
+ case rhs : RefTree
2659
+ if rhs.name == nme.deferred && sym.isAllOf(DeferredGivenFlags , butNot = Param ) =>
2660
+ EmptyTree
2661
+ case rhs =>
2662
+ typedExpr(rhs, tpt1.tpe.widenExpr)
2658
2663
}
2659
2664
val vdef1 = assignType(cpy.ValDef (vdef)(name, tpt1, rhs1), sym)
2660
2665
postProcessInfo(vdef1, sym)
@@ -2715,9 +2720,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2715
2720
2716
2721
if sym.isInlineMethod then rhsCtx.addMode(Mode .InlineableBody )
2717
2722
if sym.is(ExtensionMethod ) then rhsCtx.addMode(Mode .InExtensionMethod )
2718
- val rhs1 = PrepareInlineable .dropInlineIfError(sym,
2719
- if sym.isScala2Macro then typedScala2MacroBody(ddef.rhs)(using rhsCtx)
2720
- else typedExpr(ddef.rhs, tpt1.tpe.widenExpr)(using rhsCtx))
2723
+ val rhs1 = ddef.rhs match
2724
+ case Ident (nme.deferred) if sym.isAllOf(DeferredGivenFlags ) =>
2725
+ EmptyTree
2726
+ case rhs =>
2727
+ PrepareInlineable .dropInlineIfError(sym,
2728
+ if sym.isScala2Macro then typedScala2MacroBody(ddef.rhs)(using rhsCtx)
2729
+ else typedExpr(ddef.rhs, tpt1.tpe.widenExpr)(using rhsCtx))
2721
2730
2722
2731
if sym.isInlineMethod then
2723
2732
if StagingLevel .level > 0 then
@@ -2898,6 +2907,59 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2898
2907
case None =>
2899
2908
body
2900
2909
2910
+ /** Implement givens that were declared with a `deferred` rhs.
2911
+ * The a given value matching the declared type is searched in a
2912
+ * context directly enclosing the current class, in which all given
2913
+ * parameters of the current class are also defined.
2914
+ */
2915
+ def implementDeferredGivens (body : List [Tree ]): List [Tree ] =
2916
+ if cls.is(Trait ) || ctx.isAfterTyper then body
2917
+ else
2918
+ def isGivenValue (mbr : TermRef ) =
2919
+ val dcl = mbr.symbol
2920
+ if dcl.is(Method ) then
2921
+ report.error(
2922
+ em """ Cannnot infer the implementation of the deferred ${dcl.showLocated}
2923
+ |since that given is parameterized. An implementing given needs to be written explicitly. """ ,
2924
+ cdef.srcPos)
2925
+ false
2926
+ else true
2927
+
2928
+ def givenImpl (mbr : TermRef ): ValDef =
2929
+ val dcl = mbr.symbol
2930
+ val target = dcl.info.asSeenFrom(cls.thisType, dcl.owner)
2931
+ val constr = cls.primaryConstructor
2932
+ val usingParamAccessors = cls.paramAccessors.filter(_.is(Given ))
2933
+ val paramScope = newScopeWith(usingParamAccessors* )
2934
+ val searchCtx = ctx.outer.fresh.setScope(paramScope)
2935
+ val rhs = implicitArgTree(target, cdef.span,
2936
+ where = i " inferring the implementation of the deferred ${dcl.showLocated}"
2937
+ )(using searchCtx)
2938
+
2939
+ val impl = dcl.copy(cls,
2940
+ flags = dcl.flags &~ (HasDefault | Deferred ) | Final | Override ,
2941
+ info = target,
2942
+ coord = rhs.span).entered.asTerm
2943
+
2944
+ def anchorParams = new TreeMap :
2945
+ override def transform (tree : Tree )(using Context ): Tree = tree match
2946
+ case id : Ident if usingParamAccessors.contains(id.symbol) =>
2947
+ cpy.Select (id)(This (cls), id.name)
2948
+ case _ =>
2949
+ super .transform(tree)
2950
+ ValDef (impl, anchorParams.transform(rhs))
2951
+ end givenImpl
2952
+
2953
+ val givenImpls =
2954
+ cls.thisType.implicitMembers
2955
+ // .showing(i"impl def givens for $cls/$result")
2956
+ .filter(_.symbol.isAllOf(DeferredGivenFlags , butNot = Param ))
2957
+ // .showing(i"impl def filtered givens for $cls/$result")
2958
+ .filter(isGivenValue)
2959
+ .map(givenImpl)
2960
+ body ++ givenImpls
2961
+ end implementDeferredGivens
2962
+
2901
2963
ensureCorrectSuperClass()
2902
2964
completeAnnotations(cdef, cls)
2903
2965
val constr1 = typed(constr).asInstanceOf [DefDef ]
@@ -2919,9 +2981,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
2919
2981
else {
2920
2982
val dummy = localDummy(cls, impl)
2921
2983
val body1 =
2922
- addParentRefinements(
2923
- addAccessorDefs(cls,
2924
- typedStats(impl.body, dummy)(using ctx.inClassContext(self1.symbol))._1))
2984
+ implementDeferredGivens(
2985
+ addParentRefinements(
2986
+ addAccessorDefs(cls,
2987
+ typedStats(impl.body, dummy)(using ctx.inClassContext(self1.symbol))._1)))
2925
2988
2926
2989
checkNoDoubleDeclaration(cls)
2927
2990
val impl1 = cpy.Template (impl)(constr1, parents1, Nil , self1, body1)
0 commit comments