Defined tpeHK in a manner consistent with tpe so it has a better
chance of being found/understood, and tried to clean up its documentation a little bit. Review by moors. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@25153 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
590fcf5179
commit
3da81185ba
|
@ -745,9 +745,11 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
|
|||
* @M you should use tpeHK for a type symbol with type parameters if
|
||||
* the kind of the type need not be *, as tpe introduces dummy arguments
|
||||
* to generate a type of kind *
|
||||
* for a term symbol, its usual type
|
||||
* for a term symbol, its usual type.
|
||||
* See the tpe/tpeHK overrides in TypeSymbol for more.
|
||||
*/
|
||||
def tpe: Type = info
|
||||
def tpeHK: Type = tpe
|
||||
|
||||
/** Get type info associated with symbol at current phase, after
|
||||
* ensuring that symbol is initialized (i.e. type is completed).
|
||||
|
@ -926,15 +928,6 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
|
|||
def typeConstructor: Type =
|
||||
abort("typeConstructor inapplicable for " + this)
|
||||
|
||||
/** @M -- tpe vs tpeHK:
|
||||
* Symbol::tpe creates a TypeRef that has dummy type arguments to get a type of kind *
|
||||
* Symbol::tpeHK creates a TypeRef without type arguments, but with type params --> higher-kinded if non-empty list of tpars
|
||||
* calling tpe may hide errors or introduce spurious ones
|
||||
* (e.g., when deriving a type from the symbol of a type argument that must be higher-kinded)
|
||||
* as far as I can tell, it only makes sense to call tpe in conjunction with a substitution that replaces the generated dummy type arguments by their actual types
|
||||
*/
|
||||
def tpeHK = if (isType) typeConstructor else tpe // @M! used in memberType
|
||||
|
||||
/** The type parameters of this symbol, without ensuring type completion.
|
||||
* assumption: if a type starts out as monomorphic, it will not acquire
|
||||
* type parameters later.
|
||||
|
@ -2016,7 +2009,8 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
|
|||
tpeCache = NoType
|
||||
val targs =
|
||||
if (phase.erasedTypes && this != ArrayClass) List()
|
||||
else unsafeTypeParams map (_.typeConstructor) //@M! use typeConstructor to generate dummy type arguments,
|
||||
else unsafeTypeParams map (_.typeConstructor)
|
||||
//@M! use typeConstructor to generate dummy type arguments,
|
||||
// sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
|
||||
// memberType should be used instead, that's why it uses tpeHK and not tpe
|
||||
tpeCache = newTypeRef(targs)
|
||||
|
@ -2025,6 +2019,22 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
|
|||
assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
|
||||
tpeCache
|
||||
}
|
||||
|
||||
/** @M -- tpe vs tpeHK:
|
||||
*
|
||||
* tpe: creates a TypeRef with dummy type arguments and kind *
|
||||
* tpeHK: creates a TypeRef with no type arguments but with type parameters
|
||||
*
|
||||
* If typeParams is nonEmpty, calling tpe may hide errors or
|
||||
* introduce spurious ones. (For example, when deriving a type from
|
||||
* the symbol of a type argument that must be higher-kinded.) As far
|
||||
* as I can tell, it only makes sense to call tpe in conjunction
|
||||
* with a substitution that replaces the generated dummy type
|
||||
* arguments by their actual types.
|
||||
*
|
||||
* TODO: the above conditions desperately need to be enforced by code.
|
||||
*/
|
||||
override def tpeHK = typeConstructor // @M! used in memberType
|
||||
|
||||
// needed for experimental code for early types as type parameters
|
||||
// def refreshType() { tpePeriod = NoPeriod }
|
||||
|
@ -2100,7 +2110,8 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
|
|||
/** If type skolem comes from an existential, the tree where it was created */
|
||||
override def unpackLocation = origin
|
||||
|
||||
override def typeParams = info.typeParams //@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
|
||||
//@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
|
||||
override def typeParams = info.typeParams
|
||||
|
||||
override def cloneSymbolImpl(owner: Symbol): Symbol =
|
||||
new TypeSkolem(owner, pos, name, origin)
|
||||
|
@ -2110,7 +2121,6 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
|
|||
else super.nameString
|
||||
}
|
||||
|
||||
|
||||
/** A class for class symbols */
|
||||
class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
|
||||
extends TypeSymbol(initOwner, initPos, initName) {
|
||||
|
|
|
@ -1839,26 +1839,36 @@ A type's typeSymbol should never be inspected directly.
|
|||
else sym.unsafeTypeParams
|
||||
|
||||
// placeholders derived from type params
|
||||
private def dummyArgs = typeParamsDirect map (_.typeConstructor) //@M must be .typeConstructor
|
||||
private def dummyArgs = {
|
||||
// @PP to @AM: this appears to me a place where
|
||||
// higher-order tparams are going off the beam.
|
||||
// if (sym.isAbstractType) { something goes wrong }
|
||||
|
||||
//@M must be .typeConstructor
|
||||
typeParamsDirect map (_.typeConstructor)
|
||||
}
|
||||
|
||||
// (!result.isEmpty) IFF isHigherKinded
|
||||
override def typeParams: List[Symbol] = if (isHigherKinded) typeParamsDirect else List()
|
||||
|
||||
// note: does not go through typeRef. There's no need to because
|
||||
// neither `pre` nor `sym` changes. And there's a performance
|
||||
// advantage to call TypeRef directly.
|
||||
override def typeConstructor = TypeRef(pre, sym, Nil)
|
||||
// note: does not go through typeRef. There's no need to because neither `pre` nor `sym` changes.
|
||||
// And there's a performance advantage to call TypeRef directly.
|
||||
|
||||
|
||||
// a reference (in a Scala program) to a type that has type parameters, but where the reference does not include type arguments
|
||||
// note that it doesn't matter whether the symbol refers to a java or scala symbol,
|
||||
// it does matter whether it occurs in java or scala code
|
||||
// typerefs w/o type params that occur in java signatures/code are considered raw types, and are represented as existential types
|
||||
// A reference (in a Scala program) to a type that has type
|
||||
// parameters, but where the reference does not include type
|
||||
// arguments. Note that it doesn't matter whether the symbol refers
|
||||
// to a java or scala symbol, it does matter whether it occurs in
|
||||
// java or scala code. TypeRefs w/o type params that occur in java
|
||||
// signatures/code are considered raw types, and are represented as
|
||||
// existential types.
|
||||
override def isHigherKinded = args.isEmpty && typeParamsDirect.nonEmpty
|
||||
|
||||
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type =
|
||||
if (isHigherKinded) {
|
||||
val substTps = formals.intersect(typeParams)
|
||||
|
||||
|
||||
if (sameLength(substTps, typeParams))
|
||||
copyTypeRef(this, pre, sym, actuals)
|
||||
else if (sameLength(formals, actuals)) // partial application (needed in infer when bunching type arguments from classes and methods together)
|
||||
|
@ -1869,12 +1879,17 @@ A type's typeSymbol should never be inspected directly.
|
|||
super.instantiateTypeParams(formals, actuals)
|
||||
|
||||
|
||||
/** @pre: sym.info.typeParams.length == typeArgs.length */
|
||||
@inline private def betaReduce: Type = {
|
||||
assert(sameLength(sym.info.typeParams, typeArgs), this)
|
||||
// isHKSubType0 introduces synthetic type params so that betaReduce can first apply sym.info to typeArgs before calling asSeenFrom
|
||||
// asSeenFrom then skips synthetic type params, which are used to reduce HO subtyping to first-order subtyping, but which can't be instantiated from the given prefix and class
|
||||
// appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner) // this crashes pos/depmet_implicit_tpbetareduce.scala
|
||||
// isHKSubType0 introduces synthetic type params so that
|
||||
// betaReduce can first apply sym.info to typeArgs before calling
|
||||
// asSeenFrom. asSeenFrom then skips synthetic type params, which
|
||||
// are used to reduce HO subtyping to first-order subtyping, but
|
||||
// which can't be instantiated from the given prefix and class.
|
||||
transform(sym.info.resultType)
|
||||
//
|
||||
// this crashes pos/depmet_implicit_tpbetareduce.scala
|
||||
// appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner)
|
||||
}
|
||||
|
||||
// @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala)
|
||||
|
@ -5075,7 +5090,7 @@ A type's typeSymbol should never be inspected directly.
|
|||
*
|
||||
* @See baseTypeSeq for a definition of sorted and upwards closed.
|
||||
*/
|
||||
private def lubList(tss: List[List[Type]], depth: Int): List[Type] =
|
||||
private def lubList(tss: List[List[Type]], depth: Int): List[Type] = {
|
||||
if (tss.tail.isEmpty) tss.head
|
||||
else if (tss exists (_.isEmpty)) List()
|
||||
else {
|
||||
|
@ -5086,6 +5101,13 @@ A type's typeSymbol should never be inspected directly.
|
|||
else
|
||||
lubList(tss map (ts => if (ts.head.typeSymbol == sym) ts.tail else ts), depth)
|
||||
}
|
||||
}
|
||||
// @PP lubLists gone bad: lubList(List(
|
||||
// List(scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq], ScalaObject, java.lang.Object, Any)
|
||||
// List(scala.collection.generic.GenericCompanion[scala.collection.mutable.Seq], ScalaObject, java.lang.Object, Any)
|
||||
// )) == (
|
||||
// List(scala.collection.generic.GenericCompanion[Seq[Any]], ScalaObject, java.lang.Object, Any)
|
||||
// )
|
||||
|
||||
private def lubBaseTypeSeq(tss: List[BaseTypeSeq], depth: Int): List[Type] =
|
||||
lubList(tss map (_.toList), depth)
|
||||
|
|
Loading…
Reference in New Issue