diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/reify/utils/Extractors.scala | 13 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Printers.scala | 3 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 4 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 116 |
4 files changed, 125 insertions, 11 deletions
diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index b7206eda0e..b60d15c1d4 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -92,11 +92,18 @@ trait Extractors { Block(List(universeAlias, mirrorAlias), wrappee) } + // if we're reifying a MethodType, we can't use it as a type argument for TypeTag ctor + // http://groups.google.com/group/scala-internals/browse_thread/thread/2d7bb85bfcdb2e2 + private def mkTarg(tpe: Type): Tree = ( + if ((tpe eq null) || !isUseableAsTypeArg(tpe)) TypeTree(AnyTpe) + else TypeTree(tpe) + ) + object ReifiedTree { def apply(universe: Tree, mirror: Tree, symtab: SymbolTable, rtree: Tree, tpe: Type, rtpe: Tree, concrete: Boolean): Tree = { val tagFactory = if (concrete) nme.TypeTag else nme.WeakTypeTag - val tagCtor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), tagFactory), nme.apply), List(TypeTree(tpe))) - val exprCtor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), nme.Expr), nme.apply), List(TypeTree(tpe))) + val tagCtor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), tagFactory), nme.apply), List(mkTarg(tpe))) + val exprCtor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), nme.Expr), nme.apply), List(mkTarg(tpe))) val tagArgs = List(Ident(nme.MIRROR_SHORT), mkCreator(tpnme.REIFY_TYPECREATOR_PREFIX, symtab, rtpe)) val unwrapped = Apply(Apply(exprCtor, List(Ident(nme.MIRROR_SHORT), mkCreator(tpnme.REIFY_TREECREATOR_PREFIX, symtab, rtree))), List(Apply(tagCtor, tagArgs))) mkWrapper(universe, mirror, unwrapped) @@ -123,7 +130,7 @@ trait Extractors { object ReifiedType { def apply(universe: Tree, mirror: Tree, symtab: SymbolTable, tpe: Type, rtpe: Tree, concrete: Boolean) = { val tagFactory = if (concrete) nme.TypeTag else nme.WeakTypeTag - val ctor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), tagFactory), nme.apply), List(TypeTree(tpe))) + val ctor = TypeApply(Select(Select(Ident(nme.UNIVERSE_SHORT), tagFactory), nme.apply), List(mkTarg(tpe))) val args = List(Ident(nme.MIRROR_SHORT), mkCreator(tpnme.REIFY_TYPECREATOR_PREFIX, symtab, rtpe)) val unwrapped = Apply(ctor, args) mkWrapper(universe, mirror, unwrapped) diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index cb8dc4b197..fb165ab50f 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -576,7 +576,8 @@ trait Printers extends api.Printers { self: SymbolTable => case _ => // do nothing }) case sym: Symbol => - if (sym.isStatic && (sym.isClass || sym.isModule)) print(sym.fullName) + if (sym == NoSymbol) print("NoSymbol") + else if (sym.isStatic && (sym.isClass || sym.isModule)) print(sym.fullName) else print(sym.name) if (printIds) print("#", sym.id) if (printKinds) print("#", sym.abbreviatedKindString) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index e420b448a6..b132b91946 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -91,8 +91,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => def module = sourceModule def thisPrefix: Type = thisType def selfType: Type = typeOfThis - def typeSignature: Type = info - def typeSignatureIn(site: Type): Type = site memberInfo this + def typeSignature: Type = { fullyInitializeSymbol(this); info } + def typeSignatureIn(site: Type): Type = { fullyInitializeSymbol(this); site memberInfo this } def toType: Type = tpe def toTypeIn(site: Type): Type = site.memberType(this) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 6b274467fc..0e8665ee84 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -66,9 +66,9 @@ import util.ThreeValues._ // a type variable // Replace occurrences of type parameters with type vars, where // inst is the instantiation and constr is a list of bounds. - case DeBruijnIndex(level, index) + case DeBruijnIndex(level, index, args) // for dependent method types: a type referring to a method parameter. - case ErasedValueType(clazz, underlying) + case ErasedValueType(tref) // only used during erasure of derived value classes. */ @@ -3623,9 +3623,20 @@ trait Types extends api.Types { self: SymbolTable => */ /** A creator for type applications */ - def appliedType(tycon: Type, args: List[Type]): Type = - if (args.isEmpty) tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??)) - else tycon match { + def appliedType(tycon: Type, args: List[Type]): Type = { + if (args.isEmpty) + return tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??)) + + /** Disabled - causes cycles in tcpoly tests. */ + if (false && isDefinitionsInitialized) { + assert(isUseableAsTypeArgs(args), { + val tapp_s = s"""$tycon[${args mkString ", "}]""" + val arg_s = args filterNot isUseableAsTypeArg map (t => t + "/" + t.getClass) mkString ", " + s"$tapp_s includes illegal type argument $arg_s" + }) + } + + tycon match { case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => copyTypeRef(tycon, pre, sym, Nil) //@M drop type args to Any/Nothing case TypeRef(pre, sym, _) => copyTypeRef(tycon, pre, sym, args) case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args) @@ -3639,6 +3650,7 @@ trait Types extends api.Types { self: SymbolTable => case WildcardType => tycon // needed for neg/t0226 case _ => abort(debugString(tycon)) } + } /** Very convenient. */ def appliedType(tyconSym: Symbol, args: Type*): Type = @@ -5732,6 +5744,100 @@ trait Types extends api.Types { self: SymbolTable => case _ => false } + /** This is defined and named as it is because the goal is to exclude source + * level types which are not value types (e.g. MethodType) without excluding + * necessary internal types such as WildcardType. There are also non-value + * types which can be used as type arguments (e.g. type constructors.) + */ + def isUseableAsTypeArg(tp: Type) = ( + isInternalTypeUsedAsTypeArg(tp) // the subset of internal types which can be type args + || isHKTypeRef(tp) // not a value type, but ok as a type arg + || isValueElseNonValue(tp) // otherwise only value types + ) + + private def isHKTypeRef(tp: Type) = tp match { + case TypeRef(_, sym, Nil) => tp.isHigherKinded + case _ => false + } + @tailrec final def isUseableAsTypeArgs(tps: List[Type]): Boolean = tps match { + case Nil => true + case x :: xs => isUseableAsTypeArg(x) && isUseableAsTypeArgs(xs) + } + + /** The "third way", types which are neither value types nor + * non-value types as defined in the SLS, further divided into + * types which are used internally in type applications and + * types which are not. + */ + private def isInternalTypeNotUsedAsTypeArg(tp: Type): Boolean = tp match { + case AntiPolyType(pre, targs) => true + case ClassInfoType(parents, defs, clazz) => true + case DeBruijnIndex(level, index, args) => true + case ErasedValueType(tref) => true + case NoPrefix => true + case NoType => true + case SuperType(thistpe, supertpe) => true + case TypeBounds(lo, hi) => true + case _ => false + } + private def isInternalTypeUsedAsTypeArg(tp: Type): Boolean = tp match { + case WildcardType => true + case BoundedWildcardType(_) => true + case ErrorType => true + case _: TypeVar => true + case _ => false + } + private def isAlwaysValueType(tp: Type) = tp match { + case RefinedType(_, _) => true + case ExistentialType(_, _) => true + case ConstantType(_) => true + case _ => false + } + private def isAlwaysNonValueType(tp: Type) = tp match { + case OverloadedType(_, _) => true + case NullaryMethodType(_) => true + case MethodType(_, _) => true + case PolyType(_, MethodType(_, _)) => true + case _ => false + } + /** Should be called only with types for which a clear true/false answer + * can be given: true == value type, false == non-value type. Otherwise, + * an exception is thrown. + */ + private def isValueElseNonValue(tp: Type): Boolean = tp match { + case tp if isAlwaysValueType(tp) => true + case tp if isAlwaysNonValueType(tp) => false + case AnnotatedType(_, underlying, _) => isValueElseNonValue(underlying) + case SingleType(_, sym) => sym.isValue // excludes packages and statics + case TypeRef(_, _, _) if tp.isHigherKinded => false // excludes type constructors + case ThisType(sym) => !sym.isPackageClass // excludes packages + case TypeRef(_, sym, _) => !sym.isPackageClass // excludes packages + case PolyType(_, _) => true // poly-methods excluded earlier + case tp => sys.error("isValueElseNonValue called with third-way type " + tp) + } + + /** SLS 3.2, Value Types + * Is the given type definitely a value type? A true result means + * it verifiably is, but a false result does not mean it is not, + * only that it cannot be assured. To avoid false positives, this + * defaults to false, but since Type is not sealed, one should take + * a false answer with a grain of salt. This method may be primarily + * useful as documentation; it is likely that !isNonValueType(tp) + * will serve better than isValueType(tp). + */ + def isValueType(tp: Type) = isValueElseNonValue(tp) + + /** SLS 3.3, Non-Value Types + * Is the given type definitely a non-value type, as defined in SLS 3.3? + * The specification-enumerated non-value types are method types, polymorphic + * method types, and type constructors. Supplements to the specified set of + * non-value types include: types which wrap non-value symbols (packages + * abd statics), overloaded types. Varargs and by-name types T* and (=>T) are + * not designated non-value types because there is code which depends on using + * them as type arguments, but their precise status is unclear. + */ + def isNonValueType(tp: Type) = !isValueElseNonValue(tp) + def isNonRefinementClassType(tpe: Type) = tpe match { case SingleType(_, sym) => sym.isModuleClass case TypeRef(_, sym, _) => sym.isClass && !sym.isRefinementClass |