@@ -244,9 +244,7 @@ object PrepareInlineable {
244244 if (ctx.reporter.hasErrors) rawBody
245245 else ctx.compilationUnit.inlineAccessors.makeInlineable(rawBody)
246246 checkInlineMethod(inlined, typedBody)
247- val inlineableBody =
248- if (Inliner .typedInline) typedBody
249- else addReferences(inlined, originalBody, typedBody)
247+ val inlineableBody = typedBody
250248 inlining.println(i " Body to inline for $inlined: $inlineableBody" )
251249 inlineableBody
252250 })
@@ -262,182 +260,4 @@ object PrepareInlineable {
262260 em " inline unapply method can be rewritten only if its right hand side is a tuple (e1, ..., eN) " ,
263261 body.pos)
264262 }
265-
266- /** Tweak untyped tree `original` so that all external references are typed
267- * and it reflects the changes in the corresponding typed tree `typed` that
268- * make `typed` inlineable. Concretely:
269- *
270- * - all external references via identifiers or this-references are converted
271- * to typed splices,
272- * - if X gets an inline accessor in `typed`, references to X in `original`
273- * are converted to the inline accessor name.
274- */
275- private def addReferences (inlineMethod : Symbol ,
276- original : untpd.Tree , typed : tpd.Tree )(implicit ctx : Context ): tpd.Tree = {
277-
278- // Maps from positions to external reference types and inline selector names.
279- object referenced extends TreeTraverser {
280- val typeAtPos = mutable.Map [Position , Type ]()
281- val accessorAtPos = mutable.Map [Position , Symbol ]()
282- val implicitRefTypes = mutable.Set [Type ]()
283- val implicitRefs = new mutable.ListBuffer [Tree ]
284-
285- def registerIfContextualImplicit (tree : Tree ) = tree match {
286- case tree : RefTree
287- if tree.removeAttachment(ContextualImplicit ).isDefined &&
288- tree.symbol.exists &&
289- ! isLocalOrParam(tree.symbol, inlineMethod) &&
290- ! implicitRefTypes.contains(tree.tpe) =>
291- if (tree.existsSubTree(t => isLocal(tree.symbol, inlineMethod)))
292- ctx.warning(i " implicit reference $tree is dropped at inline site because it refers to local symbol(s) " , tree.pos)
293- else {
294- implicitRefTypes += tree.tpe
295- implicitRefs += tree
296- }
297- case _ =>
298- }
299-
300- def registerAccessor (tree : Tree ) = {
301- inlining.println(i " accessor: $tree at ${tree.pos}" )
302- accessorAtPos(tree.pos.toSynthetic) = tree.symbol
303- // Note: It's possible that during traversals several accessors are stored under the same
304- // position. This could happen for instance for implicit conersions added around a tree.
305- // or for a setter containing a getter in an op-assignment node.
306- // In general, it's always the innermost tree that holds the relevant symbol. The traversal
307- // order guarantees that the innermost tree's symbol is stored last, and thereby replaces all previously
308- // stored symbols.
309- }
310-
311- def traverse (tree : Tree )(implicit ctx : Context ): Unit = {
312- val sym = tree.symbol
313- tree match {
314- case Ident (nme.WILDCARD ) =>
315- case _ : Ident | _ : This =>
316- // println(i"leaf: $tree at ${tree.pos}")
317- if (sym.exists && ! isLocal(sym, inlineMethod)) {
318- if (ctx.debug) inlining.println(i " type at $tree @ ${tree.pos.toSynthetic} = ${tree.tpe}" )
319- tree.tpe match {
320- case tp : NamedType if tp.prefix.member(sym.name).isOverloaded =>
321- // refer to prefix instead of to ident directly, so that overloading can be resolved
322- // again at expansion site
323- typeAtPos(tree.pos.startPos) = tp.prefix
324- case _ =>
325- typeAtPos(tree.pos.toSynthetic) = tree.tpe
326- }
327- // Note: It's possible that during traversals several types are stored under the same
328- // position. This could happen for instance for implicit conersions added around a tree.
329- // In general, it's always the innermost tree that holds the relevant type. The traversal
330- // order guarantees that the innermost tree's type is stored last, and thereby replaces all previously
331- // stored types.
332- }
333- case _ : Select =>
334- sym.name match {
335- case InlineAccessorName (UniqueInlineName (_, _)) => return // was already recorded in Apply
336- case InlineAccessorName (_) => registerAccessor(tree)
337- case _ =>
338- }
339- case Apply (_ : RefTree | _ : TypeApply , receiver :: Nil ) =>
340- sym.name match {
341- case InlineAccessorName (UniqueInlineName (_, _)) => registerAccessor(tree)
342- case _ =>
343- }
344- case _ =>
345- }
346- registerIfContextualImplicit(tree)
347- traverseChildren(tree)
348- }
349- }
350- referenced.traverse(typed)
351-
352- // The untyped tree transform that applies the tweaks
353- object addRefs extends untpd.UntypedTreeMap {
354- override def transform (tree : untpd.Tree )(implicit ctx : Context ): untpd.Tree = {
355-
356- def adjustLeaf (tree : untpd.Tree ): untpd.Tree = referenced.typeAtPos.get(tree.pos.toSynthetic) match {
357- case Some (tpe) => untpd.TypedSplice (tree.withType(tpe))
358- case none => tree
359- }
360-
361- def adjustForAccessor (ref : untpd.RefTree ) =
362- referenced.accessorAtPos.get(ref.pos.toSynthetic) match {
363- case Some (acc) =>
364- def accessorRef = untpd.TypedSplice (tpd.ref(acc))
365- acc.name match {
366- case InlineAccessorName (UniqueInlineName (_, _)) =>
367- // In this case we are seeing a pair like this:
368- // untyped typed
369- // t.x inline$x(t)
370- // Drop the selection, since it is part of the accessor
371- val Select (qual, _) = ref
372- untpd.Apply (accessorRef, qual :: Nil )
373- case _ =>
374- accessorRef
375- }
376- case none => ref
377- }
378-
379- def adjustQualifier (tree : untpd.Tree ): untpd.Tree = tree match {
380- case tree @ Ident (name1) =>
381- referenced.typeAtPos.get(tree.pos.startPos) match {
382- case Some (tp : ThisType ) =>
383- val qual = untpd.TypedSplice (This (tp.cls).withPos(tree.pos.startPos))
384- cpy.Select (tree)(qual, name1)
385- case none =>
386- tree
387- }
388- case tree => tree
389- }
390-
391- def isAccessorLHS (lhs : untpd.Tree ): Boolean = lhs match {
392- case lhs : untpd.Apply => isAccessorLHS(lhs.fun)
393- case lhs : untpd.TypeApply => isAccessorLHS(lhs.fun)
394- case lhs : untpd.RefTree => lhs.name.is(InlineAccessorName )
395- case untpd.TypedSplice (lhs1) => lhs1.symbol.name.is(InlineAccessorName )
396- case _ => false
397- }
398-
399- val tree1 = super .transform(tree)
400- tree1 match {
401- case This (_) =>
402- adjustLeaf(tree1)
403- case tree1 : untpd.Ident =>
404- adjustQualifier(adjustLeaf(adjustForAccessor(tree1)))
405- case tree1 : untpd.Select =>
406- adjustForAccessor(tree1)
407- case Assign (lhs, rhs) if isAccessorLHS(lhs) =>
408- cpy.Apply (tree1)(lhs, rhs :: Nil )
409- case tree : untpd.DerivedTypeTree =>
410- inlining.println(i " inlining derived $tree --> ${ctx.typer.typed(tree)}" )
411- untpd.TypedSplice (ctx.typer.typed(tree))
412- case _ =>
413- tree1
414- }
415- }
416- }
417- val implicitBindings =
418- for (iref <- referenced.implicitRefs.toList) yield {
419- val localImplicit = iref.symbol.asTerm.copy(
420- owner = inlineMethod,
421- name = UniqueInlineName .fresh(iref.symbol.name.asTermName),
422- flags = Implicit | Method | Stable | iref.symbol.flags & (Inline | Erased ),
423- info = iref.tpe.widen.ensureMethodic,
424- coord = inlineMethod.pos).asTerm
425- val idef = polyDefDef(localImplicit, tps => vrefss =>
426- iref.appliedToTypes(tps).appliedToArgss(vrefss))
427- if (localImplicit.is(Inline )) {
428- // produce a Body annotation for inlining
429- def untype (tree : Tree ): untpd.Tree = tree match {
430- case Apply (fn, args) => untpd.cpy.Apply (tree)(untype(fn), args)
431- case TypeApply (fn, args) => untpd.cpy.TypeApply (tree)(untype(fn), args)
432- case _ => untpd.TypedSplice (tree)
433- }
434- val inlineBody = tpd.UntypedSplice (untype(idef.rhs)).withType(idef.rhs.tpe)
435- inlining.println(i " body annot for $idef: $inlineBody" )
436- localImplicit.addAnnotation(ConcreteBodyAnnotation (inlineBody))
437- }
438- idef
439- }
440- val untpdSplice = tpd.UntypedSplice (addRefs.transform(original)).withType(typed.tpe)
441- seq(implicitBindings, untpdSplice)
442- }
443263}
0 commit comments