diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 340197ffc4a0..00530c3a6936 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1932,7 +1932,7 @@ object SymDenotations { case _ => NoSymbol /** The explicitly given self type (self types of modules are assumed to be - * explcitly given here). + * explicitly given here). */ def givenSelfType(using Context): Type = classInfo.selfInfo match { case tp: Type => tp diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 0e4c1cda5b42..82eaa7dee176 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -581,7 +581,7 @@ object CheckUnused: end checkExplicit // begin if !infos.skip(m) - && !m.nextOverriddenSymbol.exists + && !m.isEffectivelyOverride && !allowed then checkExplicit() @@ -883,20 +883,20 @@ object CheckUnused: inline def exists(p: Name => Boolean): Boolean = nm.ne(nme.NO_NAME) && p(nm) inline def isWildcard: Boolean = nm == nme.WILDCARD || nm.is(WildcardParamName) - extension (tp: Type) - def importPrefix(using Context): Type = tp match + extension (tp: Type)(using Context) + def importPrefix: Type = tp match case tp: NamedType => tp.prefix case tp: ClassInfo => tp.prefix case tp: TypeProxy => tp.superType.normalizedPrefix case _ => NoType - def underlyingPrefix(using Context): Type = tp match + def underlyingPrefix: Type = tp match case tp: NamedType => tp.prefix case tp: ClassInfo => tp.prefix case tp: TypeProxy => tp.underlying.underlyingPrefix case _ => NoType - def skipPackageObject(using Context): Type = + def skipPackageObject: Type = if tp.typeSymbol.isPackageObject then tp.underlyingPrefix else tp - def underlying(using Context): Type = tp match + def underlying: Type = tp match case tp: TypeProxy => tp.underlying case _ => tp @@ -913,6 +913,9 @@ object CheckUnused: sym.isClass && sym.info.allMembers.forall: d => val m = d.symbol !m.isTerm || m.isSelfSym || m.is(Method) && (m.owner == defn.AnyClass || m.owner == defn.ObjectClass) + def isEffectivelyPrivate: Boolean = + sym.is(Private, butNot = ParamAccessor) + || sym.owner.isAnonymousClass && !sym.isEffectivelyOverride def isEffectivelyOverride: Boolean = sym.is(Override) || @@ -921,9 +924,6 @@ object CheckUnused: val base = if owner.classInfo.selfInfo != NoType then owner.thisType else owner.info base.baseClasses.drop(1).iterator.exists(sym.overriddenSymbol(_).exists) } - def isEffectivelyPrivate: Boolean = - sym.is(Private, butNot = ParamAccessor) - || sym.owner.isAnonymousClass && !sym.nextOverriddenSymbol.exists // pick the symbol the user wrote for purposes of tracking inline def userSymbol: Symbol= if sym.denot.is(ModuleClass) then sym.denot.companionModule else sym @@ -939,13 +939,13 @@ object CheckUnused: case untpd.Ident(nme.WILDCARD) => true case _ => false - extension (imp: Import) + extension (imp: Import)(using Context) /** Is it the first import clause in a statement? `a.x` in `import a.x, b.{y, z}` */ - def isPrimaryClause(using Context): Boolean = + def isPrimaryClause: Boolean = imp.srcPos.span.pointDelta > 0 // primary clause starts at `import` keyword with point at clause proper /** Generated import of cases from enum companion. */ - def isGeneratedByEnum(using Context): Boolean = + def isGeneratedByEnum: Boolean = imp.symbol.exists && imp.symbol.owner.is(Enum, butNot = Case) /** Under -Wunused:strict-no-implicit-warn, avoid false positives @@ -953,7 +953,7 @@ object CheckUnused: * specifically does import an implicit. * Similarly, import of CanEqual must not warn, as it is always witness. */ - def isLoose(sel: ImportSelector)(using Context): Boolean = + def isLoose(sel: ImportSelector): Boolean = if ctx.settings.WunusedHas.strictNoImplicitWarn then if sel.isWildcard || imp.expr.tpe.member(sel.name.toTermName).hasAltWith(_.symbol.isOneOf(GivenOrImplicit)) diff --git a/tests/warn/i15503f.scala b/tests/warn/i15503f.scala index 76badc659fb9..1b145a20280a 100644 --- a/tests/warn/i15503f.scala +++ b/tests/warn/i15503f.scala @@ -75,3 +75,18 @@ package givens: given namely (using x: X): Y with // warn protected param to given class def doY = "8" end givens + +object i22895: + trait Test[F[_], Ev] { + def apply[A, B](fa: F[A])(f: A => B)(using ev: Ev): F[B] + } + given testId: Test[[a] =>> a, Unit] = + new Test[[a] =>> a, Unit] { + def apply[A, B](fa: A)(f: A => B)(using ev: Unit): B = f(fa) // nowarn override + } + class C: + def f(using s: String) = s.toInt + class D(i: Int) extends C: + override def f(using String) = compute(i) // nowarn override + def g(using sss: String) = compute(i) // warn + def compute(i: Int) = i * 42 // returning a class param is deemed trivial, make it non-trivial diff --git a/tests/warn/i22896/J.java b/tests/warn/i22896/J.java new file mode 100644 index 000000000000..d110dd16c8fd --- /dev/null +++ b/tests/warn/i22896/J.java @@ -0,0 +1,6 @@ + +public class J { + private int i = 42; + public int i() { return 27; } + public String i(int j) { return "hello, world"; } +} diff --git a/tests/warn/i22896/s.scala b/tests/warn/i22896/s.scala new file mode 100644 index 000000000000..678c77a9bb3e --- /dev/null +++ b/tests/warn/i22896/s.scala @@ -0,0 +1,13 @@ +//> using options -Werror -Wunused:privates + +def f = + new J: + override val i = -1 // nowarn, trust override + +def g = + new J: + override def i = -1 // nowarn, trust override + +def h = + new J: + override def i() = -1 // nowarn correctly matches signature diff --git a/tests/warn/unused-params.scala b/tests/warn/unused-params.scala index 3266f3957247..9136da6425a5 100644 --- a/tests/warn/unused-params.scala +++ b/tests/warn/unused-params.scala @@ -122,7 +122,7 @@ trait BadMix { self: InterFace => a } override def call(a: Int, - XXXX: String, // warn no longer excused because required by superclass + XXXX: String, // no warn still excused because override (required by self type) c: Double): Int = { println(c) a @@ -135,6 +135,14 @@ trait BadMix { self: InterFace => def i(implicit s: String) = answer // warn } +trait ImplFace: + self: InterFace => + def call(a: Int, + b: String, // no warn required by self type + c: Double): Int = + println(c) + a + class Unequal { override def equals(other: Any) = toString.nonEmpty // no warn (override) }