diff options
author | Paul Phillips <paulp@improving.org> | 2012-04-22 05:46:50 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-04-22 06:12:23 -0700 |
commit | 8c95273b70288e4e3a547fa43f2dbdb40a71b9ea (patch) | |
tree | 214e7cb1fb5655f002a58ae8b6b3a60e53e50817 /src/compiler/scala/tools/nsc/typechecker | |
parent | 3c9c18ddccc17c2b0e62195315ba2abb72d3b761 (diff) | |
download | scala-8c95273b70288e4e3a547fa43f2dbdb40a71b9ea.tar.gz scala-8c95273b70288e4e3a547fa43f2dbdb40a71b9ea.tar.bz2 scala-8c95273b70288e4e3a547fa43f2dbdb40a71b9ea.zip |
Reflection and reification: Names and Symbols.
- Consolidating many islands of name organization. Folds NameManglers
into StdNames. Brings more of the string constants together with similar
constants. Move name manipulation methods which produce TypeNames
into object tpnme rather than nme.
- Starting on MethodSymbolApi, ClassSymbolApi, etc so we can put
sensible methods on sensible entities. This pushed into Definitions,
where I pulled a whole bunch out of the api side (or at least marked
my intention to do so -- too many tests use them to make them easy to
remove) and on the compiler side, returned something more specific than
Symbol a bunch of places.
- Added a number of conveniences to Definitions to make it easier to
get properly typed symbols.
Note: one way in which you might notice having better typed Symbols is
with Sets, which have the annoying property of inferring a type based on
what they've been constructed with and then hard failing when you test
for the presence of a more general type. So this:
val mySet = Set(a, b)
println(mySet(c))
..goes from compiling to not compiling if a and b receive more specific
types (e.g. they are MethodSymbols) and c is a Symbol or ClassSymbol or
whatever. This is easily remedied on a site-by-site basis - create
Set[Symbol](...) not Set(...) - but is an interesting and unfortunate
consequence of type inference married to invariance.
The changes to DummyMirror where things became ??? were driven by the
need to lower its tax; type "Nothing" is a lot more forgiving about changes
than is any specific symbol type.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
3 files changed, 35 insertions, 28 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 651120db4f..f8da6a462d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1121,10 +1121,10 @@ trait Implicits { } // these should be lazy, otherwise we wouldn't be able to compile scala-library with starr - private val TagSymbols = Set(ClassTagClass, TypeTagClass, ConcreteTypeTagClass) - private val TagMaterializers = Map( - ClassTagClass -> MacroInternal_materializeClassTag, - TypeTagClass -> MacroInternal_materializeTypeTag, + private val TagSymbols = Set[Symbol](ClassTagClass, TypeTagClass, ConcreteTypeTagClass) + private val TagMaterializers = Map[Symbol, MethodSymbol]( + ClassTagClass -> MacroInternal_materializeClassTag, + TypeTagClass -> MacroInternal_materializeTypeTag, ConcreteTypeTagClass -> MacroInternal_materializeConcreteTypeTag ) @@ -1140,27 +1140,34 @@ trait Implicits { failure(arg, "failed to typecheck the materialized typetag: %n%s".format(ex.msg), ex.pos) } - val prefix = (tagClass, pre) match { - // ClassTags only exist for scala.reflect.mirror, so their materializer doesn't care about prefixes - case (ClassTagClass, _) => - gen.mkAttributedRef(Reflect_mirror) setType singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror) - // [Eugene to Martin] this is the crux of the interaction between implicits and reifiers - // here we need to turn a (supposedly path-dependent) type into a tree that will be used as a prefix - // I'm not sure if I've done this right - please, review - case (_, SingleType(prePre, preSym)) => - gen.mkAttributedRef(prePre, preSym) setType pre - // necessary only to compile typetags used inside the Universe cake - case (_, ThisType(thisSym)) => - gen.mkAttributedThis(thisSym) - case _ => - // if ``pre'' is not a PDT, e.g. if someone wrote - // implicitly[scala.reflect.makro.Context#TypeTag[Int]] - // then we need to fail, because we don't know the prefix to use during type reification - return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind)) - } - + val prefix = ( + // ClassTags only exist for scala.reflect.mirror, so their materializer + // doesn't care about prefixes + if (tagClass eq ClassTagClass) ( + gen.mkAttributedRef(Reflect_mirror) + setType singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror) + ) + else pre match { + // [Eugene to Martin] this is the crux of the interaction between + // implicits and reifiers here we need to turn a (supposedly + // path-dependent) type into a tree that will be used as a prefix I'm + // not sure if I've done this right - please, review + case SingleType(prePre, preSym) => + gen.mkAttributedRef(prePre, preSym) setType pre + // necessary only to compile typetags used inside the Universe cake + case ThisType(thisSym) => + gen.mkAttributedThis(thisSym) + case _ => + // if ``pre'' is not a PDT, e.g. if someone wrote + // implicitly[scala.reflect.makro.Context#TypeTag[Int]] + // then we need to fail, because we don't know the prefix to use during type reification + return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind)) + } + ) // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros - var materializer = atPos(pos.focus)(Apply(TypeApply(Ident(TagMaterializers(tagClass)), List(TypeTree(tp))), List(prefix))) + var materializer = atPos(pos.focus)( + gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix)) + ) if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) if (context.macrosEnabled) success(materializer) else failure(materializer, "macros are disabled") @@ -1169,8 +1176,8 @@ trait Implicits { /** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest. */ private def implicitTagOrOfExpectedType(pt: Type): SearchResult = pt.dealias match { - case TypeRef(pre, sym, args) if TagSymbols(sym) => - tagOfType(pre, args.head, sym) + case TypeRef(pre, sym, arg :: Nil) if TagSymbols(sym) => + tagOfType(pre, arg, sym) case tp@TypeRef(_, sym, _) if sym.isAbstractType => implicitTagOrOfExpectedType(tp.bounds.lo) // #3977: use tp (==pt.dealias), not pt (if pt is a type alias, pt.bounds.lo == pt) case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 43cbea83ff..d327d9c397 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -134,7 +134,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT // otherwise lead to either a compiler crash or runtime failure. private lazy val isDisallowed = { import definitions._ - Set(Any_isInstanceOf, Object_isInstanceOf, Any_asInstanceOf, Object_asInstanceOf, Object_==, Object_!=, Object_##) + Set[Symbol](Any_isInstanceOf, Object_isInstanceOf, Any_asInstanceOf, Object_asInstanceOf, Object_==, Object_!=, Object_##) } override def transform(tree: Tree): Tree = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9a59d8f28a..54be9c9a87 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3322,7 +3322,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val typeParams: List[Symbol] = rawSyms map { sym => val name = sym.name match { case x: TypeName => x - case x => nme.singletonName(x) + case x => tpnme.singletonName(x) } val bound = allBounds(sym) val sowner = if (isRawParameter(sym)) context.owner else sym.owner |