@@ -7,7 +7,7 @@ import dotty.tools.dotc.ast.untpd.ImportSelector
77import dotty .tools .dotc .config .ScalaSettings
88import dotty .tools .dotc .core .Contexts .*
99import dotty .tools .dotc .core .Decorators .{em , i }
10- import dotty .tools .dotc .core .Flags .{ Given , Implicit , GivenOrImplicit , Param , Private , SelfName , Synthetic }
10+ import dotty .tools .dotc .core .Flags ._
1111import dotty .tools .dotc .core .Phases .Phase
1212import dotty .tools .dotc .core .StdNames
1313import dotty .tools .dotc .report
@@ -25,6 +25,7 @@ import dotty.tools.dotc.transform.MegaPhase.MiniPhase
2525import dotty .tools .dotc .core .Annotations
2626import dotty .tools .dotc .core .Definitions
2727import dotty .tools .dotc .core .Types .ConstantType
28+ import dotty .tools .dotc .core .NameKinds .WildcardParamName
2829
2930
3031
@@ -108,8 +109,9 @@ class CheckUnused extends MiniPhase:
108109
109110 override def prepareForTypeDef (tree : tpd.TypeDef )(using Context ): Context =
110111 _key.unusedDataApply{ ud =>
111- ud.registerDef(tree)
112- ud.addIgnoredUsage(tree.symbol)
112+ if ! tree.symbol.is(Param ) then // Ignore type parameter (as Scala 2)
113+ ud.registerDef(tree)
114+ ud.addIgnoredUsage(tree.symbol)
113115 }
114116
115117 override def prepareForBind (tree : tpd.Bind )(using Context ): Context =
@@ -313,7 +315,7 @@ object CheckUnused:
313315 /** Register all annotations of this symbol's denotation */
314316 def registerUsedAnnotation (sym : Symbol )(using Context ): Unit =
315317 val annotSym = sym.denot.annotations.map(_.symbol)
316- registerUsed(annotSym )
318+ annotSym.foreach(s => registerUsed(s, None ) )
317319
318320 /**
319321 * Register a found (used) symbol along with its name
@@ -327,13 +329,6 @@ object CheckUnused:
327329 if sym.isConstructor && sym.exists then
328330 registerUsed(sym.owner, None ) // constructor are "implicitly" imported with the class
329331
330- /** Register a list of found (used) symbols */
331- def registerUsed (syms : Seq [Symbol ])(using Context ): Unit =
332- usedInScope.top ++=
333- syms
334- .filterNot(s => isConstructorOfSynth(s) || doNotRegister(s))
335- .map(s => (s, s.isAccessibleAsIdent, None ))
336-
337332 /** Register a symbol that should be ignored */
338333 def addIgnoredUsage (sym : Symbol )(using Context ): Unit =
339334 doNotRegister += sym
@@ -359,8 +354,8 @@ object CheckUnused:
359354 def registerDef (memDef : tpd.MemberDef )(using Context ): Unit =
360355 // register the annotations for usage
361356 registerUsedAnnotation(memDef.symbol)
362- if ! memDef.symbol.isUnusedAnnot && ! memDef.symbol.isAllOf( Flags . AccessorCreationFlags ) then
363- if memDef.symbol.is( Param ) && ! isSyntheticMainParam(memDef.symbol) && ! memDef.symbol.ownerIsTrivial then
357+ if memDef.isValidMemberDef then
358+ if memDef.isValidParam then
364359 if memDef.symbol.isOneOf(GivenOrImplicit ) then
365360 implicitParamInScope += memDef
366361 else
@@ -526,7 +521,7 @@ object CheckUnused:
526521
527522 extension (sym : Symbol )
528523 /** is accessible without import in current context */
529- def isAccessibleAsIdent (using Context ): Boolean =
524+ private def isAccessibleAsIdent (using Context ): Boolean =
530525 sym.exists &&
531526 ctx.outersIterator.exists{ c =>
532527 c.owner == sym.owner
@@ -536,7 +531,7 @@ object CheckUnused:
536531 }
537532
538533 /** Given an import and accessibility, return an option of selector that match import<->symbol */
539- def isInImport (imp : tpd.Import , isAccessible : Boolean , symName : Option [Name ])(using Context ): Option [ImportSelector ] =
534+ private def isInImport (imp : tpd.Import , isAccessible : Boolean , symName : Option [Name ])(using Context ): Option [ImportSelector ] =
540535 val tpd .Import (qual, sels) = imp
541536 val qualHasSymbol = qual.tpe.member(sym.name).alternatives.map(_.symbol).contains(sym)
542537 def selector = sels.find(sel => (sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name) && symName.map(n => n.toTermName == sel.rename).getOrElse(true ))
@@ -547,24 +542,55 @@ object CheckUnused:
547542 None
548543
549544 /** Annotated with @unused */
550- def isUnusedAnnot (using Context ): Boolean =
545+ private def isUnusedAnnot (using Context ): Boolean =
551546 sym.annotations.exists(a => a.symbol == ctx.definitions.UnusedAnnot )
552547
553- def ownerIsTrivial (using Context ): Boolean =
548+ private def shouldNotReportParamOwner (using Context ): Boolean =
549+ if sym.exists then
550+ val owner = sym.owner
551+ trivialDefs(owner) ||
552+ owner.is(Flags .Override ) ||
553+ owner.isPrimaryConstructor ||
554+ owner.annotations.exists (
555+ _.symbol == ctx.definitions.DeprecatedAnnot
556+ )
557+ else
558+ false
559+
560+ private def ownerIsTrivial (using Context ): Boolean =
554561 sym.exists && trivialDefs(sym.owner)
555562
556563 extension (defdef : tpd.DefDef )
557564 // so trivial that it never consumes params
558565 private def isTrivial (using Context ): Boolean =
559566 val rhs = defdef.rhs
560- rhs.symbol == ctx.definitions.Predef_undefined || rhs.tpe =:= ctx.definitions.NothingType || (rhs match {
567+ rhs.symbol == ctx.definitions.Predef_undefined ||
568+ rhs.tpe =:= ctx.definitions.NothingType ||
569+ defdef.symbol.is(Deferred ) ||
570+ (rhs match {
561571 case _ : tpd.Literal => true
562572 case _ => rhs.tpe.isInstanceOf [ConstantType ]
563573 })
564574 def registerTrivial (using Context ): Unit =
565575 if defdef.isTrivial then
566576 trivialDefs += defdef.symbol
567577
578+ extension (memDef : tpd.MemberDef )
579+ private def isValidMemberDef (using Context ): Boolean =
580+ ! memDef.symbol.isUnusedAnnot && ! memDef.symbol.isAllOf(Flags .AccessorCreationFlags ) && ! memDef.name.isWildcard
581+
582+ private def isValidParam (using Context ): Boolean =
583+ val sym = memDef.symbol
584+ (sym.is(Param ) || sym.isAllOf(PrivateParamAccessor )) &&
585+ ! isSyntheticMainParam(sym) &&
586+ ! sym.shouldNotReportParamOwner
587+
588+
589+ extension (thisName : Name )
590+ private def isWildcard : Boolean =
591+ thisName == StdNames .nme.WILDCARD || thisName.is(WildcardParamName )
592+
593+
568594 end UnusedData
569595
570596 private object UnusedData :
0 commit comments