diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-12-03 23:47:23 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-12-03 23:47:23 -0800 |
commit | 2d87057cde5fa734a0e0935be74a315479469a90 (patch) | |
tree | 567826132248059fe1575a6930443d9444e3c154 | |
parent | 6c63ab153651f7946ece5740d52e0f2b701e349d (diff) | |
parent | d0aaa86a9fe20e00f0cfa4fd1154126579933fb7 (diff) | |
download | scala-2d87057cde5fa734a0e0935be74a315479469a90.tar.gz scala-2d87057cde5fa734a0e0935be74a315479469a90.tar.bz2 scala-2d87057cde5fa734a0e0935be74a315479469a90.zip |
Merge pull request #3212 from retronym/ticket/8023
SI-8023 Fix symbol-completion-order bug of type var patterns
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 28 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Kinds.scala | 2 | ||||
-rw-r--r-- | test/files/pos/t8023.scala | 22 | ||||
-rw-r--r-- | test/files/pos/t8023b.scala | 2 |
4 files changed, 42 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6d799b0098..c947fba37e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3835,7 +3835,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // as we don't know which alternative to choose... here we do map2Conserve(args, tparams) { //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyTpe)) + (arg, tparam) => typedHigherKindedType(arg, mode, Kind.FromParams(tparam.typeParams)) } } else // @M: there's probably something wrong when args.length != tparams.length... (triggered by bug #320) // Martin, I'm using fake trees, because, if you use args or arg.map(typedType), @@ -4879,14 +4879,19 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (sameLength(tparams, args)) { // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer) - val args1 = - if (!isComplete) - args mapConserve (typedHigherKindedType(_, mode)) - // if symbol hasn't been fully loaded, can't check kind-arity - else map2Conserve(args, tparams) { (arg, tparam) => - //@M! the polytype denotes the expected kind - typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyTpe)) + val args1 = map2Conserve(args, tparams) { (arg, tparam) => + def ptParams = Kind.FromParams(tparam.typeParams) + + // if symbol hasn't been fully loaded, can't check kind-arity except when we're in a pattern, + // where we can (we can't take part in F-Bounds) and must (SI-8023) + val pt = if (mode.typingPatternOrTypePat) { + tparam.initialize; ptParams } + else if (isComplete) ptParams + else Kind.Wildcard + + typedHigherKindedType(arg, mode, pt) + } val argtypes = args1 map (_.tpe) foreach2(args, tparams) { (arg, tparam) => @@ -5072,8 +5077,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds? val args1 = if (sameLength(args, tparams)) map2Conserve(args, tparams) { - //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, mode, GenPolyType(tparam.typeParams, AnyTpe)) + (arg, tparam) => typedHigherKindedType(arg, mode, Kind.FromParams(tparam.typeParams)) } else { //@M this branch is correctly hit for an overloaded polymorphic type. It also has to handle erroneous cases. @@ -5443,9 +5447,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper /** Types a (fully parameterized) type tree */ def typedType(tree: Tree): Tree = typedType(tree, NOmode) - /** Types a higher-kinded type tree -- pt denotes the expected kind*/ + /** Types a higher-kinded type tree -- pt denotes the expected kind and must be one of `Kind.WildCard` and `Kind.FromParams` */ def typedHigherKindedType(tree: Tree, mode: Mode, pt: Type): Tree = - if (pt.typeParams.isEmpty) typedType(tree, mode) // kind is known and it's * + if (pt != Kind.Wildcard && pt.typeParams.isEmpty) typedType(tree, mode) // kind is known and it's * else context withinTypeConstructorAllowed typed(tree, NOmode, pt) def typedHigherKindedType(tree: Tree, mode: Mode): Tree = diff --git a/src/reflect/scala/reflect/internal/Kinds.scala b/src/reflect/scala/reflect/internal/Kinds.scala index d48a6c6322..8ae201f045 100644 --- a/src/reflect/scala/reflect/internal/Kinds.scala +++ b/src/reflect/scala/reflect/internal/Kinds.scala @@ -326,6 +326,8 @@ trait Kinds { private[internal] object StringState { def empty: StringState = StringState(Seq()) } + def FromParams(tparams: List[Symbol]): Type = GenPolyType(tparams, AnyTpe) + def Wildcard: Type = WildcardType } class ProperTypeKind(val bounds: TypeBounds) extends Kind { import Kind.StringState diff --git a/test/files/pos/t8023.scala b/test/files/pos/t8023.scala new file mode 100644 index 0000000000..86824084ed --- /dev/null +++ b/test/files/pos/t8023.scala @@ -0,0 +1,22 @@ +import language._ + + +object Test { + def foo = (null: Any) match { + case a: A[k] => + // error: kinds of the type arguments (k) do not conform to the + // expected kinds of the type parameters (type K) in class B. + new B[k]() + } +} + +class A[K[L[_]]] + +class B[K[M[_]]] + + +object Test2 { + def foo = (null: Any) match { + case a: A[k] => new B[k]() // this one worked before as the info of `A` was complete + } +} diff --git a/test/files/pos/t8023b.scala b/test/files/pos/t8023b.scala new file mode 100644 index 0000000000..94c9b2f8d2 --- /dev/null +++ b/test/files/pos/t8023b.scala @@ -0,0 +1,2 @@ +// this fails with naive attempts to fix SI-8023 +trait T[A <: T[A]] |