diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-10-02 17:21:27 +0200 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-11-12 18:40:01 -0800 |
commit | a2b523a39b4e56eb9ab5d9a5639f5b59d425e354 (patch) | |
tree | 8d91dd18059b1166d9e7d3ee6a1ab22166d0ae7b /src | |
parent | ce37ae45e22463a3f1a2d659d6699f2977b26c6b (diff) | |
download | scala-a2b523a39b4e56eb9ab5d9a5639f5b59d425e354.tar.gz scala-a2b523a39b4e56eb9ab5d9a5639f5b59d425e354.tar.bz2 scala-a2b523a39b4e56eb9ab5d9a5639f5b59d425e354.zip |
blackbox restriction #1: can't refine the official return type
When an application of a blackbox macro expands into a tree `x`,
the expansion is wrapped into a type ascription `(x: T)`, where `T` is
the declared return type of the blackbox macro with type arguments and
path dependencies applied in consistency with the particular macro
application being expanded.
This invalidates blackbox macros as an implementation vehicle
of type providers.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Macros.scala | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index f1b9bd4833..57358f72f5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -604,21 +604,27 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { */ def macroExpandApply(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = { object expander extends TermMacroExpander(APPLY_ROLE, typer, expandee, mode, pt) { - override def onSuccess(expanded: Tree) = { + override def onSuccess(expanded0: Tree) = { + def approximate(tp: Type) = { + // approximation is necessary for whitebox macros to guide type inference + // read more in the comments for onDelayed below + if (isBlackbox(expandee)) tp + else { + val undetparams = tp collect { case tp if tp.typeSymbol.isTypeParameter => tp.typeSymbol } + deriveTypeWithWildcards(undetparams)(tp) + } + } + val macroPt = approximate(if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe) + val expanded = if (isBlackbox(expandee)) atPos(enclosingMacroPosition.focus)(Typed(expanded0, TypeTree(macroPt))) else expanded0 + // prematurely annotate the tree with a macro expansion attachment // so that adapt called indirectly by typer.typed knows that it needs to apply the existential fixup linkExpandeeAndExpanded(expandee, expanded) - // approximation is necessary for whitebox macros to guide type inference - // read more in the comments for onDelayed below - def approximate(tp: Type) = { - val undetparams = tp collect { case tp if tp.typeSymbol.isTypeParameter => tp.typeSymbol } - deriveTypeWithWildcards(undetparams)(tp) - } - val macroPtApprox = approximate(if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe) + // `macroExpandApply` is called from `adapt`, where implicit conversions are disabled // therefore we need to re-enable the conversions back temporarily - if (macroDebugVerbose) println(s"typecheck #1 (against macroPtApprox = $macroPtApprox): $expanded") - val expanded1 = typer.context.withImplicitsEnabled(typer.typed(expanded, mode, macroPtApprox)) + if (macroDebugVerbose) println(s"typecheck #1 (against macroPt = $macroPt): $expanded") + val expanded1 = typer.context.withImplicitsEnabled(typer.typed(expanded, mode, macroPt)) if (expanded1.isErrorTyped) { if (macroDebugVerbose) println(s"typecheck #1 has failed: ${typer.context.reportBuffer.errors}") expanded1 |