Skip to content

Commit

Permalink
SI-6323 outlaws free types from TypeTag
Browse files Browse the repository at this point in the history
Free types are no longer acceptable in normal type tags.
Like type parameters or abstract type members they don't map on any real type,
therefore I think this is a justified change.

The main reason for doing is this is to prohibit people from using `typeOf`
on local classes. Sure, the guard introduced in the previous commit will raise
runtime errors about that, but this commit provides static checking.

Those especially persistent might use `absTypeOf` and then try to play around
with the weak type it returns, but that's advanced usage scenario, and I don't
worry much about it.

Bottom line: `typeOf` should just work.
Things that work with additional effort should be explicitly marked as such.
  • Loading branch information
xeno-by committed Sep 14, 2012
1 parent 0eabb63 commit 524c90d
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/compiler/scala/reflect/reify/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ trait Errors {
throw new ReificationError(defaultErrorPosition, msg)
}

def CannotReifyTypeTagHavingUnresolvedTypeParameters(tpe: Type) = {
val msg = "cannot reify TypeTag having unresolved type parameter %s".format(tpe)
def CannotReifyWeakType(details: Any) = {
val msg = "cannot create a TypeTag" + details
throw new ReificationError(defaultErrorPosition, msg)
}

Expand Down
8 changes: 5 additions & 3 deletions src/compiler/scala/reflect/reify/States.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ trait States {
def reificationIsConcrete_=(value: Boolean): Unit = {
_reificationIsConcrete = value
if (!value && concrete) {
assert(current.isInstanceOf[Type], current)
val offender = current.asInstanceOf[Type]
CannotReifyTypeTagHavingUnresolvedTypeParameters(offender)
current match {
case tpe: Type => CannotReifyWeakType(s" having unresolved type parameter $tpe")
case sym: Symbol => CannotReifyWeakType(s" referring to local ${sym.kindString} ${sym.fullName}")
case _ => CannotReifyWeakType("")
}
}
}
var reifyStack = reifee :: Nil
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ trait GenSymbols {
def reifyFreeType(binding: Tree): Tree =
reifyIntoSymtab(binding.symbol) { sym =>
if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString))
state.reificationIsConcrete = false
val name = newTermName(nme.REIFY_FREE_PREFIX + sym.name)
Reification(name, binding, mirrorBuildCall(nme.newFreeType, reify(sym.name.toString), mirrorBuildCall(nme.flagsFromBits, reify(sym.flags)), reify(origin(sym))))
}
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scala/reflect/reify/utils/SymbolTables.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ trait SymbolTables {
private[SymbolTable] val original: Option[List[Tree]] = None) {

def syms: List[Symbol] = symtab.keys.toList
def isConcrete: Boolean = symtab.values forall (sym => !FreeTypeDef.unapply(sym).isDefined)

// def aliases: Map[Symbol, List[TermName]] = aliases.distinct groupBy (_._1) mapValues (_ map (_._2))

Expand Down
9 changes: 9 additions & 0 deletions test/files/neg/t6323a.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
t6323a.scala:11: `package`.this.materializeTypeTag[Test](scala.reflect.runtime.`package`.universe) is not a valid implicit value for reflect.runtime.universe.TypeTag[Test] because:
failed to typecheck the materialized tag:
cannot create a TypeTag referring to local class Test.Test
val value = u.typeOf[Test]
^
t6323a.scala:11: error: No TypeTag available for Test
val value = u.typeOf[Test]
^
one error found
1 change: 1 addition & 0 deletions test/files/neg/t6323a.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-Xlog-implicits
2 changes: 1 addition & 1 deletion test/files/run/t6323.scala → test/files/neg/t6323a.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object Test extends App {
val thisShouldBeA = aAccessor.apply()
println(thisShouldBeA)
} catch {
case ScalaReflectionException(msg) => println(msg)
case ScalaReflectionException(msg) => println(msg)
}
}
}
File renamed without changes.
21 changes: 21 additions & 0 deletions test/files/run/t6323b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => m}
import scala.reflect.runtime.{universe => u}

object Test extends App {
locally {
try {
case class Test(a:String,b:List[Int])

val lookAtMe = m.reflect(Test("a",List(5)))
val value = u.absTypeOf[Test]
val members = value.members
val member = value.members.filter(_.name.encoded == "a")
val aAccessor = lookAtMe.reflectMethod(member.head.asMethod)
val thisShouldBeA = aAccessor.apply()
println(thisShouldBeA)
} catch {
case ScalaReflectionException(msg) => println(msg)
}
}
}

0 comments on commit 524c90d

Please sign in to comment.