diff options
author | Paul Phillips <paulp@improving.org> | 2013-05-11 13:02:54 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-05-11 13:02:54 -0700 |
commit | 24cad039b309cf3ccd79aca8f3bae398a42ab66b (patch) | |
tree | 7074df39940276bd2f93e156310a5bc4e2948508 | |
parent | b174efbcbcf241903d2dc970f950f594b8c8c5e7 (diff) | |
download | scala-24cad039b309cf3ccd79aca8f3bae398a42ab66b.tar.gz scala-24cad039b309cf3ccd79aca8f3bae398a42ab66b.tar.bz2 scala-24cad039b309cf3ccd79aca8f3bae398a42ab66b.zip |
Eliminated HKmode.
It becomes context mode "TypeConstructor".
4 files changed, 53 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 48df7cb261..e0b7f8b670 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -244,6 +244,9 @@ trait Contexts { self: Analyzer => def inSecondTry = this(SecondTry) def inSecondTry_=(value: Boolean) = this(SecondTry) = value def inReturnExpr = this(ReturnExpr) + def inTypeConstructor = this(TypeConstructor) + + def defaultModeForTyped: Mode = if (inTypeConstructor) Mode.NOmode else Mode.EXPRmode /** These messages are printed when issuing an error */ var diagnostic: List[String] = Nil @@ -361,6 +364,7 @@ trait Contexts { self: Analyzer => def withStarPatterns[T](op: => T): T = withMode(enabled = StarPatterns)(op) def withSuperInit[T](op: => T): T = withMode(enabled = SuperInit)(op) def withSecondTry[T](op: => T): T = withMode(enabled = SecondTry)(op) + def withTypeConstructor[T](op: => T): T = withMode(enabled = TypeConstructor)(op) def withReturnExpr[T](op: => T): T = { enclMethod.returnsSeen = true @@ -1364,6 +1368,9 @@ object ContextMode { /** Are we in return position? Formerly RETmode. */ final val ReturnExpr: ContextMode = 1 << 15 + /** Are we typing a type constructor? Formerly HKmode. */ + final val TypeConstructor: ContextMode = 1 << 16 + final val DefaultMode: ContextMode = MacrosEnabled private val contextModeNameMap = Map( @@ -1379,7 +1386,8 @@ object ContextMode { PatternAlternative -> "PatternAlternative", StarPatterns -> "StarPatterns", SuperInit -> "SuperInit", - SecondTry -> "SecondTry" + SecondTry -> "SecondTry", + TypeConstructor -> "TypeConstructor" ) } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 290ad76a1d..0b902318b2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -944,7 +944,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def checkSensible(pos: Position, fn: Tree, args: List[Tree]) = fn match { case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 => - def isReferenceOp = name == nme.eq || name == nme.ne + // Make sure the 'eq' or 'ne' method is the one in AnyRef. + def isReferenceOp = fn.symbol == Object_eq || fn.symbol == Object_ne def isNew(tree: Tree) = tree match { case Function(_, _) | Apply(Select(New(_), nme.CONSTRUCTOR), _) => true diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 3bcc670c89..f26b15b208 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -877,36 +877,43 @@ trait Typers extends Adaptations with Tags { } def adaptType(): Tree = { - if (mode.inFunMode) { - // todo. the commented line below makes sense for typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...)) - // because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail - // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else - // tree setType tree.tpe.normalize - tree - } else if (tree.hasSymbolField && !tree.symbol.typeParams.isEmpty && !mode.inHKMode && - !(tree.symbol.isJavaDefined && context.unit.isJava)) { // (7) - // @M When not typing a higher-kinded type ((mode & HKmode) == 0) - // or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *, - // and thus parameterized types must be applied to their type arguments - // @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't? - MissingTypeParametersError(tree) - } else if ( // (7.1) @M: check kind-arity + // @M When not typing a higher-kinded type (!context.inTypeConstructor) + // or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *, + // and thus parameterized types must be applied to their type arguments + // @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't? + def kindStarRequired = ( + tree.hasSymbolField + && !context.inTypeConstructor + && !(tree.symbol.isJavaDefined && context.unit.isJava) + ) + // @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!! + // (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!) // @M: removed check for tree.hasSymbolField and replace tree.symbol by tree.tpe.symbol // (TypeTree's must also be checked here, and they don't directly have a symbol) - mode.inHKMode && - // @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!! - // (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!) - !sameLength(tree.tpe.typeParams, pt.typeParams) && - !(tree.tpe.typeSymbol == AnyClass || - tree.tpe.typeSymbol == NothingClass || - 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). + def kindArityMismatch = ( + context.inTypeConstructor + && !sameLength(tree.tpe.typeParams, pt.typeParams) + ) + // 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). + def kindArityMismatchOk = tree.tpe.typeSymbol match { + case NothingClass | AnyClass => true + case _ => pt == WildcardType + } + + // todo. It would make sense when mode.inFunMode to instead use + // tree setType tree.tpe.normalize + // when typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...)) + // because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail + // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else + if (mode.inFunMode) + tree + else if (kindStarRequired && tree.symbol.typeParams.nonEmpty) // (7) + MissingTypeParametersError(tree) + else if (kindArityMismatch && !kindArityMismatchOk) // (7.1) @M: check kind-arity KindArityMismatchError(tree, pt) - } else tree match { // (6) + else tree match { // (6) case TypeTree() => tree case _ => TypeTree(tree.tpe) setOriginal tree } @@ -1028,7 +1035,7 @@ trait Typers extends Adaptations with Tags { } def insertApply(): Tree = { - assert(!mode.inHKMode, mode) //@M + assert(!context.inTypeConstructor, mode) //@M val adapted = adaptToName(tree, nme.apply) def stabilize0(pre: Type): Tree = stabilize(adapted, pre, EXPRmode | QUALmode, WildcardType) @@ -1212,7 +1219,7 @@ trait Typers extends Adaptations with Tags { else if (shouldInsertApply(tree)) insertApply() else if (hasUndetsInMonoMode) { // (9) - assert(!mode.inHKMode, mode) //@M + assert(!context.inTypeConstructor, context) //@M if (mode.typingExprNotFun && pt.typeSymbol == UnitClass) instantiateExpectingUnit(tree, mode) else @@ -1246,7 +1253,7 @@ trait Typers extends Adaptations with Tags { adapt(tree setType arg, mode, pt, original) case tp if mode.typingExprNotLhs && isExistentialType(tp) => adapt(tree setType tp.dealias.skolemizeExistential(context.owner, tree), mode, pt, original) - case PolyType(tparams, restpe) if mode.inNone(TAPPmode | PATTERNmode | HKmode) => // (3) + case PolyType(tparams, restpe) if mode.inNone(TAPPmode | PATTERNmode) && !context.inTypeConstructor => // (3) // assert((mode & HKmode) == 0) //@M a PolyType in HKmode represents an anonymous type function, // we're in HKmode since a higher-kinded type is expected --> hence, don't implicitly apply it to type params! // ticket #2197 triggered turning the assert into a guard @@ -5366,7 +5373,7 @@ trait Typers extends Adaptations with Tags { /** Types expression or definition `tree`. */ def typed(tree: Tree): Tree = { - val ret = typed(tree, EXPRmode, WildcardType) + val ret = typed(tree, context.defaultModeForTyped, WildcardType) ret } @@ -5381,7 +5388,7 @@ trait Typers extends Adaptations with Tags { /** Types expression `tree` with given prototype `pt`. */ def typed(tree: Tree, pt: Type): Tree = - typed(tree, EXPRmode, pt) + typed(tree, context.defaultModeForTyped, pt) def typed(tree: Tree, mode: Mode): Tree = typed(tree, mode, WildcardType) @@ -5444,10 +5451,10 @@ trait Typers extends Adaptations with Tags { /** Types a higher-kinded type tree -- pt denotes the expected kind*/ def typedHigherKindedType(tree: Tree, mode: Mode, pt: Type): Tree = if (pt.typeParams.isEmpty) typedType(tree, mode) // kind is known and it's * - else typed(tree, HKmode, pt) + else context withTypeConstructor typed(tree, NOmode, pt) def typedHigherKindedType(tree: Tree, mode: Mode): Tree = - typed(tree, HKmode, WildcardType) + context withTypeConstructor typed(tree) /** Types a type constructor tree used in a new or supertype */ def typedTypeConstructor(tree: Tree, mode: Mode): Tree = { diff --git a/src/reflect/scala/reflect/internal/Mode.scala b/src/reflect/scala/reflect/internal/Mode.scala index a15a3dcc84..37633c9302 100644 --- a/src/reflect/scala/reflect/internal/Mode.scala +++ b/src/reflect/scala/reflect/internal/Mode.scala @@ -52,12 +52,6 @@ object Mode { */ final val LHSmode: Mode = 0x400 - /** HKmode 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. - */ - final val HKmode: Mode = 0x4000 // @M: could also use POLYmode | TAPPmode - /** BYVALmode is set when we are typing an expression * that occurs in a by-value position. An expression e1 is in by-value * position within expression e2 iff it will be reduced to a value at that @@ -90,7 +84,7 @@ object Mode { (1 << 11) -> "<>", (1 << 12) -> "<>", // formerly STARmode (1 << 13) -> "<>", // formerly ALTmode - (1 << 14) -> "HKmode", + (1 << 14) -> "<>", // formerly HKmode (1 << 15) -> "BYVALmode", (1 << 16) -> "TYPEPATmode" ).map({ case (k, v) => Mode(k) -> v }) @@ -120,7 +114,6 @@ final class Mode private (val bits: Int) extends AnyVal { def inByValMode = inAll(BYVALmode) def inExprMode = inAll(EXPRmode) def inFunMode = inAll(FUNmode) - def inHKMode = inAll(HKmode) def inLhsMode = inAll(LHSmode) def inPatternMode = inAll(PATTERNmode) def inPolyMode = inAll(POLYmode) |