diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-12-02 17:14:41 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-12-02 20:47:47 +0100 |
commit | a89000be9f5b6506bcd891bd076700a9d1e79d01 (patch) | |
tree | 09e0b70eba2c07d0ab00eb3704ad6d0533c2f315 | |
parent | 073ebbd20ce9775260b83a78ecf9ed6a3e6d3d9e (diff) | |
download | scala-a89000be9f5b6506bcd891bd076700a9d1e79d01.tar.gz scala-a89000be9f5b6506bcd891bd076700a9d1e79d01.tar.bz2 scala-a89000be9f5b6506bcd891bd076700a9d1e79d01.zip |
SI-8023 Fix symbol-completion-order type var pattern bug
Removing the `isComplete` check altogether leads to cycles in,
for instatnce, F-bound type parameters:
trait LSO[+A, +Repr <: LSO[A, Repr]] // error: illegal cyclic reference involving type Repr
But, I believe that we can (and must) eagerly initialize the type
parameter symbols if we are typechecking a pattern.
While this appeared to regress in 2.11.x, but the problem was in fact
dormant and was merely uncovered in the fix for SI-7756, 3df1d77fc.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 22 | ||||
-rw-r--r-- | test/files/pos/t8023.scala | 22 |
2 files changed, 37 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6d799b0098..a8d332f96a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4879,14 +4879,22 @@ 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) => + //@M! the polytype denotes the expected kind + def pt = GenPolyType(tparam.typeParams, AnyTpe) + + // if symbol hasn't been fully loaded, can't check kind-arity + // ... except, if we're in a pattern, where we can and must (SI-8023) + if (mode.typingPatternOrTypePat) { + tparam.initialize + typedHigherKindedType(arg, mode, pt) } + else if (isComplete) + typedHigherKindedType(arg, mode, pt) + else + // This overload (without pt) allows type constructors, as we don't don't know the allowed kind. + typedHigherKindedType(arg, mode) + } val argtypes = args1 map (_.tpe) foreach2(args, tparams) { (arg, tparam) => 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 + } +} |