@@ -512,6 +512,80 @@ object Checking {
512
512
}
513
513
}
514
514
515
+ def checkScala2Implicit (sym : Symbol )(using Context ): Unit =
516
+ def migration (msg : Message ) =
517
+ report.errorOrMigrationWarning(msg, sym.srcPos, MigrationVersion .Scala2Implicits )
518
+ def info = sym match
519
+ case sym : ClassSymbol => sym.primaryConstructor.info
520
+ case _ => sym.info
521
+ def paramName = info.firstParamNames match
522
+ case pname :: _ => pname.show
523
+ case _ => " x"
524
+ def paramTypeStr = info.firstParamTypes match
525
+ case pinfo :: _ => pinfo.show
526
+ case _ => " T"
527
+ def toFunctionStr (info : Type ): String = info match
528
+ case ExprType (resType) =>
529
+ i " () => $resType"
530
+ case info : MethodType =>
531
+ i " ( ${ctx.printer.paramsText(info).mkString()}) => ${toFunctionStr(info.resType)}"
532
+ case info : PolyType =>
533
+ i " [ ${ctx.printer.paramsText(info).mkString()}] => ${toFunctionStr(info.resType)}"
534
+ case _ =>
535
+ info.show
536
+
537
+ if sym.isClass then
538
+ migration(
539
+ em """ `implicit` classes are no longer supported. They can usually be replaced
540
+ |by extension methods. Example:
541
+ |
542
+ | extension ( $paramName: $paramTypeStr)
543
+ | // class methods go here, replace `this` by ` $paramName`
544
+ |
545
+ |Alternatively, convert to a regular class and define
546
+ |a given `Conversion` instance into that class. Example:
547
+ |
548
+ | class ${sym.name} ...
549
+ | given Conversion[ $paramTypeStr, ${sym.name}] = ${sym.name}( $paramName)
550
+ |
551
+ | """ )
552
+ else if sym.isOldStyleImplicitConversion(directOnly = true ) then
553
+ migration(
554
+ em """ `implicit` conversion methods are no longer supported. They can usually be
555
+ |replaced by given instances of class `Conversion`. Example:
556
+ |
557
+ | given Conversion[ $paramTypeStr, ${sym.info.finalResultType}] = $paramName => ...
558
+ |
559
+ | """ )
560
+ else if sym.is(Method ) then
561
+ if ! sym.isOldStyleImplicitConversion(forImplicitClassOnly = true ) then
562
+ migration(
563
+ em """ `implicit` defs are no longer supported, use a `given` clause instead. Example:
564
+ |
565
+ | given ${sym.name}: ${toFunctionStr(sym.info)} = ...
566
+ |
567
+ | """ )
568
+ else if sym.isTerm && ! sym.isOneOf(TermParamOrAccessor ) then
569
+ def note =
570
+ if sym.is(Lazy ) then " "
571
+ else
572
+ i """
573
+ |
574
+ |Note: given clauses are evaluated lazily unless the right hand side is
575
+ |a simple reference. If eager evaluation of the value's right hand side
576
+ |is important, you can define a regular val and a given instance like this:
577
+ |
578
+ | val ${sym.name} = ...
579
+ | given ${sym.info} = ${sym.name}"""
580
+
581
+ migration(
582
+ em """ `implicit` vals are no longer supported, use a `given` clause instead. Example:
583
+ |
584
+ | given ${sym.name}: ${sym.info} = ... $note
585
+ |
586
+ | """ )
587
+ end checkScala2Implicit
588
+
515
589
/** Check that symbol's definition is well-formed. */
516
590
def checkWellFormed (sym : Symbol )(using Context ): Unit = {
517
591
def fail (msg : Message ) = report.error(msg, sym.srcPos)
@@ -537,11 +611,11 @@ object Checking {
537
611
fail(ParamsNoInline (sym.owner))
538
612
if sym.isInlineMethod && ! sym.is(Deferred ) && sym.allOverriddenSymbols.nonEmpty then
539
613
checkInlineOverrideParameters(sym)
540
- if ( sym.is(Implicit )) {
614
+ if sym.is(Implicit ) then
541
615
assert(! sym.owner.is(Package ), s " top-level implicit $sym should be wrapped by a package after typer " )
542
616
if sym.isType && (! sym.isClass || sym.is(Trait )) then
543
617
fail(TypesAndTraitsCantBeImplicit ())
544
- }
618
+ else checkScala2Implicit(sym)
545
619
if sym.is(Transparent ) then
546
620
if sym.isType then
547
621
if ! sym.isExtensibleClass then fail(em " `transparent` can only be used for extensible classes and traits " )
0 commit comments