Skip to content

Commit eae5a38

Browse files
Merge pull request #6233 from dotty-staging/fix-scope-exists
Fix Scope.exists and some missing Inlined trees
2 parents 574fd0c + e219f7e commit eae5a38

File tree

6 files changed

+28
-11
lines changed

6 files changed

+28
-11
lines changed

compiler/src/dotty/tools/dotc/core/Scopes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ object Scopes {
106106
}
107107

108108
/** Tests whether a predicate holds for at least one Symbol of this Scope. */
109-
def exists(p: Symbol => Boolean)(implicit ctx: Context): Boolean = filter(p).isEmpty
109+
def exists(p: Symbol => Boolean)(implicit ctx: Context): Boolean = filter(p).nonEmpty
110110

111111
/** Finds the first Symbol of this Scope satisfying a predicate, if any. */
112112
def find(p: Symbol => Boolean)(implicit ctx: Context): Symbol = filter(p) match {

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
224224
super.transform(tree1)
225225
}
226226
case Inlined(call, bindings, expansion) if !call.isEmpty =>
227-
val callTrace = Inliner.inlineCallTrace(call.symbol, call.sourcePos)
227+
val pos = call.sourcePos
228+
val callTrace = Inliner.inlineCallTrace(call.symbol, pos)(ctx.withSource(pos.source))
228229
cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(inlineContext(call)))
229230
case tree: Template =>
230231
withNoCheckNews(tree.parents.flatMap(newPart)) {

compiler/src/dotty/tools/dotc/transform/YCheckPositions.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ class YCheckPositions extends Phases.Phase {
4040
assert(bindings.isEmpty)
4141
val old = sources
4242
sources = old.tail
43-
traverse(expansion)(inlineContext(EmptyTree))
43+
traverse(expansion)(inlineContext(EmptyTree).withSource(sources.head))
4444
sources = old
4545
case Inlined(call, bindings, expansion) =>
4646
bindings.foreach(traverse(_))
4747
sources = call.symbol.topLevelClass.source :: sources
4848
if (!isMacro(call)) // FIXME macro implementations can drop Inlined nodes. We should reinsert them after macro expansion based on the positions of the trees
49-
traverse(expansion)(inlineContext(call))
49+
traverse(expansion)(inlineContext(call).withSource(sources.head))
5050
sources = sources.tail
5151
case _ => traverseChildren(tree)
5252
}
@@ -57,8 +57,9 @@ class YCheckPositions extends Phases.Phase {
5757
}
5858

5959
private def isMacro(call: Tree)(implicit ctx: Context) = {
60-
if (ctx.phase <= ctx.typerPhase.next) call.symbol.is(Macro)
61-
else (call.symbol.unforcedDecls.exists(_.is(Macro)) || call.symbol.unforcedDecls.toList.exists(_.is(Macro)))
60+
if (ctx.phase <= ctx.postTyperPhase) call.symbol.is(Macro)
61+
else call.isInstanceOf[Select] // The call of a macro after typer is encoded as a Select while other inlines are Ident
62+
// TODO remove this distinction once Inline nodes of expanded macros can be trusted (also in Inliner.inlineCallTrace)
6263
}
6364

6465
}

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,12 @@ object Inliner {
180180
* - the call's position
181181
* in the call field of an Inlined node.
182182
* The trace has enough info to completely reconstruct positions.
183+
* Note: For macros it returns a Select and for other inline methods it returns an Ident (this distinction is only temporary to be able to run YCheckPositions)
183184
*/
184185
def inlineCallTrace(callSym: Symbol, pos: SourcePosition)(implicit ctx: Context): Tree = {
185-
implicit val src = pos.source
186-
Ident(callSym.topLevelClass.typeRef).withSpan(pos.span)
186+
assert(ctx.source == pos.source)
187+
if (callSym.is(Macro)) ref(callSym.topLevelClass.owner).select(callSym.topLevelClass.name).withSpan(pos.span)
188+
else Ident(callSym.topLevelClass.typeRef).withSpan(pos.span)
187189
}
188190
}
189191

@@ -250,7 +252,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
250252
* @param bindingsBuf the buffer to which the definition should be appended
251253
*/
252254
private def paramBindingDef(name: Name, paramtp: Type, arg: Tree,
253-
bindingsBuf: mutable.ListBuffer[ValOrDefDef]): ValOrDefDef = {
255+
bindingsBuf: mutable.ListBuffer[ValOrDefDef])(implicit ctx: Context): ValOrDefDef = {
254256
val argtpe = arg.tpe.dealiasKeepAnnots
255257
val isByName = paramtp.dealias.isInstanceOf[ExprType]
256258
var inlineFlag = InlineProxy
@@ -694,15 +696,15 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
694696
val argSyms = (mt.paramNames, mt.paramInfos, args).zipped.map { (name, paramtp, arg) =>
695697
arg.tpe.dealias match {
696698
case ref @ TermRef(NoPrefix, _) => ref.symbol
697-
case _ => paramBindingDef(name, paramtp, arg, bindingsBuf).symbol
699+
case _ => paramBindingDef(name, paramtp, arg, bindingsBuf)(ctx.withSource(cl.source)).symbol
698700
}
699701
}
700702
val expander = new TreeTypeMap(
701703
oldOwners = ddef.symbol :: Nil,
702704
newOwners = ctx.owner :: Nil,
703705
substFrom = ddef.vparamss.head.map(_.symbol),
704706
substTo = argSyms)
705-
seq(bindingsBuf.toList, expander.transform(ddef.rhs))
707+
Inlined(ddef, bindingsBuf.toList, expander.transform(ddef.rhs))
706708
case _ => tree
707709
}
708710
case _ => tree

tests/run/i4431-b/quoted_1.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
inline def h(f: => Int => String): String = f(42)
5+
}

tests/run/i4431-b/quoted_2.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
println(h(x => "abc" + x))
7+
}
8+
}

0 commit comments

Comments
 (0)