diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Tags.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Tags.scala | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala new file mode 100644 index 0000000000..d371f02d1d --- /dev/null +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -0,0 +1,86 @@ +package scala.tools.nsc +package typechecker + +trait Tags { + self: Analyzer => + + import global._ + import definitions._ + + trait Tag { + self: Typer => + + private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = beforeTyper { + def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree)) + wrapper(inferImplicit( + EmptyTree, + taggedTp, + /*reportAmbiguous =*/ true, + /*isView =*/ false, + /*context =*/ context, + /*saveAmbiguousDivergent =*/ true, + /*pos =*/ pos + ).tree) + } + + /** Finds in scope or materializes an ArrayTag. + * Should be used instead of ClassTag or ClassManifest every time compiler needs to create an array. + * + * @param pos Position for error reporting. Please, provide meaningful value. + * @param tp Type we're looking an ArrayTag for, e.g. resolveArrayTag(pos, IntClass.tpe) will look for ArrayTag[Int]. + * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no array tag in scope. + * If false then materialization macros are prohibited from running. + * + * @returns Tree that represents an `scala.reflect.ArrayTag` for `tp` if everything is okay. + * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. + * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members. + */ + def resolveArrayTag(pos: Position, tp: Type, allowMaterialization: Boolean = true): Tree = { + val taggedTp = appliedType(ArrayTagClass.typeConstructor, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } + + /** Finds in scope or materializes a ClassTag. + * Should be used instead of ClassManifest every time compiler needs to persist an erasure. + * + * Once upon a time, we had an `ErasureTag` which was to `ClassTag` the same that `TypeTag` is for `ConcreteTypeTag`. + * However we found out that we don't really need this concept, so it got removed. + * + * @param pos Position for error reporting. Please, provide meaningful value. + * @param tp Type we're looking a ClassTag for, e.g. resolveClassTag(pos, IntClass.tpe) will look for ClassTag[Int]. + * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no class tag in scope. + * If false then materialization macros are prohibited from running. + * + * @returns Tree that represents an `scala.reflect.ClassTag` for `tp` if everything is okay. + * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members. + * EmptyTree if `allowMaterialization` is false, and there is no class tag in scope. + */ + def resolveClassTag(pos: Position, tp: Type, allowMaterialization: Boolean = true): Tree = { + val taggedTp = appliedType(ClassTagClass.typeConstructor, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } + + /** Finds in scope or materializes a TypeTag (if `concrete` is false) or a ConcreteTypeTag (if `concrete` is true). + * + * @param pos Position for error reporting. Please, provide meaningful value. + * @param pre Prefix that represents a universe this type tag will be bound to. + * If `pre` is set to `NoType`, then any type tag in scope will do, regardless of its affiliation. + * If `pre` is set to `NoType`, and tag resolution involves materialization, then `mkBasisPrefix` will be used. + * @param tp Type we're looking a TypeTag for, e.g. resolveTypeTag(pos, reflectBasisPrefix, IntClass.tpe, false) will look for scala.reflect.basis.TypeTag[Int]. + * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members. + * If false then the function will always succeed (abstract types will be reified as free types). + * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no type tag in scope. + * If false then materialization macros are prohibited from running. + * + * @returns Tree that represents a `scala.reflect.TypeTag` for `tp` if everything is okay. + * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. + * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. + */ + def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = { + val tagSym = if (concrete) ConcreteTypeTagClass else TypeTagClass + val tagTp = if (pre == NoType) TypeRef(BaseUniverseClass.asTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) + val taggedTp = appliedType(tagTp, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } + } +}
\ No newline at end of file |