@@ -3143,52 +3143,55 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31433143 * parameters of the current class are also defined.
31443144 */
31453145 def implementDeferredGivens (body : List [Tree ]): List [Tree ] =
3146+ def failFor (mbr : TermRef , why : String ): false =
3147+ report.error(
3148+ em """ Cannot infer the implementation of the deferred ${mbr.symbol.showLocated}
3149+ |since $why. An implementing given needs to be written explicitly. """ ,
3150+ cdef.srcPos)
3151+ false
3152+ def isGivenValue (mbr : TermRef ) = ! mbr.symbol.is(Method ) || failFor(mbr, " that given is parameterized" )
3153+
3154+ def willBeImplementedInParentClass (m : TermRef ) =
3155+ val superCls = cls.superClass
3156+ superCls.exists && superCls.asClass.baseClasses.contains(m.symbol.owner)
3157+
3158+ def givenImpl (mbr : TermRef ): ValDef =
3159+ val dcl = mbr.symbol
3160+ val target = dcl.info.asSeenFrom(cls.thisType, dcl.owner)
3161+ val constr = cls.primaryConstructor
3162+ val usingParamAccessors = cls.paramAccessors.filter(_.is(Given ))
3163+ val paramScope = newScopeWith(usingParamAccessors* )
3164+ val searchCtx = ctx.outer.fresh.setScope(paramScope)
3165+ val rhs = implicitArgTree(target, cdef.span,
3166+ where = i " inferring the implementation of the deferred ${dcl.showLocated}"
3167+ )(using searchCtx)
3168+ val resolvedHere =
3169+ rhs.tpe match
3170+ case tp : NamedType => (tp.prefix.typeSymbol eq cls) && tp.name == mbr.name && ! tp.typeSymbol.is(Method )
3171+ case _ => false
3172+ if resolvedHere then failFor(mbr, " the result is self-recursive" )
3173+
3174+ val impl = dcl.copy(cls,
3175+ flags = dcl.flags &~ (HasDefault | Deferred ) | Final | Override ,
3176+ info = target,
3177+ coord = rhs.span).entered.asTerm
3178+
3179+ def anchorParams = new TreeMap :
3180+ override def transform (tree : Tree )(using Context ): Tree = tree match
3181+ case id : Ident if usingParamAccessors.contains(id.symbol) =>
3182+ cpy.Select (id)(This (cls), id.name)
3183+ case _ =>
3184+ super .transform(tree)
3185+ ValDef (impl, anchorParams.transform(rhs)).withSpan(impl.span.endPos)
3186+ end givenImpl
3187+
31463188 if cls.is(Trait ) || ctx.isAfterTyper then body
31473189 else
3148- def isGivenValue (mbr : TermRef ) =
3149- val dcl = mbr.symbol
3150- if dcl.is(Method ) then
3151- report.error(
3152- em """ Cannnot infer the implementation of the deferred ${dcl.showLocated}
3153- |since that given is parameterized. An implementing given needs to be written explicitly. """ ,
3154- cdef.srcPos)
3155- false
3156- else true
3157-
3158- def willBeimplementedInParentClass (m : TermRef ) =
3159- val superCls = cls.superClass
3160- superCls.exists && superCls.asClass.baseClasses.contains(m.symbol.owner)
3161-
3162- def givenImpl (mbr : TermRef ): ValDef =
3163- val dcl = mbr.symbol
3164- val target = dcl.info.asSeenFrom(cls.thisType, dcl.owner)
3165- val constr = cls.primaryConstructor
3166- val usingParamAccessors = cls.paramAccessors.filter(_.is(Given ))
3167- val paramScope = newScopeWith(usingParamAccessors* )
3168- val searchCtx = ctx.outer.fresh.setScope(paramScope)
3169- val rhs = implicitArgTree(target, cdef.span,
3170- where = i " inferring the implementation of the deferred ${dcl.showLocated}"
3171- )(using searchCtx)
3172-
3173- val impl = dcl.copy(cls,
3174- flags = dcl.flags &~ (HasDefault | Deferred ) | Final | Override ,
3175- info = target,
3176- coord = rhs.span).entered.asTerm
3177-
3178- def anchorParams = new TreeMap :
3179- override def transform (tree : Tree )(using Context ): Tree = tree match
3180- case id : Ident if usingParamAccessors.contains(id.symbol) =>
3181- cpy.Select (id)(This (cls), id.name)
3182- case _ =>
3183- super .transform(tree)
3184- ValDef (impl, anchorParams.transform(rhs)).withSpan(impl.span.endPos)
3185- end givenImpl
3186-
31873190 val givenImpls =
31883191 cls.thisType.implicitMembers
31893192 // .showing(i"impl def givens for $cls/$result")
31903193 .filter(_.symbol.isAllOf(DeferredGivenFlags , butNot = Param ))
3191- .filter(! willBeimplementedInParentClass (_)) // only implement the given in the topmost class
3194+ .filter(! willBeImplementedInParentClass (_)) // only implement the given in the topmost class
31923195 // .showing(i"impl def filtered givens for $cls/$result")
31933196 .filter(isGivenValue)
31943197 .map(givenImpl)
0 commit comments