diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-04-16 11:23:30 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-04-16 11:23:30 +0000 |
commit | 24eb581d805653215fce5f931f78789e31924800 (patch) | |
tree | 3c0690df90110449a36a10461cae0260fca7ca74 /src/compiler/scala/tools | |
parent | 3d9d369b7147f3933cce9932d2914f68d39418c3 (diff) | |
download | scala-24eb581d805653215fce5f931f78789e31924800.tar.gz scala-24eb581d805653215fce5f931f78789e31924800.tar.bz2 scala-24eb581d805653215fce5f931f78789e31924800.zip |
implementing Martin's suggestions for tcpoly
- prefixString in SingleType suppresses scala.Predef prefixes
- (sym.isPredefModule) better handling of double defs of `_' in type
- params (now in enterInScope in Namers) introduced HKmode to indicate
- we're typing a higher-kinded type, instead of reusing POLYmode |
- TAPPmode
- Typers.typedTypeConstructor does not normalize the result anymore -- now in GenICode
generatedType = toTypeKind(tpt.tpe.normalize)
Diffstat (limited to 'src/compiler/scala/tools')
5 files changed, 30 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 1cb38f79e1..0a2e024a57 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -624,7 +624,7 @@ abstract class GenICode extends SubComponent { assert(ctor.isClassConstructor, "'new' call to non-constructor: " + tree) - generatedType = toTypeKind(tpt.tpe) + generatedType = toTypeKind(tpt.tpe.normalize) // @M: because typedTypeConstructor doesn't normalize anymore assert(generatedType.isReferenceType || generatedType.isArrayType, "Non reference type cannot be instantiated: " + generatedType) diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 63c502db84..e9b62f1b99 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -209,6 +209,7 @@ trait Symbols requires SymbolTable { final def isRootPackage = isPackage && name == nme.ROOTPKG final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName + final def isPredefModule = isModule && name == nme.Predef def isDeprecated = attributes exists (attr => attr.atp.symbol == DeprecatedAttr) @@ -1120,12 +1121,7 @@ trait Symbols requires SymbolTable { * of this class. Classes are instances of a subclass. */ class TypeSymbol(initOwner: Symbol, initPos: PositionType, initName: Name) - extends Symbol(initOwner, initPos, -// @M type params with name "_" implicitly get unique name @M TODO: the name generation is a bit hacky... - if(initName.length==1 && initName(0)=='_') // faster equality test than first converting to string - newTypeName("_$" + (ids+1)) - else initName) { - override def nameString: String = if(name.startsWith("_$")) "_"+idString else super.nameString // @M: undo underscore-mangling + extends Symbol(initOwner, initPos, initName) { override def isType = true privateWithin = NoSymbol private var tyconCache: Type = null diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index c27cf02811..71c97bef15 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -670,7 +670,7 @@ trait Types requires SymbolTable { override def symbol = sym override def prefix: Type = pre override def prefixString: String = - if ((sym.isEmptyPackage || sym.isInterpreterWrapper) && !settings.debug.value) "" + if ((sym.isEmptyPackage || sym.isInterpreterWrapper || sym.isPredefModule) && !settings.debug.value) "" else pre.prefixString + sym.nameString + "." } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index fb3e7931cc..4bbd881cb5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -126,7 +126,8 @@ trait Namers requires Analyzer { if ((prev ne null) && prev.owner == context.scope && (!prev.sym.isSourceMethod || nme.isSetterName(sym.name) || - sym.owner.isPackageClass)) { + sym.owner.isPackageClass) && + !(sym.owner.isTypeParameter && sym.name.length==1 && sym.name(0)=='_')) { //@M: allow repeated use of `_' for higher-order type params doubleDefError(sym.pos, prev.sym) sym setInfo ErrorType } else context.scope enter sym diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e52fc84523..7534df9bbb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -123,6 +123,12 @@ trait Typers requires Analyzer { /** The mode <code>ALTmode</code> is set when we are under a pattern alternative */ val ALTmode = 0x2000 + /** The mode <code>HKmode</code> is set when we are typing a higher-kinded type + * adapt should then check kind-arity based on the prototypical type's kind arity + * type arguments should not be inferred + */ + val HKmode = 0x4000 // @M: could also use POLYmode | TAPPmode + private val stickyModes: int = EXPRmode | PATTERNmode | TYPEmode | CONSTmode | ALTmode private def funMode(mode: int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode @@ -541,8 +547,8 @@ trait Typers requires Analyzer { * unapply or unapplySeq method. * * (6) Convert all other types to TypeTree nodes. - * (7) When in TYPEmode but not FUNmode, check that types are fully parameterized - * (7.1) @M! when in POLYmode | TAPPmode, check that types have the expected kind + * (7) When in TYPEmode but not FUNmode or HKmode, check that types are fully parameterized + * (7.1) In HKmode, higher-kinded types are allowed, but they must have the expected kind-arity * (8) When in both EXPRmode and FUNmode, add apply method calls to values of object type. * (9) If there are undetermined type variables and not POLYmode, infer expression instance * Then, if tree's type is not a subtype of expected type, try the following adaptations: @@ -565,6 +571,7 @@ trait Typers requires Analyzer { if ((mode & EXPRmode) != 0 && sym == ByNameParamClass) => // (2) adapt(tree setType arg, mode, pt) case PolyType(tparams, restpe) if ((mode & (TAPPmode | PATTERNmode)) == 0) => // (3) + assert((mode & HKmode) == 0) //@M val tparams1 = cloneSymbols(tparams) val tree1 = if (tree.isType) tree else TypeApply(tree, tparams1 map (tparam => @@ -605,15 +612,19 @@ trait Typers requires Analyzer { if (tree.isType) { if ((mode & FUNmode) != 0) { tree - } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && (mode & (POLYmode | TAPPmode)) == 0) { // (7) - // @M higher-kinded types are allowed in (POLYmode | TAPPmode) -- see (7.1) + } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && (mode & HKmode) == 0) { // (7) + // @M When not typing a higher-kinded type ((mode & HKmode) == 0), types must be of kind *, + // and thus parameterised types must be applied to their type arguments errorTree(tree, tree.symbol+" takes type parameters") tree setType tree.tpe - } else if (tree.hasSymbol && ((mode & (POLYmode | TAPPmode)) == (POLYmode | TAPPmode)) && // (7.1) @M: check kind-arity (full checks are done in checkKindBounds in Infer) + } else if (tree.hasSymbol && ((mode & HKmode) != 0) && // (7.1) @M: check kind-arity tree.symbol.typeParams.length != pt.typeParams.length && - !(tree.symbol==AnyClass || tree.symbol==AllClass || pt == WildcardType )) { //@M Any and Nothing are kind-polymorphic - // WildcardType is only used when typing type arguments to an overloaded method, before the overload is resolved - // (or in the case of an error type) -- see case TypeApply in typed1 + !(tree.symbol==AnyClass || tree.symbol==AllClass || pt == WildcardType )) { + // Check that the actual kind arity (tree.symbol.typeParams.length) conforms to the expected + // kind-arity (pt.typeParams.length). Full checks are done in checkKindBounds in Infer. + // Note that we treat Any and Nothing as kind-polymorphic. + // We can't perform this check when typing type arguments to an overloaded method before the overload is resolved + // (or in the case of an error type) -- this is indicated by pt == WildcardType (see case TypeApply in typed1). errorTree(tree, tree.symbol+" takes "+reporter.countElementsAsString(tree.symbol.typeParams.length, "type parameter")+ ", expected: "+reporter.countAsString(pt.typeParams.length)) tree setType tree.tpe @@ -651,6 +662,7 @@ trait Typers requires Analyzer { ((mode & TAPPmode) == 0 || tree.tpe.typeParams.isEmpty) && member(adaptToName(tree, nme.apply), nme.apply) .filter(m => m.tpe.paramSectionCount > 0) != NoSymbol) { // (8) + assert((mode & HKmode) == 0) //@M val qual = adaptToName(tree, nme.apply) match { case id @ Ident(_) => val pre = if (id.symbol.owner.isPackageClass) id.symbol.owner.thisType @@ -665,6 +677,7 @@ trait Typers requires Analyzer { } typed(atPos(tree.pos)(Select(qual, nme.apply)), mode, pt) } else if (!context.undetparams.isEmpty && (mode & POLYmode) == 0) { // (9) + assert((mode & HKmode) == 0) //@M instantiate(tree, mode, pt) } else if (tree.tpe <:< pt) { tree @@ -2669,17 +2682,17 @@ trait Typers requires Analyzer { /** Types a higher-kinded type tree -- pt denotes the expected kind*/ def typedHigherKindedType(tree: Tree, pt: Type): Tree = if(pt.typeParams.isEmpty) typedType(tree) // kind is known and it's * - else withNoGlobalVariance{ typed(tree, POLYmode | TAPPmode, pt) } + else withNoGlobalVariance{ typed(tree, HKmode, pt) } def typedHigherKindedType(tree: Tree): Tree = - withNoGlobalVariance{ typed(tree, POLYmode | TAPPmode, WildcardType) } + withNoGlobalVariance{ typed(tree, HKmode, WildcardType) } /** Types a type constructor tree used in a new or supertype */ def typedTypeConstructor(tree: Tree): Tree = { val result = withNoGlobalVariance{ typed(tree, TYPEmode | FUNmode, WildcardType) } if (!phase.erasedTypes && result.tpe.isInstanceOf[TypeRef] && !result.tpe.prefix.isStable) error(tree.pos, result.tpe.prefix+" is not a legal prefix for a constructor") - result setType(result.tpe.normalize) // @MAT remove aliases when instantiating + result setType(result.tpe) // @M: no need to normalize here, see GenICode line 627: generatedType = toTypeKind(tpt.tpe.normalize) } def computeType(tree: Tree, pt: Type): Type = { |