Skip to content

Commit 9d9314b

Browse files
committed
Fix #2473: Check self for inner class redefinitions
1 parent 5f1a8de commit 9d9314b

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1316,12 +1316,27 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
13161316
result
13171317
}
13181318

1319+
/** Checks if one of the decls is a type with the same name as class type member in selfType */
1320+
def classExistsOnSelf(decls: Scope, selfType: Type): Boolean = {
1321+
if (!selfType.exists || (selfType.classSymbol eq cls)) false
1322+
else {
1323+
def memberInSelfButNotThis(decl: Symbol) =
1324+
selfType.member(decl.name).symbol.filter(other => other.isClass && other.owner != cls)
1325+
decls.iterator.filter(_.isType).foldLeft(false) { (foundRedef, decl) =>
1326+
val other = memberInSelfButNotThis(decl)
1327+
if (other.exists)
1328+
ctx.error(CannotHaveSameNameAs(decl, other), decl.pos)
1329+
foundRedef || other.exists
1330+
}
1331+
}
1332+
}
1333+
13191334
completeAnnotations(cdef, cls)
13201335
val constr1 = typed(constr).asInstanceOf[DefDef]
13211336
val parentsWithClass = ensureFirstIsClass(parents mapconserve typedParent, cdef.namePos)
13221337
val parents1 = ensureConstrCall(cls, parentsWithClass)(superCtx)
13231338
val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible
1324-
if (self1.tpt.tpe.isError) {
1339+
if (self1.tpt.tpe.isError || classExistsOnSelf(cls.unforcedDecls, self1.tpt.tpe)) {
13251340
// fail fast to avoid typing the body with an error type
13261341
cdef.withType(UnspecifiedErrorType)
13271342
} else {

tests/neg/i2473.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
trait Foo { trait Inner }
2+
trait Bar { foo: Foo =>
3+
type Inner <: foo.Inner // error: type Inner cannot have the same name as trait Inner in trait Foo -- class definitions cannot be overridden
4+
}
5+
trait Baz { baz: Foo =>
6+
class Inner // error: class Inner cannot have the same name as trait Inner in trait Foo -- class definitions cannot be overridden
7+
}

0 commit comments

Comments
 (0)