diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index c526a4324a10..aca6fced1602 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -954,6 +954,12 @@ class Namer { typer: Typer => else if (sym.isConstructor || sym.is(ModuleClass) || sym.is(Bridge)) SKIP else if (cls.derivesFrom(sym.owner) && (sym.owner == cls || !sym.is(Deferred))) i"is already a member of $cls" + else if (sym.is(Override)) + sym.allOverriddenSymbols.find( + other => cls.derivesFrom(other.owner) && !other.is(Deferred)) match { + case Some(other) => i"overrides ${other.showLocated}, which is already a member of $cls" + case None => "" + } else "" } diff --git a/docs/docs/reference/other-new-features/export.md b/docs/docs/reference/other-new-features/export.md index 358eb41af04a..b87f9d7bf1b9 100644 --- a/docs/docs/reference/other-new-features/export.md +++ b/docs/docs/reference/other-new-features/export.md @@ -59,6 +59,8 @@ of one of the following forms: A member is _eligible_ if all of the following holds: - its owner is not a base class of the class(*) containing the export clause, + - the member does not override a concrete definition that has as owner + a base class of the class containing the export clause. - it is accessible at the export clause, - it is not a constructor, nor the (synthetic) class part of an object, - it is a given instance (or an old-style `implicit` value) diff --git a/tests/neg/i7086.scala b/tests/neg/i7086.scala new file mode 100644 index 000000000000..61790d94a6cd --- /dev/null +++ b/tests/neg/i7086.scala @@ -0,0 +1,23 @@ +object Test1 { + class A { + override def toString: String = "A" + } + class B(a: A) { + export a.toString // error: no eligible member toString at B.this.a + } +} + +object Test extends App { + trait T { + def foo: Int = 1 + def bar: Int + } + class A extends T { + override def foo = 2 + override def bar = 2 + } + class B(a: A) extends T { + export a.foo // error: no eligible member foo at B.this.a + export a.bar // OK + } +} \ No newline at end of file diff --git a/tests/run/i7086.scala b/tests/run/i7086.scala new file mode 100644 index 000000000000..d17f7adcba70 --- /dev/null +++ b/tests/run/i7086.scala @@ -0,0 +1,25 @@ +object Test1 { + class A { + override def toString: String = "A" + } + class B(a: A) { + export a._ // OK + } +} + +object Test extends App { + trait T { + def foo: Int = 1 + def bar: Int + } + class A extends T { + override def foo = 2 + override def bar = 2 + } + class B(a: A) extends T { + export a._ + } + val b = B(A()) + assert(b.foo == 1) + assert(b.bar == 2) +} \ No newline at end of file