Skip to content

Commit 9c6060a

Browse files
authored
Merge pull request #4137 from dotty-staging/add-thistypes
Several type system fixes
2 parents 7be9199 + e64c62c commit 9c6060a

File tree

7 files changed

+423
-32
lines changed

7 files changed

+423
-32
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ object SymDenotations {
14661466
val builder = new BaseDataBuilder
14671467
for (p <- classParents) {
14681468
if (p.typeSymbol.isClass) builder.addAll(p.typeSymbol.asClass.baseClasses)
1469-
else assert(ctx.mode.is(Mode.Interactive), s"$this has non-class parent: $p")
1469+
else assert(isRefinementClass || ctx.mode.is(Mode.Interactive), s"$this has non-class parent: $p")
14701470
}
14711471
(classSymbol :: builder.baseClasses, builder.baseClassSet)
14721472
}

compiler/src/dotty/tools/dotc/core/Types.scala

+28-30
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ object Types {
989989
case tp: TypeRef =>
990990
if (tp.symbol.isClass) tp
991991
else tp.info match {
992-
case TypeAlias(tp) => tp.dealias1(keepAnnots): @tailrec
992+
case TypeAlias(alias) => alias.dealias1(keepAnnots): @tailrec
993993
case _ => tp
994994
}
995995
case app @ AppliedType(tycon, args) =>
@@ -1967,37 +1967,35 @@ object Types {
19671967
def derivedSelect(prefix: Type)(implicit ctx: Context): Type =
19681968
if (prefix eq this.prefix) this
19691969
else if (prefix.isBottomType) prefix
1970-
else if (isType) {
1971-
val res =
1972-
if (currentSymbol.is(ClassTypeParam)) argForParam(prefix)
1973-
else prefix.lookupRefined(name)
1974-
if (res.exists) res
1975-
else if (Config.splitProjections)
1976-
prefix match {
1977-
case prefix: AndType =>
1978-
def isMissing(tp: Type) = tp match {
1979-
case tp: TypeRef => !tp.info.exists
1980-
case _ => false
1981-
}
1982-
val derived1 = derivedSelect(prefix.tp1)
1983-
val derived2 = derivedSelect(prefix.tp2)
1984-
return (
1985-
if (isMissing(derived1)) derived2
1986-
else if (isMissing(derived2)) derived1
1987-
else prefix.derivedAndType(derived1, derived2))
1988-
case prefix: OrType =>
1989-
val derived1 = derivedSelect(prefix.tp1)
1990-
val derived2 = derivedSelect(prefix.tp2)
1991-
return prefix.derivedOrType(derived1, derived2)
1992-
case _ =>
1993-
withPrefix(prefix)
1994-
}
1970+
else {
1971+
if (isType) {
1972+
val res =
1973+
if (currentSymbol.is(ClassTypeParam)) argForParam(prefix)
1974+
else prefix.lookupRefined(name)
1975+
if (res.exists) return res
1976+
if (Config.splitProjections)
1977+
prefix match {
1978+
case prefix: AndType =>
1979+
def isMissing(tp: Type) = tp match {
1980+
case tp: TypeRef => !tp.info.exists
1981+
case _ => false
1982+
}
1983+
val derived1 = derivedSelect(prefix.tp1)
1984+
val derived2 = derivedSelect(prefix.tp2)
1985+
return (
1986+
if (isMissing(derived1)) derived2
1987+
else if (isMissing(derived2)) derived1
1988+
else prefix.derivedAndType(derived1, derived2))
1989+
case prefix: OrType =>
1990+
val derived1 = derivedSelect(prefix.tp1)
1991+
val derived2 = derivedSelect(prefix.tp2)
1992+
return prefix.derivedOrType(derived1, derived2)
1993+
case _ =>
1994+
}
1995+
}
1996+
if (prefix.isInstanceOf[WildcardType]) WildcardType
19951997
else withPrefix(prefix)
19961998
}
1997-
else prefix match {
1998-
case _: WildcardType => WildcardType
1999-
case _ => withPrefix(prefix)
2000-
}
20011999

20022000
/** A reference like this one, but with the given symbol, if it exists */
20032001
final def withSym(sym: Symbol)(implicit ctx: Context): ThisType =

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ object ProtoTypes {
105105
private def hasUnknownMembers(tp: Type)(implicit ctx: Context): Boolean = tp match {
106106
case tp: TypeVar => !tp.isInstantiated
107107
case tp: WildcardType => true
108+
case NoType => true
108109
case tp: TypeRef =>
109110
val sym = tp.symbol
110111
sym == defn.NothingClass ||
@@ -114,6 +115,7 @@ object ProtoTypes {
114115
bound.isProvisional && hasUnknownMembers(bound)
115116
}
116117
}
118+
case tp: AppliedType => hasUnknownMembers(tp.tycon) || hasUnknownMembers(tp.superType)
117119
case tp: TypeProxy => hasUnknownMembers(tp.superType)
118120
case _ => false
119121
}

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,10 @@ object RefChecks {
343343
if (autoOverride(member) ||
344344
other.owner.is(JavaTrait) && ctx.testScala2Mode("`override' modifier required when a Java 8 default method is re-implemented", member.pos))
345345
member.setFlag(Override)
346-
else if (member.owner != clazz && other.owner != clazz && !(other.owner derivesFrom member.owner))
346+
else if (member.isType && self.memberInfo(member) =:= self.memberInfo(other))
347+
() // OK, don't complain about type aliases which are equal
348+
else if (member.owner != clazz && other.owner != clazz &&
349+
!(other.owner derivesFrom member.owner))
347350
emitOverrideError(
348351
clazz + " inherits conflicting members:\n "
349352
+ infoStringWithLocation(other) + " and\n " + infoStringWithLocation(member)

tests/neg/typeclass-encoding2.scala

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Used to crash with:
2+
// assertion failed: class <refinement> has non-class parent
3+
// Once that was fixed, another crash with:
4+
// assertion failed: invalid prefix WildcardType(NoType)
5+
object runtime1 {
6+
7+
trait TypeClass1[A] {
8+
val common: TypeClassCommon1
9+
type This[X] = common.This[X]
10+
}
11+
12+
trait TypeClassCommon1 { self =>
13+
type This[X]
14+
type Instance[X] <: TypeClass1[X]
15+
def inject[A](x: This[A]): Instance[A]// { val common: self.type }
16+
}
17+
18+
trait Extension1[From[_], To[X] <: TypeClass1[X]] extends TypeClassCommon1 {
19+
type This[X] = From[X]
20+
type Instance[X] = To[X]
21+
}
22+
23+
implicit def inject[A, From[_]](x: From[A])
24+
(implicit ev: Extension1[From, _]): ev.Instance[A] { type This[X] = From[X] } =
25+
ev.inject(x) // error: found: ev.To[A], required: ev.To[A]{This = From}
26+
}

tests/pos/this-types.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait A {
2+
type A_This <: A
3+
}
4+
trait B extends A {
5+
type A_This = B_This
6+
type B_This <: B
7+
}
8+
trait C extends A {
9+
type A_This = C_This
10+
type C_This <: C
11+
}
12+
trait D extends B with C {
13+
type B_This = D_This
14+
type C_This = D_This
15+
type D_This <: D
16+
}

0 commit comments

Comments
 (0)