@@ -127,7 +127,6 @@ class Staging extends MacroTransformWithImplicits {
127
127
*/
128
128
val importedTags = new mutable.LinkedHashMap [TypeRef , Tree ]()
129
129
130
-
131
130
/** A stack of entered symbols, to be unwound after scope exit */
132
131
var enteredSyms : List [Symbol ] = Nil
133
132
@@ -267,68 +266,80 @@ class Staging extends MacroTransformWithImplicits {
267
266
* @return Some(msg) if unsuccessful where `msg` is a potentially empty error message
268
267
* to be added to the "inconsistent phase" message.
269
268
*/
270
- def tryHeal (tp : Type , pos : SourcePosition )(implicit ctx : Context ): Option [String ] = tp match {
271
- case tp : TypeRef =>
272
- if (level == - 1 ) {
273
- assert(ctx.inInlineMethod)
274
- None
275
- } else {
276
- val reqType = defn.QuotedTypeType .appliedTo(tp)
277
- val tag = ctx.typer.inferImplicitArg(reqType, pos.span)
278
- tag.tpe match {
279
- case fail : SearchFailureType =>
280
- Some (i """
281
- |
282
- | The access would be accepted with the right type tag, but
283
- | ${ctx.typer.missingArgMsg(tag, reqType, " " )}""" )
284
- case _ =>
285
- importedTags(tp) = nested(isQuote = false ).transform(tag)
286
- None
269
+ def tryHeal (sym : Symbol , tp : Type , pos : SourcePosition )(implicit ctx : Context ): Option [Tree ] = {
270
+ def levelError (errMsg : String ) = {
271
+ def symStr =
272
+ if (! tp.isInstanceOf [ThisType ]) sym.show
273
+ else if (sym.is(ModuleClass )) sym.sourceModule.show
274
+ else i " ${sym.name}.this "
275
+ ctx.error(
276
+ em """ access to $symStr from wrong staging level:
277
+ | - the definition is at level ${levelOf.getOrElse(sym, 0 )},
278
+ | - but the access is at level $level. $errMsg""" , pos)
279
+ None
280
+ }
281
+ tp match {
282
+ case tp : TypeRef =>
283
+ if (level == - 1 ) {
284
+ assert(ctx.inInlineMethod)
285
+ None
286
+ } else {
287
+ val reqType = defn.QuotedTypeType .appliedTo(tp)
288
+ val tag = ctx.typer.inferImplicitArg(reqType, pos.span)
289
+ tag.tpe match {
290
+ case fail : SearchFailureType =>
291
+ levelError(i """
292
+ |
293
+ | The access would be accepted with the right type tag, but
294
+ | ${ctx.typer.missingArgMsg(tag, reqType, " " )}""" )
295
+ case _ =>
296
+ importedTags(tp) = nested(isQuote = false ).transform(tag) // TODO remove me
297
+ Some (nested(isQuote = false ).transform(tag).select(tpnme.UNARY_~ )) // TODO remove the transform?
298
+ }
287
299
}
288
- }
289
- case _ =>
290
- Some ( " " )
300
+ case _ =>
301
+ levelError( " " )
302
+ }
291
303
}
292
304
293
305
/** Check reference to `sym` for phase consistency, where `tp` is the underlying type
294
306
* by which we refer to `sym`.
295
307
*/
296
- def check (sym : Symbol , tp : Type , pos : SourcePosition )(implicit ctx : Context ): Unit = {
308
+ def check (sym : Symbol , tp : Type , pos : SourcePosition )(implicit ctx : Context ): Option [ Tree ] = {
297
309
val isThis = tp.isInstanceOf [ThisType ]
298
- def symStr =
299
- if (! isThis) sym.show
300
- else if (sym.is(ModuleClass )) sym.sourceModule.show
301
- else i " ${sym.name}.this "
302
310
if (! isThis && sym.maybeOwner.isType && ! sym.is(Param ))
303
311
check(sym.owner, sym.owner.thisType, pos)
304
312
else if (sym.exists && ! sym.isStaticOwner && ! levelOK(sym))
305
- for (errMsg <- tryHeal(tp, pos))
306
- ctx.error(em """ access to $symStr from wrong staging level:
307
- | - the definition is at level ${levelOf.getOrElse(sym, 0 )},
308
- | - but the access is at level $level. $errMsg""" , pos)
313
+ tryHeal(sym, tp, pos)
314
+ else
315
+ None
309
316
}
310
317
311
318
/** Check all named types and this-types in a given type for phase consistency. */
312
- def checkType (pos : SourcePosition )(implicit ctx : Context ): TypeAccumulator [ Unit ] = new TypeAccumulator [ Unit ] {
313
- def apply (acc : Unit , tp : Type ): Unit = reporting.trace(i " check type level $tp at $level" ) {
319
+ def checkType (pos : SourcePosition )(implicit ctx : Context ): TypeMap = new TypeMap {
320
+ def apply (tp : Type ): Type = reporting.trace(i " check type level $tp at $level" ) {
314
321
tp match {
315
322
case tp : TypeRef if tp.symbol.isSplice =>
316
323
if (inQuote) {
317
- outer.checkType(pos).foldOver(acc, tp)
324
+ // TODO add level to checkType TypeMap and avoid accessing the outer one?
325
+ outer.checkType(pos).mapOver(tp)
318
326
}
319
327
else {
320
328
if (tp.isTerm) ctx.error(i " splice outside quotes " , pos)
321
329
tp
322
330
}
323
331
case tp : NamedType =>
324
- check(tp.symbol, tp, tp.symbol.sourcePos)
325
- if (! tp.symbol.is(Param ))
326
- foldOver(acc, tp)
332
+ check(tp.symbol, tp, tp.symbol.sourcePos) match {
333
+ case Some (tpRef) => tpRef.tpe
334
+ case _ =>
335
+ if (tp.symbol.is(Param )) tp
336
+ else mapOver(tp)
337
+ }
327
338
case tp : ThisType =>
328
- check(tp.cls, tp, tp.cls.sourcePos)
329
- foldOver(acc, tp)
339
+ assert( check(tp.cls, tp, tp.cls.sourcePos).isEmpty )
340
+ mapOver( tp)
330
341
case _ =>
331
- foldOver(acc, tp)
342
+ mapOver( tp)
332
343
}
333
344
}
334
345
}
@@ -348,19 +359,32 @@ class Staging extends MacroTransformWithImplicits {
348
359
*/
349
360
private def checkLevel (tree : Tree )(implicit ctx : Context ): Tree = {
350
361
tree match {
351
- case (_ : Ident ) | (_ : This ) =>
352
- check(tree.symbol, tree.tpe, tree.sourcePos)
362
+ case _ : This =>
363
+ assert(check(tree.symbol, tree.tpe, tree.sourcePos).isEmpty)
364
+ tree
365
+ case _ : Ident =>
366
+ check(tree.symbol, tree.tpe, tree.sourcePos) match {
367
+ case Some (tpRef) => tpRef
368
+ case _ => tree
369
+ }
353
370
case (_ : UnApply ) | (_ : TypeTree ) =>
354
- checkType(tree.sourcePos).apply((), tree.tpe)
371
+ checkType(tree.sourcePos).apply(tree.tpe)
372
+ tree
355
373
case Select (qual, OuterSelectName (_, levels)) =>
356
- checkType(tree.sourcePos).apply((), tree.tpe.widen)
374
+ checkType(tree.sourcePos).apply(tree.tpe.widen)
375
+ tree
357
376
case _ : Bind =>
358
- checkType(tree.sourcePos).apply((), tree.symbol.info)
377
+ checkType(tree.sourcePos).apply(tree.symbol.info)
378
+ tree
359
379
case _ : Template =>
360
- checkType(tree.sourcePos).apply((), tree.symbol.owner.asClass.givenSelfType)
380
+ checkType(tree.sourcePos).apply(tree.symbol.owner.asClass.givenSelfType)
381
+ tree
382
+ case tree : Typed =>
383
+ val tp = checkType(tree.sourcePos).apply(tree.tpe)
384
+ tree.withType(tp)
361
385
case _ =>
386
+ tree
362
387
}
363
- tree
364
388
}
365
389
366
390
/** Split `body` into a core and a list of embedded splices.
@@ -424,7 +448,8 @@ class Staging extends MacroTransformWithImplicits {
424
448
/** Transform `tree` followed by `addTags` transform. */
425
449
private def transformAndAddTags (tree : Tree )(implicit ctx : Context ): Tree = {
426
450
assert(inQuote)
427
- addTags(transform(tree))
451
+ // addTags(transform(tree))
452
+ transform(tree)
428
453
}
429
454
430
455
override def transform (tree : Tree )(implicit ctx : Context ): Tree =
@@ -449,11 +474,11 @@ class Staging extends MacroTransformWithImplicits {
449
474
if (tree.isType || level == 0 ) splice(tree)
450
475
else {
451
476
// TODO add comment '{ ~(...: T) } --> '{ ~(...: T).asInstanceOf[T] } --> '{ ~(...: T).asInstanceOf[~t] }
452
- val tp = tree.tpe.widenTermRefExpr
453
- checkType(tree.sourcePos).apply((), tp)
477
+ val tp = checkType(tree.sourcePos).apply(tree.tpe.widenTermRefExpr)
454
478
splice(tree).asInstance(tp).withSpan(tree.span)
455
479
}
456
480
}
481
+ // TODO remove this case?
457
482
case tree : RefTree if tree.symbol.is(Inline ) && tree.symbol.is(Param ) =>
458
483
tree
459
484
case Block (stats, _) =>
@@ -495,18 +520,17 @@ class Staging extends MacroTransformWithImplicits {
495
520
case tree : DefDef if tree.symbol.is(Macro ) && level > 0 =>
496
521
mapOverTree(enteredSyms)
497
522
EmptyTree
523
+ case tree : ValDef =>
524
+ markDef(tree)
525
+ val tree1 @ ValDef (_, tpt, _) = checkLevel(mapOverTree(enteredSyms))
526
+ tree1.symbol.info = tpt.tpe // TODO transform in a cleaner way
527
+ tree1
498
528
case _ =>
499
529
markDef(tree)
500
530
checkLevel(mapOverTree(enteredSyms))
501
531
}
502
532
}
503
533
504
- private def liftList (list : List [Tree ], tpe : Type )(implicit ctx : Context ): Tree = {
505
- list.foldRight[Tree ](ref(defn.NilModule )) { (x, acc) =>
506
- acc.select(" ::" .toTermName).appliedToType(tpe).appliedTo(x)
507
- }
508
- }
509
-
510
534
/** InlineSplice is used to detect cases where the expansion
511
535
* consists of a (possibly multiple & nested) block or a sole expression.
512
536
*/
0 commit comments