@@ -256,6 +256,16 @@ object desugar {
256256 evidenceParamBuf.toList)
257257 end elimContextBounds
258258
259+ def isPreciseAnnot (tree : untpd.Tree )(using Context ): Boolean =
260+ tree match
261+ case Apply (Select (New (clsSel), _), Nil ) =>
262+ inContext(ctx.fresh.setReporter(Reporter .NoReporter ).setExploreTyperState()) {
263+ try
264+ ctx.typer.typedExpr(clsSel).tpe.classSymbol == defn.PreciseAnnot
265+ catch case _ : Throwable => false
266+ }
267+ case _ => false
268+
259269 def addDefaultGetters (meth : DefDef )(using Context ): Tree =
260270
261271 /** The longest prefix of parameter lists in paramss whose total number of
@@ -293,14 +303,33 @@ object desugar {
293303 vparam => toDefParam(vparam, keepAnnotations = true , keepDefault = false )
294304 }
295305
306+ // gets arguments should be considered precise
307+ val paramPrecises : List [Boolean ] =
308+ // indication for the type parameters preciseness
309+ val preciseMap : Map [TypeName , Boolean ] =
310+ meth.leadingTypeParams.map(t => (t.name, t.mods.annotations.exists(isPreciseAnnot))).toMap
311+ // mapping type parameters preciseness onto term parameter preciseness
312+ meth.termParamss.view.flatten.map(p => p.tpt).map {
313+ case Ident (n) => preciseMap.getOrElse(n.asTypeName, false )
314+ case _ => false
315+ }.toList
316+
296317 def defaultGetters (paramss : List [ParamClause ], n : Int ): List [DefDef ] = paramss match
297318 case ValDefs (vparam :: vparams) :: paramss1 =>
298319 def defaultGetter : DefDef =
320+ val (rhs, tpt) =
321+ // if the parameter is precise, then we add explicit return type for the
322+ // definition to keep the precise type after precise typing.
323+ if paramPrecises(n) then
324+ val rhsTyped = withMode(Mode .Precise ){ctx.typer.typedExpr(vparam.rhs)}
325+ (TypedSplice (rhsTyped), TypeTree (rhsTyped.tpe))
326+ // otherwise, the desugaring is unchanged from the status quo
327+ else (vparam.rhs, TypeTree ())
299328 DefDef (
300329 name = DefaultGetterName (meth.name, n),
301330 paramss = getterParamss(n),
302- tpt = TypeTree () ,
303- rhs = vparam. rhs
331+ tpt = tpt ,
332+ rhs = rhs
304333 )
305334 .withMods(Modifiers (
306335 meth.mods.flags & (AccessFlags | Synthetic ) | (vparam.mods.flags & Inline ),
@@ -381,9 +410,10 @@ object desugar {
381410
382411 @ sharable private val synthetic = Modifiers (Synthetic )
383412
384- private def toDefParam (tparam : TypeDef , keepAnnotations : Boolean ): TypeDef = {
413+ private def toDefParam (tparam : TypeDef , keepAnnotations : Boolean )( using Context ) : TypeDef = {
385414 var mods = tparam.rawMods
386- if (! keepAnnotations) mods = mods.withAnnotations(Nil )
415+ val onlyPreciseAnnot = mods.annotations.filter(isPreciseAnnot)
416+ if (! keepAnnotations) mods = mods.withAnnotations(onlyPreciseAnnot)
387417 tparam.withMods(mods & EmptyFlags | Param )
388418 }
389419 private def toDefParam (vparam : ValDef , keepAnnotations : Boolean , keepDefault : Boolean ): ValDef = {
0 commit comments