Skip to content

Commit

Permalink
Exclude implicit class conversions in SemanticDB
Browse files Browse the repository at this point in the history
Conversions generated for implicit classes were synthetic before,
now they need to be excluded separately.
  • Loading branch information
odersky committed Jul 23, 2021
1 parent c98150f commit d97ba02
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class ExtractSemanticDB extends Phase:
|| sym.isLocalDummy
|| sym.is(Synthetic)
|| sym.isSetter
|| sym.isOldStyleImplicitConversion(forImplicitClassOnly = true)
|| excludeDefOrUse(sym)

private def excludeDefOrUse(sym: Symbol)(using Context): Boolean =
Expand All @@ -103,6 +104,7 @@ class ExtractSemanticDB extends Phase:
private def excludeChildren(sym: Symbol)(using Context): Boolean =
!sym.exists
|| sym.is(Param) && sym.info.bounds.hi.isInstanceOf[Types.HKTypeLambda]
|| sym.isOldStyleImplicitConversion(forImplicitClassOnly = true)

/** Uses of this symbol where the reference has given span should be excluded from semanticdb */
private def excludeUse(qualifier: Option[Symbol], sym: Symbol)(using Context): Boolean =
Expand Down
13 changes: 13 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ object SymUtils:

def isGenericProduct(using Context): Boolean = whyNotGenericProduct.isEmpty

/** Is this the an old style implicit conversion?
* @param directOnly only consider explicitly written methods
* @param forImplicitClassOnly only consider methods generated from implicit classes
*/
def isOldStyleImplicitConversion(directOnly: Boolean = false, forImplicitClassOnly: Boolean = false)(using Context): Boolean =
self.is(Implicit) && self.info.stripPoly.match
case mt @ MethodType(_ :: Nil) if !mt.isImplicitMethod =>
if self.isCoDefinedGiven(mt.finalResultType.typeSymbol)
then !directOnly
else !forImplicitClassOnly
case _ =>
false

def useCompanionAsMirror(using Context): Boolean = self.linkedClass.exists && !self.is(Scala2x)

/** Is this a sealed class or trait for which a sum mirror is generated?
Expand Down
13 changes: 2 additions & 11 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -861,23 +861,14 @@ trait Checking {
/** If `sym` is an old-style implicit conversion, check that implicit conversions are enabled.
* @pre sym.is(GivenOrImplicit)
*/
def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit = {
def check(): Unit =
def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit =
if sym.isOldStyleImplicitConversion(directOnly = true) then
checkFeature(
nme.implicitConversions,
i"Definition of implicit conversion $sym",
ctx.owner.topLevelClass,
sym.srcPos)

sym.info.stripPoly match {
case mt @ MethodType(_ :: Nil)
if !mt.isImplicitMethod && !sym.isCoDefinedGiven(mt.finalResultType.typeSymbol) =>
// it's an old-style conversion
check()
case _ =>
}
}

