@@ -12,13 +12,17 @@ import SymDenotations.SymDenotation
12
12
import config .Printers .inlining
13
13
import ErrorReporting .errorTree
14
14
import dotty .tools .dotc .util .{SourceFile , SourcePosition , SrcPos }
15
+ import dotty .tools .dotc .transform .*
16
+ import dotty .tools .dotc .transform .MegaPhase
17
+ import dotty .tools .dotc .transform .MegaPhase .MiniPhase
15
18
import parsing .Parsers .Parser
16
19
import transform .{PostTyper , Inlining , CrossVersionChecks }
17
20
import staging .StagingLevel
18
21
19
22
import collection .mutable
20
23
import reporting .{NotConstant , trace }
21
24
import util .Spans .Span
25
+ import dotty .tools .dotc .core .Periods .PhaseId
22
26
23
27
/** Support for querying inlineable methods and for inlining calls to such methods */
24
28
object Inlines :
@@ -343,10 +347,53 @@ object Inlines:
343
347
if Inlines .isInlineable(codeArg1.symbol) then stripTyped(Inlines .inlineCall(codeArg1))
344
348
else codeArg1
345
349
350
+ class MegaPhaseWithCustomPhaseId (miniPhases : Array [MiniPhase ], startId : PhaseId , endId : PhaseId )
351
+ extends MegaPhase (miniPhases) {
352
+ override def start : Int = startId
353
+ override def end : Int = endId
354
+ }
355
+
346
356
ConstFold (underlyingCodeArg).tpe.widenTermRefExpr match {
347
357
case ConstantType (Constant (code : String )) =>
348
- val source2 = SourceFile .virtual(" tasty-reflect" , code)
349
- inContext(ctx.fresh.setNewTyperState().setTyper(new Typer (ctx.nestingLevel + 1 )).setSource(source2)) {
358
+ val unitName = " tasty-reflect"
359
+ val source2 = SourceFile .virtual(unitName, code)
360
+ // We need a dummy owner, as the actual one does not have a computed denotation yet,
361
+ // but might be inspected in a transform phase, leading to cyclic errors
362
+ val dummyOwner = newSymbol(ctx.owner, " $dummySymbol$" .toTermName, Private , defn.AnyType , NoSymbol )
363
+ val newContext =
364
+ ctx.fresh.setNewTyperState().setTyper(new Typer (ctx.nestingLevel + 1 )).setSource(source2)
365
+
366
+ inContext(newContext) {
367
+ // Let's reconstruct necessary transform MegaPhases, without anything
368
+ // that could cause problems here (like `CrossVersionChecks`).
369
+ // The individiual lists here should line up with Compiler.scala, i.e
370
+ // separate chunks there should also be kept separate here.
371
+ // For now we create a single MegaPhase, since there does not seem to
372
+ // be any important checks later (e.g. ForwardDepChecks could be applicable here,
373
+ // but the equivalent is also not run in the scala 2's `ctx.typechecks`,
374
+ // so let's leave it out for now).
375
+ val transformPhases : List [List [(Class [? ], () => MiniPhase )]] = List (
376
+ List (
377
+ (classOf [InlineVals ], () => new InlineVals ),
378
+ (classOf [ElimRepeated ], () => new ElimRepeated ),
379
+ (classOf [RefChecks ], () => new RefChecks ),
380
+ ),
381
+ )
382
+
383
+ val mergedTransformPhases =
384
+ transformPhases.flatMap( (megaPhaseList : List [(Class [? ], () => MiniPhase )]) =>
385
+ val (newMegaPhasePhases, phaseIds) =
386
+ megaPhaseList
387
+ .flatMap { filteredPhase =>
388
+ ctx.base.phases.find(phase => filteredPhase._1.isInstance(phase)).map { a =>
389
+ (filteredPhase._2(), a.id)
390
+ }
391
+ }
392
+ .unzip
393
+ if newMegaPhasePhases.isEmpty then None
394
+ else Some (MegaPhaseWithCustomPhaseId (newMegaPhasePhases.toArray, phaseIds.head, phaseIds.last))
395
+ )
396
+
350
397
val tree2 = new Parser (source2).block()
351
398
if ctx.reporter.allErrors.nonEmpty then
352
399
ctx.reporter.allErrors.map((ErrorKind .Parser , _))
@@ -355,10 +402,24 @@ object Inlines:
355
402
ctx.base.postTyperPhase match
356
403
case postTyper : PostTyper if ctx.reporter.allErrors.isEmpty =>
357
404
val tree4 = atPhase(postTyper) { postTyper.newTransformer.transform(tree3) }
358
- ctx.base.inliningPhase match
359
- case inlining : Inlining if ctx.reporter.allErrors.isEmpty =>
360
- atPhase(inlining) { inlining.newTransformer.transform(tree4) }
361
- case _ =>
405
+ ctx.base.setRootTreePhase match
406
+ case setRootTree =>
407
+ val tree5 =
408
+ val compilationUnit = CompilationUnit (unitName, code)
409
+ compilationUnit.tpdTree = tree4
410
+ compilationUnit.untpdTree = tree2
411
+ var units = List (compilationUnit)
412
+ atPhase(setRootTree)(setRootTree.runOn(units).head.tpdTree)
413
+
414
+ ctx.base.inliningPhase match
415
+ case inlining : Inlining if ctx.reporter.allErrors.isEmpty =>
416
+ val tree6 = atPhase(inlining) { inlining.newTransformer.transform(tree5) }
417
+ if mergedTransformPhases.nonEmpty then
418
+ var transformTree = tree6
419
+ for (phase <- mergedTransformPhases if ctx.reporter.allErrors.isEmpty) {
420
+ transformTree = atPhase(phase.end + 1 )(phase.transformUnit(transformTree))
421
+ }
422
+ case _ =>
362
423
case _ =>
363
424
ctx.reporter.allErrors.map((ErrorKind .Typer , _))
364
425
}
0 commit comments