Skip to content

Commit

Permalink
Merge pull request #10188 from som-snytt/issue/12647-more-whitebox
Browse files Browse the repository at this point in the history
Ignore override type just for whitebox expansion
  • Loading branch information
lrytz committed Oct 26, 2022
2 parents 384c440 + 8ecb219 commit 8fa1e7c
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 2 deletions.
24 changes: 22 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Namers.scala
Expand Up @@ -1120,14 +1120,34 @@ trait Namers extends MethodSynthesis {

/** Computes the type of the body in a ValDef or DefDef, and
* assigns the type to the tpt's node. Returns the type.
*
* Under `-Xsource:3`, use `pt`, the type of the overridden member.
* But preserve the precise type of a whitebox macro.
* For `def f = macro g`, here we see `def f = xp(g)` the expansion,
* not the `isMacro` case: `openMacros` will be nonEmpty.
* For `def m = f`, retrieve the typed RHS and check if it is an expansion;
* in that case, check if the expandee `f` is whitebox and preserve
* the precise type if it is. The user must provide an explicit type
* to "opt out" of the inferred narrow type; in Scala 3, they would
* inline the def to "opt in".
*/
private def assignTypeToTree(tree: ValOrDefDef, defnTyper: Typer, pt: Type): Type = {
val rhsTpe = tree match {
case ddef: DefDef if tree.symbol.isTermMacro => defnTyper.computeMacroDefType(ddef, pt)
case ddef: DefDef if tree.symbol.isTermMacro => defnTyper.computeMacroDefType(ddef, pt) // unreached, see methodSig
case _ => defnTyper.computeType(tree.rhs, pt)
}
tree.tpt.defineType {
if (currentRun.isScala3 && !pt.isWildcard && pt != NoType && !pt.isErroneous && openMacros.isEmpty) pt
val inferOverridden = currentRun.isScala3 &&
!pt.isWildcard && pt != NoType && !pt.isErroneous &&
openMacros.isEmpty && {
context.unit.transformed.get(tree.rhs) match {
case Some(t) if t.hasAttachment[MacroExpansionAttachment] =>
val xp = macroExpandee(t)
xp.symbol == null || isBlackbox(xp.symbol)
case _ => true
}
}
if (inferOverridden) pt
else dropIllegalStarTypes(widenIfNecessary(tree.symbol, rhsTpe, pt))
}.setPos(tree.pos.focus)
tree.tpt.tpe
Expand Down
4 changes: 4 additions & 0 deletions test/files/neg/t12647.check
@@ -0,0 +1,4 @@
Test_3.scala:6: error: value value is not a member of Result
println(resolver.resolve.value)
^
1 error
13 changes: 13 additions & 0 deletions test/files/neg/t12647/Macro_1.scala
@@ -0,0 +1,13 @@

// scalac: -Xsource:3

import scala.reflect.macros.blackbox.Context

trait Result

object Macros {
def impl(c: Context) = {
import c.universe._
q"""new Result { def value = "Was this the answer you sought?" }"""
}
}
13 changes: 13 additions & 0 deletions test/files/neg/t12647/Resolve_2.scala
@@ -0,0 +1,13 @@

// scalac: -Xsource:3

import language.experimental.macros

trait Resolver {
def resolve: Result = ???
}

class ValueResolver extends Resolver {
override def resolve = valueResult
def valueResult: Result = macro Macros.impl
}
7 changes: 7 additions & 0 deletions test/files/neg/t12647/Test_3.scala
@@ -0,0 +1,7 @@

// scalac: -Xsource:3

object Test extends App {
val resolver = new ValueResolver
println(resolver.resolve.value)
}
13 changes: 13 additions & 0 deletions test/files/pos/t12647/Macro_1.scala
@@ -0,0 +1,13 @@

// scalac: -Xsource:3

import scala.reflect.macros.whitebox.Context

trait Result

object Macros {
def impl(c: Context) = {
import c.universe._
q"""new Result { def value = "Was this the answer you sought?" }"""
}
}
13 changes: 13 additions & 0 deletions test/files/pos/t12647/Resolve_2.scala
@@ -0,0 +1,13 @@

// scalac: -Xsource:3

import language.experimental.macros

trait Resolver {
def resolve: Result = ???
}

class ValueResolver extends Resolver {
override def resolve = valueResult
def valueResult: Result = macro Macros.impl
}
7 changes: 7 additions & 0 deletions test/files/pos/t12647/Test_3.scala
@@ -0,0 +1,7 @@

// scalac: -Xsource:3

object Test extends App {
val resolver = new ValueResolver
println(resolver.resolve.value)
}
11 changes: 11 additions & 0 deletions test/files/pos/t12647b/Macro_1.scala
@@ -0,0 +1,11 @@

import scala.reflect.macros.whitebox.Context

trait Result

object Macros {
def impl(c: Context): c.Tree = {
import c.universe._
q"""new Result { def value = "Was this the answer you sought?" }"""
}
}
11 changes: 11 additions & 0 deletions test/files/pos/t12647b/Resolve_2.scala
@@ -0,0 +1,11 @@

import language.experimental.macros

abstract class Resolver {
def resolve: Result = ???
}

class ValueResolver extends Resolver {
override def resolve = valueResult
def valueResult: Result = macro Macros.impl
}
5 changes: 5 additions & 0 deletions test/files/pos/t12647b/Test_3.scala
@@ -0,0 +1,5 @@

object Test extends App {
val resolver = new ValueResolver
println(resolver.resolve.value)
}

0 comments on commit 8fa1e7c

Please sign in to comment.