Skip to content

Change implicit conversions warnings #9935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 15 additions & 23 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -761,29 +761,21 @@ trait Checking {
}
}

/** If `sym` is an implicit conversion, check that that implicit conversions are enabled, unless
* - it is synthetic
* - it is has the same owner as one of the classes it converts to (modulo companions)
* - it is defined in Predef
* - it is the scala.reflect.Selectable.reflectiveSelectable conversion
/** 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.
*/
def checkImplicitConversionUseOK(sym: Symbol, pos: SrcPos)(using Context): Unit =
if (sym.exists) {
val conv =
if (sym.isOneOf(GivenOrImplicit) || sym.info.isErroneous) sym
else {
assert(sym.name == nme.apply || ctx.reporter.errorsReported)
sym.owner
}
val conversionOK =
conv.is(Synthetic) ||
sym.info.finalResultType.classSymbols.exists(_.isLinkedWith(conv.owner)) ||
defn.isPredefClass(conv.owner) ||
conv.name == nme.reflectiveSelectable && conv.maybeOwner.maybeOwner.maybeOwner == defn.ScalaPackageClass
if (!conversionOK)
checkFeature(nme.implicitConversions,
i"Use of implicit conversion ${conv.showLocated}", NoSymbol, pos)
}
def checkImplicitConversionUseOK(tree: Tree)(using Context): Unit =
val sym = tree.symbol
if sym.name == nme.apply
&& sym.owner.derivesFrom(defn.ConversionClass)
&& !sym.info.isErroneous
then
def conv = methPart(tree) match
case Select(qual, _) => qual.symbol.orElse(sym.owner)
case _ => sym.owner
checkFeature(nme.implicitConversions,
i"Use of implicit conversion ${conv.showLocated}", NoSymbol, tree.srcPos)

private def infixOKSinceFollowedBy(tree: untpd.Tree): Boolean = tree match {
case _: untpd.Block | _: untpd.Match => true
Expand Down Expand Up @@ -1244,7 +1236,7 @@ trait NoChecking extends ReChecking {
override def checkStable(tp: Type, pos: SrcPos, kind: String)(using Context): Unit = ()
override def checkClassType(tp: Type, pos: SrcPos, traitReq: Boolean, stablePrefixReq: Boolean)(using Context): Type = tp
override def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit = ()
override def checkImplicitConversionUseOK(sym: Symbol, pos: SrcPos)(using Context): Unit = ()
override def checkImplicitConversionUseOK(tree: Tree)(using Context): Unit = ()
override def checkFeasibleParent(tp: Type, pos: SrcPos, where: => String = "")(using Context): Type = tp
override def checkInlineConformant(tpt: Tree, tree: Tree, sym: Symbol)(using Context): Unit = ()
override def checkNoAlphaConflict(stats: List[Tree])(using Context): Unit = ()
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3490,7 +3490,7 @@ class Typer extends Namer
case SearchSuccess(found: ExtMethodApply, _, _) =>
found // nothing to check or adapt for extension method applications
case SearchSuccess(found, _, _) =>
checkImplicitConversionUseOK(found.symbol, tree.srcPos)
checkImplicitConversionUseOK(found)
withoutMode(Mode.ImplicitsEnabled)(readapt(found))
case failure: SearchFailure =>
if (pt.isInstanceOf[ProtoType] && !failure.isAmbiguous) then
Expand Down
3 changes: 2 additions & 1 deletion library/src/scala/Conversion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ package scala
* from two to one.
*/
@java.lang.FunctionalInterface
abstract class Conversion[-T, +U] extends Function1[T, U]
abstract class Conversion[-T, +U] extends Function1[T, U]:
def apply(x: T): U
2 changes: 1 addition & 1 deletion tests/neg-custom-args/impl-conv/A.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package implConv
object A {

implicit def s2i(x: String): Int = Integer.parseInt(x) // error: feature
implicit val i2s: Conversion[Int, String] = _.toString // error: feature
given i2s as Conversion[Int, String] = _.toString // ok

implicit class Foo(x: String) {
def foo = x.length
Expand Down
5 changes: 2 additions & 3 deletions tests/neg-custom-args/impl-conv/B.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package implConv

object B {
import A._
import A.{_, given _}

"".foo

val x: Int = "" // error: feature
val x: Int = "" // ok
val y: String = 1 // error: feature

}
4 changes: 2 additions & 2 deletions tests/neg-custom-args/implicit-conversions-old.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ object Test {
import D._

val x1: A = new B
val x2: B = new A // error under -Xfatal-warnings -feature
val x3: C = new A // error under -Xfatal-warnings -feature
val x2: B = new A // ok, since it's an old-style comversion
val x3: C = new A // ok, since it's an old-style comversion
}
2 changes: 1 addition & 1 deletion tests/neg-custom-args/implicit-conversions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object D {
object Test {
import D.{given _}

val x1: A = new B
val x1: A = new B // error under -Xfatal-warnings -feature
val x2: B = new A // error under -Xfatal-warnings -feature
val x3: C = new A // error under -Xfatal-warnings -feature
}