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 Aug 23, 2021
1 parent 0925ac5 commit 9b5338d
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,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 @@ -102,6 +103,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
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/InventedNames.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ given X/*->givens::X#*/ with
given (using X/*->givens::X#*/): 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
given [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
11 changes: 6 additions & 5 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ classes/C12#foo2Impl().(context) => param context: Context
classes/C12#foo2Impl().(x) => param x: context.Expr[Int]
classes/C12#foo2Impl().(y) => param y: context.Expr[String]
classes/M. => final object M extends Object { self: M.type => +3 decls }
classes/M.C5# => class C5 extends Object { self: C5 => +2 decls }
classes/M.C5# => implicit class C5 extends Object { self: C5 => +2 decls }
classes/M.C5#`<init>`(). => primary ctor <init> (param x: Int): C5
classes/M.C5#`<init>`().(x) => param x: Int
classes/M.C5#x. => private[this] val method x Int
Expand Down Expand Up @@ -1519,7 +1519,7 @@ example/ImplicitConversion#string2Number().(string) => param string: String
example/ImplicitConversion#tuple. => val method tuple Tuple2[Int, Int]
example/ImplicitConversion#x. => val method x Int
example/ImplicitConversion. => final object ImplicitConversion extends Object { self: ImplicitConversion.type => +6 decls }
example/ImplicitConversion.newAny2stringadd# => final class newAny2stringadd [typeparam A ] extends AnyVal { self: newAny2stringadd[A] => +4 decls }
example/ImplicitConversion.newAny2stringadd# => final implicit class newAny2stringadd [typeparam A ] extends AnyVal { self: newAny2stringadd[A] => +4 decls }
example/ImplicitConversion.newAny2stringadd#[A] => typeparam A
example/ImplicitConversion.newAny2stringadd#`+`(). => method + (param other: String): String
example/ImplicitConversion.newAny2stringadd#`+`().(other) => param other: String
Expand Down Expand Up @@ -1684,7 +1684,7 @@ Uri => InventedNames.scala
Text => empty
Language => Scala
Symbols => 45 entries
Occurrences => 61 entries
Occurrences => 62 entries

Symbols:
givens/InventedNames$package. => final package object givens extends Object { self: givens.type => +24 decls }
Expand All @@ -1705,14 +1705,14 @@ givens/InventedNames$package.given_List_T().[T] => typeparam T
givens/InventedNames$package.given_String. => final implicit lazy val given method given_String String
givens/InventedNames$package.given_X. => final implicit given object given_X extends Object with X { self: given_X.type => +2 decls }
givens/InventedNames$package.given_X.doX(). => method doX => Int <: givens/X#doX().
givens/InventedNames$package.given_Y# => class given_Y extends Object with Y { self: given_Y => +3 decls }
givens/InventedNames$package.given_Y# => implicit given class given_Y extends Object with Y { self: given_Y => +3 decls }
givens/InventedNames$package.given_Y#`<init>`(). => primary ctor <init> ()(implicit val given param x$1: X): given_Y
givens/InventedNames$package.given_Y#`<init>`().(x$1) => implicit val given param x$1: X
givens/InventedNames$package.given_Y#doY(). => method doY => String <: givens/Y#doY().
givens/InventedNames$package.given_Y#x$1. => protected implicit val given method x$1 X
givens/InventedNames$package.given_Y(). => final implicit given method given_Y (implicit given param x$1: X): given_Y
givens/InventedNames$package.given_Y().(x$1) => implicit given param x$1: X
givens/InventedNames$package.given_Z_T# => class given_Z_T [typeparam T ] extends Object with Z[T] { self: given_Z_T[T] => +3 decls }
givens/InventedNames$package.given_Z_T# => implicit given class given_Z_T [typeparam T ] extends Object with Z[T] { self: given_Z_T[T] => +3 decls }
givens/InventedNames$package.given_Z_T#[T] => typeparam T
givens/InventedNames$package.given_Z_T#`<init>`(). => primary ctor <init> [typeparam T ](): given_Z_T[T]
givens/InventedNames$package.given_Z_T#doZ(). => method doZ => List[T] <: givens/Z#doZ().
Expand Down Expand Up @@ -1767,6 +1767,7 @@ Occurrences:
[24:17..24:18): Y -> givens/Y#
[25:6..25:9): doY <- givens/InventedNames$package.given_Y#doY().
[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 9b5338d

Please sign in to comment.