@@ -17,7 +17,7 @@ package typechecker
1717import scala .annotation .{tailrec , unused }
1818import scala .collection .mutable
1919import scala .reflect .internal .{Chars , TypesStats }
20- import scala .reflect .internal .util .{FreshNameCreator , ListOfNil , Statistics }
20+ import scala .reflect .internal .util .{FreshNameCreator , ListOfNil , Statistics , StringContextStripMarginOps }
2121import scala .tools .nsc .Reporting .{MessageFilter , Suppression , WConf , WarningCategory }
2222import scala .util .chaining ._
2323import mutable .ListBuffer
@@ -884,26 +884,35 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
884884
885885 def warnTree = original orElse tree
886886
887- def warnEtaZero (): Boolean = {
888- if (! settings.warnEtaZero) return true
889- context.warning(tree.pos,
890- s """ An unapplied 0-arity method was eta-expanded (due to the expected type $pt), rather than applied to `()`.
891- |Write ${Apply (warnTree, Nil )} to invoke method ${meth.decodedName}, or change the expected type. """ .stripMargin,
892- WarningCategory .LintEtaZero )
887+ def warnEtaZero (): true = {
888+ if (settings.warnEtaZero) {
889+ context.warning(tree.pos,
890+ s """ An unapplied 0-arity method was eta-expanded (due to the expected type $pt), rather than applied to `()`.
891+ |Write ${Apply (warnTree, Nil )} to invoke method ${meth.decodedName}, or change the expected type. """ .stripMargin,
892+ WarningCategory .LintEtaZero )
893+ }
893894 true
894895 }
895896
896- def warnEtaSam (): Boolean = {
897- if (! settings.warnEtaSam) return true
898- val sam = samOf(pt)
899- val samClazz = sam.owner
900- // TODO: we allow a Java class as a SAM type, whereas Java only allows the @FunctionalInterface on interfaces -- align?
901- if (sam.exists && (! samClazz.hasFlag(JAVA ) || samClazz.hasFlag(INTERFACE )) && ! samClazz.hasAnnotation(definitions.FunctionalInterfaceClass ))
902- context.warning(tree.pos,
903- s """ Eta-expansion performed to meet expected type $pt, which is SAM-equivalent to ${samToFunctionType(pt)},
904- |even though $samClazz is not annotated with `@FunctionalInterface`;
905- |to suppress warning, add the annotation or write out the equivalent function literal. """ .stripMargin,
906- WarningCategory .LintEtaSam )
897+ def warnEtaSam (): true = {
898+ if (settings.warnEtaSam || currentRun.isScala3) {
899+ val sam = samOf(pt)
900+ if (sam.exists) {
901+ val samClazz = sam.owner
902+ val isJavaClass = samClazz.isJava && ! samClazz.isInterface
903+ if (! samClazz.hasAnnotation(definitions.FunctionalInterfaceClass )) {
904+ val ft = samToFunctionType(pt)
905+ val sample = Function (meth.paramss.head.map(ValDef (_)), Apply (meth, meth.paramss.head.map(p => Ident (p.name)): _* ))
906+ val places = Apply (meth, meth.paramss.head.map(_ => Ident (nme.USCOREkw )): _* )
907+ val advice = if (isJavaClass) " " else s " \n $samClazz should be annotated with `@FunctionalInterface` if eta-expansion is desired. "
908+ context.warning(tree.pos,
909+ sm """ Eta-expansion to expected type $pt, which is not a function type but is SAM-convertible to $ft. $advice
910+ |Avoid eta-expansion by writing the function literal ` $sample` or ` $places`.
911+ |This warning can be filtered with `-Wconf:cat=lint-eta-sam`. """ ,
912+ WarningCategory .LintEtaSam )
913+ }
914+ }
915+ }
907916 true
908917 }
909918
0 commit comments