@@ -3115,52 +3115,55 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31153115 * parameters of the current class are also defined.
31163116 */
31173117 def implementDeferredGivens (body : List [Tree ]): List [Tree ] =
3118+ def failFor (mbr : TermRef , why : String ): false =
3119+ report.error(
3120+ em """ Cannot infer the implementation of the deferred ${mbr.symbol.showLocated}
3121+ |since $why. An implementing given needs to be written explicitly. """ ,
3122+ cdef.srcPos)
3123+ false
3124+ def isGivenValue (mbr : TermRef ) = ! mbr.symbol.is(Method ) || failFor(mbr, " that given is parameterized" )
3125+
3126+ def willBeImplementedInParentClass (m : TermRef ) =
3127+ val superCls = cls.superClass
3128+ superCls.exists && superCls.asClass.baseClasses.contains(m.symbol.owner)
3129+
3130+ def givenImpl (mbr : TermRef ): ValDef =
3131+ val dcl = mbr.symbol
3132+ val target = dcl.info.asSeenFrom(cls.thisType, dcl.owner)
3133+ val constr = cls.primaryConstructor
3134+ val usingParamAccessors = cls.paramAccessors.filter(_.is(Given ))
3135+ val paramScope = newScopeWith(usingParamAccessors* )
3136+ val searchCtx = ctx.outer.fresh.setScope(paramScope)
3137+ val rhs = implicitArgTree(target, cdef.span,
3138+ where = i " inferring the implementation of the deferred ${dcl.showLocated}"
3139+ )(using searchCtx)
3140+ val resolvedHere =
3141+ rhs.tpe match
3142+ case tp : NamedType => (tp.prefix.typeSymbol eq cls) && tp.name == mbr.name && ! tp.typeSymbol.is(Method )
3143+ case _ => false
3144+ if resolvedHere then failFor(mbr, " the result is self-recursive" )
3145+
3146+ val impl = dcl.copy(cls,
3147+ flags = dcl.flags &~ (HasDefault | Deferred ) | Final | Override ,
3148+ info = target,
3149+ coord = rhs.span).entered.asTerm
3150+
3151+ def anchorParams = new TreeMap :
3152+ override def transform (tree : Tree )(using Context ): Tree = tree match
3153+ case id : Ident if usingParamAccessors.contains(id.symbol) =>
3154+ cpy.Select (id)(This (cls), id.name)
3155+ case _ =>
3156+ super .transform(tree)
3157+ ValDef (impl, anchorParams.transform(rhs)).withSpan(impl.span.endPos)
3158+ end givenImpl
3159+
31183160 if cls.is(Trait ) || ctx.isAfterTyper then body
31193161 else
3120- def isGivenValue (mbr : TermRef ) =
3121- val dcl = mbr.symbol
3122- if dcl.is(Method ) then
3123- report.error(
3124- em """ Cannnot infer the implementation of the deferred ${dcl.showLocated}
3125- |since that given is parameterized. An implementing given needs to be written explicitly. """ ,
3126- cdef.srcPos)
3127- false
3128- else true
3129-
3130- def willBeimplementedInParentClass (m : TermRef ) =
3131- val superCls = cls.superClass
3132- superCls.exists && superCls.asClass.baseClasses.contains(m.symbol.owner)
3133-
3134- def givenImpl (mbr : TermRef ): ValDef =
3135- val dcl = mbr.symbol
3136- val target = dcl.info.asSeenFrom(cls.thisType, dcl.owner)
3137- val constr = cls.primaryConstructor
3138- val usingParamAccessors = cls.paramAccessors.filter(_.is(Given ))
3139- val paramScope = newScopeWith(usingParamAccessors* )
3140- val searchCtx = ctx.outer.fresh.setScope(paramScope)
3141- val rhs = implicitArgTree(target, cdef.span,
3142- where = i " inferring the implementation of the deferred ${dcl.showLocated}"
3143- )(using searchCtx)
3144-
3145- val impl = dcl.copy(cls,
3146- flags = dcl.flags &~ (HasDefault | Deferred ) | Final | Override ,
3147- info = target,
3148- coord = rhs.span).entered.asTerm
3149-
3150- def anchorParams = new TreeMap :
3151- override def transform (tree : Tree )(using Context ): Tree = tree match
3152- case id : Ident if usingParamAccessors.contains(id.symbol) =>
3153- cpy.Select (id)(This (cls), id.name)
3154- case _ =>
3155- super .transform(tree)
3156- ValDef (impl, anchorParams.transform(rhs)).withSpan(impl.span.endPos)
3157- end givenImpl
3158-
31593162 val givenImpls =
31603163 cls.thisType.implicitMembers
31613164 // .showing(i"impl def givens for $cls/$result")
31623165 .filter(_.symbol.isAllOf(DeferredGivenFlags , butNot = Param ))
3163- .filter(! willBeimplementedInParentClass (_)) // only implement the given in the topmost class
3166+ .filter(! willBeImplementedInParentClass (_)) // only implement the given in the topmost class
31643167 // .showing(i"impl def filtered givens for $cls/$result")
31653168 .filter(isGivenValue)
31663169 .map(givenImpl)
0 commit comments