summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-04-22 07:59:26 -0700
committerPaul Phillips <paulp@improving.org>2013-04-22 09:26:08 -0700
commit7b4e450e9b746a9289f6d429cdee73bffa5cd733 (patch)
treec34f3dbe89eac6b3328eead8baf866d16b50c336 /src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
parent1d54f26b9a87c8df6a3b0e4472147d1ffb9037f1 (diff)
downloadscala-7b4e450e9b746a9289f6d429cdee73bffa5cd733.tar.gz
scala-7b4e450e9b746a9289f6d429cdee73bffa5cd733.tar.bz2
scala-7b4e450e9b746a9289f6d429cdee73bffa5cd733.zip
SI-4365 nondeterministic failure in asSeenFrom
Under some order-dependent conditions (if source files arrive in one order it happens, in the other order it does not) more than one set of type parameters are created for a given class. Previously this would lead to a crash in asSeenFrom when a type parameter had to be matched up with a type application. Now when that situation arises I compare them by name and log a dev warning if it hits. This does not risk anything undesirable happening because the wayward type parameter's owner is always the right class; it's only the class type parameters which don't include the wayward one. Since in a given type parameter list names are unique, we have enough information to salvage the search.
Diffstat (limited to 'src/reflect/scala/reflect/internal/tpe/TypeMaps.scala')
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 0f9db31ec1..4227699da2 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -525,15 +525,39 @@ private[internal] trait TypeMaps {
val TypeRef(_, rhsSym, rhsArgs) = rhs
require(lhsSym.safeOwner == rhsSym, s"$lhsSym is not a type parameter of $rhsSym")
- // Find the type parameter position; we'll use the corresponding argument
- val argIndex = rhsSym.typeParams indexOf lhsSym
-
- if (argIndex >= 0 && argIndex < rhsArgs.length) // @M! don't just replace the whole thing, might be followed by type application
- appliedType(rhsArgs(argIndex), lhsArgs mapConserve this)
- else if (rhsSym.tpe_*.parents exists typeIsErroneous) // don't be too zealous with the exceptions, see #2641
+ // Find the type parameter position; we'll use the corresponding argument.
+ // Why are we checking by name rather than by equality? Because for
+ // reasons which aren't yet fully clear, we can arrive here holding a type
+ // parameter whose owner is rhsSym, and which shares the name of an actual
+ // type parameter of rhsSym, but which is not among the type parameters of
+ // rhsSym. One can see examples of it at SI-4365.
+ val argIndex = rhsSym.typeParams indexWhere (lhsSym.name == _.name)
+ // don't be too zealous with the exceptions, see #2641
+ if (argIndex < 0 && rhs.parents.exists(typeIsErroneous))
ErrorType
- else
- abort(s"something is wrong: cannot make sense of type application\n $lhs\n $rhs")
+ else {
+ // It's easy to get here when working on hardcore type machinery (not to
+ // mention when not doing so, see above) so let's provide a standout error.
+ def own_s(s: Symbol) = s.nameString + " in " + s.safeOwner.nameString
+ def explain =
+ sm"""| sought ${own_s(lhsSym)}
+ | classSym ${own_s(rhsSym)}
+ | tparams ${rhsSym.typeParams map own_s mkString ", "}
+ |"""
+
+ if (argIndex < 0)
+ abort(s"Something is wrong: cannot find $lhs in applied type $rhs\n" + explain)
+ else {
+ val targ = rhsArgs(argIndex)
+ // @M! don't just replace the whole thing, might be followed by type application
+ val result = appliedType(targ, lhsArgs mapConserve this)
+ def msg = s"Created $result, though could not find ${own_s(lhsSym)} among tparams of ${own_s(rhsSym)}"
+ if (!rhsSym.typeParams.contains(lhsSym))
+ devWarning(s"Inconsistent tparam/owner views: had to fall back on names\n$msg\n$explain")
+
+ result
+ }
+ }
}
// 0) @pre: `classParam` is a class type parameter