From 696dcdfcdb40ee3dbd2ba63f8281b87cde787a00 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 25 Feb 2013 17:58:11 +0100 Subject: [PATCH 1/2] SI-7126 Account for the alias types that don't dealias. After this change: qbin/scalac -Ydebug test/files/pos/t7126.scala 2>&1 | grep warning warning: dropExistential did not progress dealiasing Test.this.T[Test.this.T], see SI-7126 one warning found T[T]? Really? The true bug lies somewhere else; the comments of the ticket illuminate the general areas of concern. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 9 +++++++-- test/files/pos/t7126.scala | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/files/pos/t7126.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index cff3f4f0fa18..4fb68fc2a9cb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -222,8 +222,13 @@ trait Typers extends Modes with Adaptations with Tags { new SubstWildcardMap(tparams).apply(tp) case TypeRef(_, sym, _) if sym.isAliasType => val tp0 = tp.dealias - val tp1 = dropExistential(tp0) - if (tp1 eq tp0) tp else tp1 + if (tp eq tp0) { + debugwarn(s"dropExistential did not progress dealiasing $tp, see SI-7126") + tp + } else { + val tp1 = dropExistential(tp0) + if (tp1 eq tp0) tp else tp1 + } case _ => tp } diff --git a/test/files/pos/t7126.scala b/test/files/pos/t7126.scala new file mode 100644 index 000000000000..6720511e08a7 --- /dev/null +++ b/test/files/pos/t7126.scala @@ -0,0 +1,11 @@ +import language._ + +object Test { + type T = Any + boom(???): Option[T] // SOE + def boom[CC[U]](t : CC[T]): Option[CC[T]] = None + + // okay + foo(???): Option[Any] + def foo[CC[U]](t : CC[Any]): Option[CC[Any]] = None +} \ No newline at end of file From 204b2b45a83cf057b6ece7a25ea4f15ec38b4a3f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 26 Feb 2013 17:11:43 +0100 Subject: [PATCH 2/2] SI-7126 Eliminate a source of malformed types. The kind-polymorphic nature of Nothing and Any in concert with type argument inference could lead to types like `T[T]` (where `type T=Any`). Compensatory action is taken later on to recover; see the usages of `TypeRef#typeParamsMatchArgs`. But this these types have a nasty property, they can dealias to themselves. Callers recursing through types who fail to account for this hit an infinite recursion, as was reported in SI-7126. This commit simply dealiases `T` when registering the type bound in `unifySimple`. We should try to weed out additional sources of these types. --- src/reflect/scala/reflect/internal/Types.scala | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index fb493fabd86b..7299b439f83b 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3183,12 +3183,19 @@ trait Types extends api.Types { self: SymbolTable => * ?TC[?T] <: Any * }}} */ - def unifySimple = ( - (params.isEmpty || tp.typeSymbol == NothingClass || tp.typeSymbol == AnyClass) && { + def unifySimple = { + val sym = tp.typeSymbol + if (sym == NothingClass || sym == AnyClass) { // kind-polymorphic + // SI-7126 if we register some type alias `T=Any`, we can later end + // with malformed types like `T[T]` during type inference in + // `handlePolymorphicCall`. No such problem if we register `Any`. + addBound(sym.tpe) + true + } else if (params.isEmpty) { addBound(tp) true - } - ) + } else false + } /** Full case: involving a check of the form * {{{