Skip to content

Commit e4ebaca

Browse files
authored
Merge pull request #346 from scala/backport-lts-3.3-22901
Backport "No warn implicit param of overriding method" to 3.3 LTS
2 parents d0255bb + 87fbea5 commit e4ebaca

File tree

6 files changed

+57
-15
lines changed

6 files changed

+57
-15
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,7 @@ object SymDenotations {
19321932
case _ => NoSymbol
19331933

19341934
/** The explicitly given self type (self types of modules are assumed to be
1935-
* explcitly given here).
1935+
* explicitly given here).
19361936
*/
19371937
def givenSelfType(using Context): Type = classInfo.selfInfo match {
19381938
case tp: Type => tp

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ object CheckUnused:
581581
end checkExplicit
582582
// begin
583583
if !infos.skip(m)
584-
&& !m.nextOverriddenSymbol.exists
584+
&& !m.isEffectivelyOverride
585585
&& !allowed
586586
then
587587
checkExplicit()
@@ -883,20 +883,20 @@ object CheckUnused:
883883
inline def exists(p: Name => Boolean): Boolean = nm.ne(nme.NO_NAME) && p(nm)
884884
inline def isWildcard: Boolean = nm == nme.WILDCARD || nm.is(WildcardParamName)
885885

886-
extension (tp: Type)
887-
def importPrefix(using Context): Type = tp match
886+
extension (tp: Type)(using Context)
887+
def importPrefix: Type = tp match
888888
case tp: NamedType => tp.prefix
889889
case tp: ClassInfo => tp.prefix
890890
case tp: TypeProxy => tp.superType.normalizedPrefix
891891
case _ => NoType
892-
def underlyingPrefix(using Context): Type = tp match
892+
def underlyingPrefix: Type = tp match
893893
case tp: NamedType => tp.prefix
894894
case tp: ClassInfo => tp.prefix
895895
case tp: TypeProxy => tp.underlying.underlyingPrefix
896896
case _ => NoType
897-
def skipPackageObject(using Context): Type =
897+
def skipPackageObject: Type =
898898
if tp.typeSymbol.isPackageObject then tp.underlyingPrefix else tp
899-
def underlying(using Context): Type = tp match
899+
def underlying: Type = tp match
900900
case tp: TypeProxy => tp.underlying
901901
case _ => tp
902902

@@ -913,6 +913,9 @@ object CheckUnused:
913913
sym.isClass && sym.info.allMembers.forall: d =>
914914
val m = d.symbol
915915
!m.isTerm || m.isSelfSym || m.is(Method) && (m.owner == defn.AnyClass || m.owner == defn.ObjectClass)
916+
def isEffectivelyPrivate: Boolean =
917+
sym.is(Private, butNot = ParamAccessor)
918+
|| sym.owner.isAnonymousClass && !sym.isEffectivelyOverride
916919
def isEffectivelyOverride: Boolean =
917920
sym.is(Override)
918921
||
@@ -921,9 +924,6 @@ object CheckUnused:
921924
val base = if owner.classInfo.selfInfo != NoType then owner.thisType else owner.info
922925
base.baseClasses.drop(1).iterator.exists(sym.overriddenSymbol(_).exists)
923926
}
924-
def isEffectivelyPrivate: Boolean =
925-
sym.is(Private, butNot = ParamAccessor)
926-
|| sym.owner.isAnonymousClass && !sym.nextOverriddenSymbol.exists
927927
// pick the symbol the user wrote for purposes of tracking
928928
inline def userSymbol: Symbol=
929929
if sym.denot.is(ModuleClass) then sym.denot.companionModule else sym
@@ -939,21 +939,21 @@ object CheckUnused:
939939
case untpd.Ident(nme.WILDCARD) => true
940940
case _ => false
941941

942-
extension (imp: Import)
942+
extension (imp: Import)(using Context)
943943
/** Is it the first import clause in a statement? `a.x` in `import a.x, b.{y, z}` */
944-
def isPrimaryClause(using Context): Boolean =
944+
def isPrimaryClause: Boolean =
945945
imp.srcPos.span.pointDelta > 0 // primary clause starts at `import` keyword with point at clause proper
946946

947947
/** Generated import of cases from enum companion. */
948-
def isGeneratedByEnum(using Context): Boolean =
948+
def isGeneratedByEnum: Boolean =
949949
imp.symbol.exists && imp.symbol.owner.is(Enum, butNot = Case)
950950

951951
/** Under -Wunused:strict-no-implicit-warn, avoid false positives
952952
* if this selector is a wildcard that might import implicits or
953953
* specifically does import an implicit.
954954
* Similarly, import of CanEqual must not warn, as it is always witness.
955955
*/
956-
def isLoose(sel: ImportSelector)(using Context): Boolean =
956+
def isLoose(sel: ImportSelector): Boolean =
957957
if ctx.settings.WunusedHas.strictNoImplicitWarn then
958958
if sel.isWildcard
959959
|| imp.expr.tpe.member(sel.name.toTermName).hasAltWith(_.symbol.isOneOf(GivenOrImplicit))

tests/warn/i15503f.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,18 @@ package givens:
7575
given namely (using x: X): Y with // warn protected param to given class
7676
def doY = "8"
7777
end givens
78+
79+
object i22895:
80+
trait Test[F[_], Ev] {
81+
def apply[A, B](fa: F[A])(f: A => B)(using ev: Ev): F[B]
82+
}
83+
given testId: Test[[a] =>> a, Unit] =
84+
new Test[[a] =>> a, Unit] {
85+
def apply[A, B](fa: A)(f: A => B)(using ev: Unit): B = f(fa) // nowarn override
86+
}
87+
class C:
88+
def f(using s: String) = s.toInt
89+
class D(i: Int) extends C:
90+
override def f(using String) = compute(i) // nowarn override
91+
def g(using sss: String) = compute(i) // warn
92+
def compute(i: Int) = i * 42 // returning a class param is deemed trivial, make it non-trivial

tests/warn/i22896/J.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
public class J {
3+
private int i = 42;
4+
public int i() { return 27; }
5+
public String i(int j) { return "hello, world"; }
6+
}

tests/warn/i22896/s.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//> using options -Werror -Wunused:privates
2+
3+
def f =
4+
new J:
5+
override val i = -1 // nowarn, trust override
6+
7+
def g =
8+
new J:
9+
override def i = -1 // nowarn, trust override
10+
11+
def h =
12+
new J:
13+
override def i() = -1 // nowarn correctly matches signature

tests/warn/unused-params.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ trait BadMix { self: InterFace =>
122122
a
123123
}
124124
override def call(a: Int,
125-
XXXX: String, // warn no longer excused because required by superclass
125+
XXXX: String, // no warn still excused because override (required by self type)
126126
c: Double): Int = {
127127
println(c)
128128
a
@@ -135,6 +135,14 @@ trait BadMix { self: InterFace =>
135135
def i(implicit s: String) = answer // warn
136136
}
137137

138+
trait ImplFace:
139+
self: InterFace =>
140+
def call(a: Int,
141+
b: String, // no warn required by self type
142+
c: Double): Int =
143+
println(c)
144+
a
145+
138146
class Unequal {
139147
override def equals(other: Any) = toString.nonEmpty // no warn (override)
140148
}

0 commit comments

Comments
 (0)