diff options
15 files changed, 239 insertions, 101 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index 56b9c7011c..202d5d3f82 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -212,8 +212,7 @@ trait TypeStrings { } private def tparamString[T: ru.TypeTag] : String = { - // [Eugene++ to Paul] needs review!! - def typeArguments: List[ru.Type] = ru.typeOf[T].typeArguments + def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil } // [Eugene++] todo. need to use not the `rootMirror`, but a mirror with the REPL's classloader // how do I get to it? acquiring context classloader seems unreliable because of multithreading def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => ru.rootMirror.runtimeClass(targ)) diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 7bd5f4caeb..bd2808d049 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -70,11 +70,8 @@ trait MethodSynthesis { // [Eugene++->Martin] now this compiles, will soon check it out def newMethodType[F](owner: Symbol)(implicit t: TT[F]): Type = { val fnSymbol = compilerSymbolFromTag(t) - assert(fnSymbol isSubClass FunctionClass(t.tpe.typeArguments.size - 1), (owner, t)) - // [Eugene++ to Paul] needs review!! - // val symbols = m.typeArguments map (m => manifestToSymbol(m)) - // val formals = symbols.init map (_.typeConstructor) val formals = compilerTypeFromTag(t).typeArguments + assert(fnSymbol isSubClass FunctionClass(formals.size - 1), (owner, t)) val params = owner newSyntheticValueParams formals MethodType(params, formals.last) } diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 7ca1d9c7c6..cd9044c934 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -43,23 +43,6 @@ trait Symbols extends base.Symbols { self: Universe => */ def hasAnnotation(sym: Symbol): Boolean - /** ... - */ - def orElse(alt: => Symbol): Symbol - - /** ... - */ - def filter(cond: Symbol => Boolean): Symbol - - /** If this is a NoSymbol, returns NoSymbol, otherwise - * returns the result of applying `f` to this symbol. - */ - def map(f: Symbol => Symbol): Symbol - - /** ... - */ - def suchThat(cond: Symbol => Boolean): Symbol - /** * Set when symbol has a modifier of the form private[X], NoSymbol otherwise. * @@ -93,15 +76,17 @@ trait Symbols extends base.Symbols { self: Universe => */ def companionSymbol: Symbol - /** If this symbol is a package class, this symbol; otherwise the next enclosing - * package class, or `NoSymbol` if none exists. + /** The type signature of this symbol seen as a member of given type `site`. */ - def enclosingPackageClass: Symbol + def typeSignatureIn(site: Type): Type - /** If this symbol is a top-level class, this symbol; otherwise the next enclosing - * top-level class, or `NoSymbol` if none exists. + /** The type signature of this symbol. + * Note if the symbol is a member of a class, one almost always is interested + * in `typeSignatureIn` with a site type instead. */ - def enclosingTopLevelClass: Symbol + def typeSignature: Type + + /******************* tests *******************/ /** Does this symbol represent the definition of a package? * If yes, `isTerm` is also guaranteed to be true. @@ -136,15 +121,24 @@ trait Symbols extends base.Symbols { self: Universe => */ def isStatic: Boolean - /** The type signature of this symbol seen as a member of given type `site`. + /******************* helpers *******************/ + + /** ... */ - def typeSignatureIn(site: Type): Type + def orElse(alt: => Symbol): Symbol - /** The type signature of this symbol. - * Note if the symbol is a member of a class, one almost always is interested - * in `typeSignatureIn` with a site type instead. + /** ... */ - def typeSignature: Type + def filter(cond: Symbol => Boolean): Symbol + + /** If this is a NoSymbol, returns NoSymbol, otherwise + * returns the result of applying `f` to this symbol. + */ + def map(f: Symbol => Symbol): Symbol + + /** ... + */ + def suchThat(cond: Symbol => Boolean): Symbol /** The string discriminator of this symbol; useful for debugging */ def kind: String @@ -263,10 +257,33 @@ trait Symbols extends base.Symbols { self: Universe => } /** The API of method symbols */ - type MethodSymbolApi = MethodSymbolBase + trait MethodSymbolApi extends TermSymbolApi with MethodSymbolBase { this: MethodSymbol => + /** For a polymorphic method, its type parameters, the empty list for all other methods */ + def typeParams: List[Symbol] + + /** The first parameter list of the method. + * + * For a nullary method, returns the empty list. + * For a method with an empty parameter list, returns the empty list. + * To distinguish between those, use `allParams`. + */ + def params: List[Symbol] + + /** All parameter lists of the method. + * + * Can be used to distinguish nullary methods and methods with empty parameter lists. + * For a nullary method, returns the empty list (i.e. `List()`). + * For a method with an empty parameter list, returns a list that contains the empty list (i.e. `List(List())`). + */ + def allParams: List[List[Symbol]] + + /** The result type of the method */ + def resultType: Type + } /** The API of module symbols */ - type ModuleSymbolApi = ModuleSymbolBase + trait ModuleSymbolApi extends TermSymbolApi with ModuleSymbolBase { this: ModuleSymbol => + } /** The API of class symbols */ trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol => diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala index 33248fcbee..199cf9b9e5 100644 --- a/src/reflect/scala/reflect/api/Types.scala +++ b/src/reflect/scala/reflect/api/Types.scala @@ -45,45 +45,14 @@ trait Types extends base.Types { self: Universe => */ def members: MemberScope - /** Substitute symbols in `to` for corresponding occurrences of references to - * symbols `from` in this type. - */ - def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type - - /** Substitute types in `to` for corresponding occurrences of references to - * symbols `from` in this type. - */ - def substituteTypes(from: List[Symbol], to: List[Type]): Type - - /** If this is a parameterized types, the type arguments. - * Otherwise the empty list - */ - def typeArguments: List[Type] - - /** For a (potentially wrapped) poly type, its type parameters, - * the empty list for all other types */ - def typeParams: List[Symbol] - - /** For a (nullary) method or poly type, its direct result type, - * the type itself for all other types. */ - def resultType: Type - /** Is this type a type constructor that is missing its type arguments? */ - def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no? + def takesTypeArgs: Boolean /** Returns the corresponding type constructor (e.g. List for List[T] or List[String]) */ def typeConstructor: Type - /** Does this type refer to spliceable types or is a spliceable type? - */ - def isConcrete: Boolean - - /** Is this type an abstract type that needs to be resolved? - */ - def isSpliceable: Boolean - /** * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. * Functions on types are also implemented as PolyTypes. @@ -92,7 +61,7 @@ trait Types extends base.Types { self: Universe => * TypeRef(pre, <List>, List()) is replaced by * PolyType(X, TypeRef(pre, <List>, List(X))) */ - def normalize: Type // !!! Alternative name? "normalize" is used to mean too many things. + def normalize: Type /** Does this type conform to given type argument `that`? */ def <:< (that: Type): Boolean @@ -104,7 +73,7 @@ trait Types extends base.Types { self: Universe => * in reverse linearization order, starting with the class itself and ending * in class Any. */ - def baseClasses: List[Symbol] // !!! Alternative name, perhaps linearization? + def baseClasses: List[Symbol] /** The least type instance of given class which is a supertype * of this type. Example: @@ -134,36 +103,7 @@ trait Types extends base.Types { self: Universe => /** The erased type corresponding to this type after * all transformations from Scala to Java have been performed. */ - def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased") - // why not name it "erasure"? - - /** Apply `f` to each part of this type, returning - * a new type. children get mapped before their parents */ - def map(f: Type => Type): Type - - /** Apply `f` to each part of this type, for side effects only */ - def foreach(f: Type => Unit) - - /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, - * or None if none exists. - */ - def find(p: Type => Boolean): Option[Type] - - /** Is there part of this type which satisfies predicate `p`? */ - def exists(p: Type => Boolean): Boolean - - /** Does this type contain a reference to given symbol? */ - def contains(sym: Symbol): Boolean - - /** If this is a compound type, the list of its parent types; - * otherwise the empty list - */ - def parents: List[Type] - - /** If this is a singleton type, returns the type underlying it; - * otherwise returns this type itself. - */ - def underlying: Type + def erasure: Type /** If this is a singleton type, widen it to its nearest underlying non-singleton * base type by applying one or more `underlying` dereferences. @@ -186,6 +126,36 @@ trait Types extends base.Types { self: Universe => */ def narrow: Type + /******************* helpers *******************/ + + /** Substitute symbols in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type + + /** Substitute types in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteTypes(from: List[Symbol], to: List[Type]): Type + + /** Apply `f` to each part of this type, returning + * a new type. children get mapped before their parents */ + def map(f: Type => Type): Type + + /** Apply `f` to each part of this type, for side effects only */ + def foreach(f: Type => Unit) + + /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, + * or None if none exists. + */ + def find(p: Type => Boolean): Option[Type] + + /** Is there part of this type which satisfies predicate `p`? */ + def exists(p: Type => Boolean): Boolean + + /** Does this type contain a reference to given symbol? */ + def contains(sym: Symbol): Boolean + /** The string discriminator of this type; useful for debugging */ def kind: String } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 8cf20ba062..68144da2d7 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2486,6 +2486,29 @@ trait Symbols extends api.Symbols { self: SymbolTable => mtpeResult = res res } + + override def allParams: List[List[Symbol]] = paramss + + override def params: List[Symbol] = { + def loop(tpe: Type): List[Symbol] = + tpe match { + case NullaryMethodType(_) => Nil + case MethodType(params, _) => params + case PolyType(_, tpe) => loop(tpe) + } + loop(info) + } + + override def resultType: Type = { + def loop(tpe: Type): Type = + tpe match { + case NullaryMethodType(ret) => loop(ret) + case MethodType(_, ret) => loop(ret) + case PolyType(_, tpe) => loop(tpe) + case tpe => tpe + } + loop(info) + } } implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol]) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 1386cca42f..442a91774d 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -323,6 +323,7 @@ trait Types extends api.Types { self: SymbolTable => /** Is this type higher-kinded, i.e., is it a type constructor @M */ def isHigherKinded: Boolean = false + def takesTypeArgs: Boolean = this.isHigherKinded /** Does this type denote a stable reference (i.e. singleton type)? */ def isStable: Boolean = false diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 6a3501b1dd..525673fe6d 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -110,6 +110,9 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol { override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) } + override def allParams: List[List[Symbol]] = synchronized { super.allParams } + override def params: List[Symbol] = synchronized { super.params } + override def resultType: Type = synchronized { super.resultType } } trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol { diff --git a/test/files/run/reflection-methodsymbol-allparams.check b/test/files/run/reflection-methodsymbol-allparams.check new file mode 100644 index 0000000000..11f349d52b --- /dev/null +++ b/test/files/run/reflection-methodsymbol-allparams.check @@ -0,0 +1,8 @@ +List()
+List(List())
+List(List(value x))
+List(List(value x), List(value y))
+List()
+List(List())
+List(List(value x))
+List(List(value x), List(value y))
diff --git a/test/files/run/reflection-methodsymbol-allparams.scala b/test/files/run/reflection-methodsymbol-allparams.scala new file mode 100644 index 0000000000..cfd14f56a5 --- /dev/null +++ b/test/files/run/reflection-methodsymbol-allparams.scala @@ -0,0 +1,24 @@ +import scala.reflect.runtime.universe._ + +class C { + def x1: Int = ??? + def x2(): Int = ??? + def x3(x: Int): Int = ??? + def x4(x: Int)(y: Int): Int = ??? + + def y1[T]: Int = ??? + def y2[T](): Int = ??? + def y3[T](x: Int): Int = ??? + def y4[T](x: Int)(y: Int): Int = ??? +} + +object Test extends App { + println(typeOf[C].member(newTermName("x1")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("x2")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("x3")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("x4")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("y1")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("y2")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("y3")).asMethodSymbol.allParams) + println(typeOf[C].member(newTermName("y4")).asMethodSymbol.allParams) +}
\ No newline at end of file diff --git a/test/files/run/reflection-methodsymbol-params.check b/test/files/run/reflection-methodsymbol-params.check new file mode 100644 index 0000000000..899ae15a0c --- /dev/null +++ b/test/files/run/reflection-methodsymbol-params.check @@ -0,0 +1,8 @@ +List()
+List()
+List(value x)
+List(value x)
+List()
+List()
+List(value x)
+List(value x)
diff --git a/test/files/run/reflection-methodsymbol-params.scala b/test/files/run/reflection-methodsymbol-params.scala new file mode 100644 index 0000000000..654a16b59d --- /dev/null +++ b/test/files/run/reflection-methodsymbol-params.scala @@ -0,0 +1,24 @@ +import scala.reflect.runtime.universe._ + +class C { + def x1: Int = ??? + def x2(): Int = ??? + def x3(x: Int): Int = ??? + def x4(x: Int)(y: Int): Int = ??? + + def y1[T]: Int = ??? + def y2[T](): Int = ??? + def y3[T](x: Int): Int = ??? + def y4[T](x: Int)(y: Int): Int = ??? +} + +object Test extends App { + println(typeOf[C].member(newTermName("x1")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("x2")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("x3")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("x4")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("y1")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("y2")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("y3")).asMethodSymbol.params) + println(typeOf[C].member(newTermName("y4")).asMethodSymbol.params) +}
\ No newline at end of file diff --git a/test/files/run/reflection-methodsymbol-resulttype.check b/test/files/run/reflection-methodsymbol-resulttype.check new file mode 100644 index 0000000000..0f30d1beaf --- /dev/null +++ b/test/files/run/reflection-methodsymbol-resulttype.check @@ -0,0 +1,8 @@ +Int
+Int
+Int
+Int
+Int
+Int
+Int
+Int
diff --git a/test/files/run/reflection-methodsymbol-resulttype.scala b/test/files/run/reflection-methodsymbol-resulttype.scala new file mode 100644 index 0000000000..7a9f66dda8 --- /dev/null +++ b/test/files/run/reflection-methodsymbol-resulttype.scala @@ -0,0 +1,24 @@ +import scala.reflect.runtime.universe._ + +class C { + def x1: Int = ??? + def x2(): Int = ??? + def x3(x: Int): Int = ??? + def x4(x: Int)(y: Int): Int = ??? + + def y1[T]: Int = ??? + def y2[T](): Int = ??? + def y3[T](x: Int): Int = ??? + def y4[T](x: Int)(y: Int): Int = ??? +} + +object Test extends App { + println(typeOf[C].member(newTermName("x1")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("x2")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("x3")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("x4")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("y1")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("y2")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("y3")).asMethodSymbol.resultType) + println(typeOf[C].member(newTermName("y4")).asMethodSymbol.resultType) +}
\ No newline at end of file diff --git a/test/files/run/reflection-methodsymbol-typeparams.check b/test/files/run/reflection-methodsymbol-typeparams.check new file mode 100644 index 0000000000..c888e09a17 --- /dev/null +++ b/test/files/run/reflection-methodsymbol-typeparams.check @@ -0,0 +1,8 @@ +List()
+List()
+List()
+List()
+List(type T)
+List(type T)
+List(type T)
+List(type T)
diff --git a/test/files/run/reflection-methodsymbol-typeparams.scala b/test/files/run/reflection-methodsymbol-typeparams.scala new file mode 100644 index 0000000000..28f1c8973d --- /dev/null +++ b/test/files/run/reflection-methodsymbol-typeparams.scala @@ -0,0 +1,24 @@ +import scala.reflect.runtime.universe._ + +class C { + def x1: Int = ??? + def x2(): Int = ??? + def x3(x: Int): Int = ??? + def x4(x: Int)(y: Int): Int = ??? + + def y1[T]: Int = ??? + def y2[T](): Int = ??? + def y3[T](x: Int): Int = ??? + def y4[T](x: Int)(y: Int): Int = ??? +} + +object Test extends App { + println(typeOf[C].member(newTermName("x1")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("x2")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("x3")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("x4")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("y1")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("y2")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("y3")).asMethodSymbol.typeParams) + println(typeOf[C].member(newTermName("y4")).asMethodSymbol.typeParams) +}
\ No newline at end of file |