Skip to content

Commit

Permalink
Use a new prefixDirect in checkKindBounds0
Browse files Browse the repository at this point in the history
Analogous to `typeSymbolDirect`, we add `prefixDirect`,
because `prefix` normalizes type aliases.
But kind-checking should not normalize type aliases.
This was the intention as noted by comments and `typeSymbolDirect`.
  • Loading branch information
joroKr21 committed Dec 21, 2020
1 parent 1a4fa66 commit 70169c0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/reflect/scala/reflect/internal/Kinds.scala
Expand Up @@ -219,14 +219,15 @@ trait Kinds {
// Prevent WildcardType from causing kind errors, as typevars may be higher-order
if (targ == WildcardType) Nil else {
// NOTE: *not* targ.typeSymbol, which normalizes
val targSym = targ.typeSymbolDirect
// force symbol load for #4205
targSym.info
// force initialize symbol for scala/bug#4205
val targSym = targ.typeSymbolDirect.initialize
// NOTE: *not* targ.prefix, which normalizes
val targPre = targ.prefixDirect
// @M must use the typeParams of the *type* targ, not of the *symbol* of targ!!
val tparamsHO = targ.typeParams
if (targ.isHigherKinded || tparam.typeParams.nonEmpty) {
val kindErrors = checkKindBoundsHK(
tparamsHO, targSym, targ.prefix, targSym.owner,
tparamsHO, targSym, targPre, targSym.owner,
tparam, tparam.owner, tparam.typeParams, tparamsHO
)
if (kindErrors.isEmpty) Nil else {
Expand Down
8 changes: 8 additions & 0 deletions src/reflect/scala/reflect/internal/Types.scala
Expand Up @@ -163,6 +163,7 @@ trait Types
override def upperBound = underlying.upperBound
override def parents = underlying.parents
override def prefix = underlying.prefix
override def prefixDirect = underlying.prefixDirect
override def decls = underlying.decls
override def baseType(clazz: Symbol) = underlying.baseType(clazz)
override def baseTypeSeq = underlying.baseTypeSeq
Expand Down Expand Up @@ -425,6 +426,12 @@ trait Types
* NoType for all other types. */
def prefix: Type = NoType

/** The prefix ''directly'' associated with the type.
* In other words, no normalization is performed: if this is an alias type,
* the prefix returned is that of the alias, not the underlying type.
*/
def prefixDirect: Type = prefix

/** A chain of all typeref or singletype prefixes of this type, longest first.
* (Only used from safeToString.)
*/
Expand Down Expand Up @@ -2580,6 +2587,7 @@ trait Types

override def baseTypeSeqDepth = baseTypeSeq.maxDepth
override def prefix = pre
override def prefixDirect = pre
override def termSymbol = super.termSymbol
override def termSymbolDirect = super.termSymbol
override def typeArgs = args
Expand Down
9 changes: 9 additions & 0 deletions test/files/pos/t10186.scala
@@ -0,0 +1,9 @@
object Test {
trait Foo {
type A
type F[_ <: A]
}

def noop[A, F[_ <: A]]: Unit = ()
def f(foo: Foo): Unit = noop[foo.A, foo.F]
}
13 changes: 13 additions & 0 deletions test/files/pos/t9337.scala
@@ -0,0 +1,13 @@
object Test {
trait TypePreservingFn[T[X <: T[X]]]
trait Validator[T, This <: Validator[T,This]]

trait Foo[T] {
type V[This <: Validator[T, This]] = Validator[T, This]
val f: TypePreservingFn[V] = ???
}

class Bar[T] extends Foo[T] {
val g: TypePreservingFn[V] = ???
}
}

0 comments on commit 70169c0

Please sign in to comment.