/** If `tree` is an application of a new-style implicit conversion (using the apply
* method of a `scala.Conversion` instance), check that implicit conversions are
* enabled.
Expand Down
4 changes: 2 additions & 2 deletions tests/semanticdb/expect/InventedNames.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ given `* */*<-givens::InventedNames$package.`* *`.*/`: Long/*->scala::Long#*/ =
given X with
/*<-givens::InventedNames$package.given_X.*//*->givens::X#*/ def doX/*<-givens::InventedNames$package.given_X.doX().*/ = 7

given (using X/*->givens::X#*/): Y/*->givens::Y#*/ with
/*->givens::InventedNames$package.given_Y().(x$1)*/given /*<-givens::InventedNames$package.given_Y().*/(using X/*->givens::X#*//*<-givens::InventedNames$package.given_Y().(x$1)*/): Y/*->givens::Y#*/ with
def doY/*<-givens::InventedNames$package.given_Y#doY().*/ = "7"

given [T/*<-givens::InventedNames$package.given_Z_T#[T]*/]: Z/*->givens::Z#*/[T/*->givens::InventedNames$package.given_Z_T#[T]*/] with
/*->givens::InventedNames$package.given_Z_T().[T]*/given /*<-givens::InventedNames$package.given_Z_T().*/[T/*<-givens::InventedNames$package.given_Z_T#[T]*//*<-givens::InventedNames$package.given_Z_T().[T]*/]: Z/*->givens::Z#*/[T/*->givens::InventedNames$package.given_Z_T#[T]*/] with
def doZ/*<-givens::InventedNames$package.given_Z_T#doZ().*/: List/*->scala::package.List#*/[T/*->givens::InventedNames$package.given_Z_T#[T]*/] = Nil/*->scala::package.Nil.*/


Expand Down
17 changes: 11 additions & 6 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ Schema => SemanticDB v4
Uri => Classes.scala
Text => empty
Language => Scala
Symbols => 109 entries
Symbols => 108 entries
Occurrences => 130 entries

Symbols:
Expand Down Expand Up @@ -467,7 +467,6 @@ classes/M.C5#`<init>`(). => primary ctor <init>
classes/M.C5#`<init>`().(x) => param x
classes/M.C5#x. => private[this] val method x
classes/M.C5(). => final implicit method C5
classes/M.C5().(x) => param x
classes/N. => final object N
classes/N.anonClass. => val method anonClass
classes/N.anonFun. => val method anonFun
Expand Down Expand Up @@ -1546,7 +1545,7 @@ Schema => SemanticDB v4
Uri => ImplicitConversion.scala
Text => empty
Language => Scala
Symbols => 23 entries
Symbols => 21 entries
Occurrences => 62 entries

Symbols:
Expand All @@ -1570,8 +1569,6 @@ example/ImplicitConversion.newAny2stringadd#`<init>`(). => primary ctor <init>
example/ImplicitConversion.newAny2stringadd#`<init>`().(self) => param self
example/ImplicitConversion.newAny2stringadd#self. => private val method self
example/ImplicitConversion.newAny2stringadd(). => final implicit method newAny2stringadd
example/ImplicitConversion.newAny2stringadd().(self) => param self
example/ImplicitConversion.newAny2stringadd().[A] => typeparam A
example/ImplicitConversion.newAny2stringadd. => final object newAny2stringadd

Occurrences:
Expand Down Expand Up @@ -1744,7 +1741,7 @@ Uri => InventedNames.scala
Text => empty
Language => Scala
Symbols => 45 entries
Occurrences => 72 entries
Occurrences => 80 entries

Symbols:
givens/InventedNames$package. => final package object givens
Expand Down Expand Up @@ -1830,12 +1827,20 @@ Occurrences:
[21:6..22:0): <- givens/InventedNames$package.given_X.
[21:6..21:7): X -> givens/X#
[22:6..22:9): doX <- givens/InventedNames$package.given_X.doX().
[24:0..24:0): -> givens/InventedNames$package.given_Y#`<init>`().
[24:0..24:0): -> givens/InventedNames$package.given_Y().(x$1)
[24:6..24:6): <- givens/InventedNames$package.given_Y().
[24:13..24:13): <- givens/InventedNames$package.given_Y#`<init>`().
[24:13..24:14): X -> givens/X#
[24:13..24:13): <- givens/InventedNames$package.given_Y().(x$1)
[24:17..24:18): Y -> givens/Y#
[25:6..25:9): doY <- givens/InventedNames$package.given_Y#doY().
[27:0..27:0): -> givens/InventedNames$package.given_Z_T().[T]
[27:0..27:0): -> givens/InventedNames$package.given_Z_T#`<init>`().
[27:6..27:6): <- givens/InventedNames$package.given_Z_T().
[27:7..27:7): <- givens/InventedNames$package.given_Z_T#`<init>`().
[27:7..27:8): T <- givens/InventedNames$package.given_Z_T#[T]
[27:7..27:8): T <- givens/InventedNames$package.given_Z_T().[T]
[27:11..27:12): Z -> givens/Z#
[27:13..27:14): T -> givens/InventedNames$package.given_Z_T#[T]
[28:6..28:9): doZ <- givens/InventedNames$package.given_Z_T#doZ().
Expand Down

0 comments on commit d97ba02

Please sign in to comment.