summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala19
-rw-r--r--test/files/neg/t2208.check4
-rw-r--r--test/files/neg/t2208.scala8
-rw-r--r--test/files/pos/t2208.scala8
5 files changed, 39 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 0ebd2018fb..e115446147 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1559,6 +1559,8 @@ A type's typeSymbol should never be inspected directly.
PolyType(typeParams, typeRef(pre, sym.initialize, dummyArgs))
} else if (sym.isRefinementClass) {
sym.info.normalize // @MO to AM: OK?
+ //@M I think this is okay, but changeset 12414 (which fixed #1241) re-introduced another bug (#2208)
+ // see typedTypeConstructor in Typers
} else {
super.normalize
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a552c2ef7c..c3fa5555c4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3875,11 +3875,26 @@ trait Typers { self: Analyzer =>
/** Types a type constructor tree used in a new or supertype */
def typedTypeConstructor(tree: Tree, mode: Int): Tree = {
val result = typed(tree, typeMode(mode) | FUNmode, WildcardType)
- val restpe = result.tpe.normalize
+
+ val restpe = result.tpe.normalize // normalize to get rid of type aliases for the following check (#1241)
if (!phase.erasedTypes && restpe.isInstanceOf[TypeRef] && !restpe.prefix.isStable) {
error(tree.pos, restpe.prefix+" is not a legal prefix for a constructor")
}
- result setType restpe // @M: normalization is done during erasure
+
+ //@M fix for #2208
+ // if there are no type arguments, normalization does not bypass any checks, so perform it to get rid of AnyRef
+ if(result.tpe.typeArgs.isEmpty) {
+ // minimal check: if(result.tpe.typeSymbolDirect eq AnyRefClass) {
+ // must expand the fake AnyRef type alias, because bootstrapping (init in Definitions) is not
+ // designed to deal with the cycles in the scala package (ScalaObject extends
+ // AnyRef, but the AnyRef type alias is entered after the scala package is
+ // loaded and completed, so that ScalaObject is unpickled while AnyRef is not
+ // yet defined )
+ result setType(restpe)
+ } else { // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208
+ // during uncurry (after refchecks), all types are normalized
+ result
+ }
}
def typedTypeConstructor(tree: Tree): Tree = typedTypeConstructor(tree, NOmode)
diff --git a/test/files/neg/t2208.check b/test/files/neg/t2208.check
new file mode 100644
index 0000000000..6f7d60d84e
--- /dev/null
+++ b/test/files/neg/t2208.check
@@ -0,0 +1,4 @@
+ticket2208.scala:7: error: type arguments [Any] do not conform to type Alias's type parameter bounds [X <: Test.A]
+ class C extends Alias[Any] // not ok, normalisation should check bounds before expanding Alias
+ ^
+one error found \ No newline at end of file
diff --git a/test/files/neg/t2208.scala b/test/files/neg/t2208.scala
new file mode 100644
index 0000000000..43bb0adec5
--- /dev/null
+++ b/test/files/neg/t2208.scala
@@ -0,0 +1,8 @@
+object Test {
+ class A
+
+ class B[X]
+ type Alias[X <: A] = B[X]
+
+ class C extends Alias[Any] // not ok, normalisation should check bounds before expanding Alias
+} \ No newline at end of file
diff --git a/test/files/pos/t2208.scala b/test/files/pos/t2208.scala
new file mode 100644
index 0000000000..f1a521b14c
--- /dev/null
+++ b/test/files/pos/t2208.scala
@@ -0,0 +1,8 @@
+object Test {
+ class A
+
+ class B[X]
+ type Alias[X <: A] = B[X]
+
+ val foo: B[A] = new Alias[A] // check that type aliases can be instantiated
+} \ No newline at end of file