diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index da918c0f31b6..b242ce3d3979 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -531,19 +531,6 @@ trait ContextErrors extends splain.SplainErrors { setError(tree) } - //typedEta - private def mkUnderscoreNullaryEtaMessage(what: String) = - s"Methods without a parameter list and by-name params can $what be converted to functions as `m _`, " + - "write a function literal `() => m` instead" - - final val UnderscoreNullaryEtaWarnMsg = mkUnderscoreNullaryEtaMessage("no longer") - final val UnderscoreNullaryEtaErrorMsg = mkUnderscoreNullaryEtaMessage("not") - - def UnderscoreNullaryEtaError(tree: Tree, actions: List[CodeAction]) = { - issueNormalTypeError(tree, UnderscoreNullaryEtaErrorMsg, actions) - setError(tree) - } - def UnderscoreEtaError(tree: Tree) = { issueNormalTypeError(tree, "_ must follow method; cannot follow " + tree.tpe) setError(tree) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index a714622eda4d..bdb8efc29345 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -80,6 +80,7 @@ abstract class RefChecks extends Transform { } class RefCheckTransformer(unit: CompilationUnit) extends AstTransformer { + private final val indent = " " var localTyper: analyzer.Typer = typer var currentApplication: Tree = EmptyTree @@ -252,21 +253,27 @@ abstract class RefChecks extends Transform { private def checkAllOverrides(clazz: Symbol, typesOnly: Boolean = false): Unit = { val self = clazz.thisType - case class MixinOverrideError(member: Symbol, msg: String) + case class MixinOverrideError(member: Symbol, msg: String, actions: List[CodeAction], s3Migration: Boolean) val mixinOverrideErrors = new ListBuffer[MixinOverrideError]() + def issue(pos: Position, msg: String, actions: List[CodeAction], s3Migration: Boolean) = + if (s3Migration) runReporting.warning(pos, msg, WarningCategory.Scala3Migration, currentOwner, actions) + else runReporting.error(pos, msg, actions) + def printMixinOverrideErrors(): Unit = { mixinOverrideErrors.toList match { case List() => - case List(MixinOverrideError(_, msg)) => - reporter.error(clazz.pos, msg) - case MixinOverrideError(member, msg) :: others => + case List(MixinOverrideError(_, msg, actions, s3Migration)) => + issue(clazz.pos, msg, actions, s3Migration) + case MixinOverrideError(member, msg, actions, s3Migration) :: others => val others1 = others.map(_.member.name.decode).filter(member.name.decode != _).distinct - reporter.error( + issue( clazz.pos, - msg+(if (others1.isEmpty) "" - else ";\n other members with override errors are: "+(others1 mkString ", "))) + if (others1.isEmpty) msg + else s"$msg;\n other members with override errors are: ${others1.mkString(", ")}", + actions, + s3Migration) } } @@ -297,63 +304,74 @@ abstract class RefChecks extends Transform { val memberClass = member.owner val otherClass = other.owner - // debuglog(s"Checking validity of ${member.fullLocationString} overriding ${other.fullLocationString}") + // debuglog(s"Checking validity of ${member.fullLocationString} overriding ${other.fullLocationString}") def noErrorType = !pair.isErroneous def isRootOrNone(sym: Symbol) = sym != null && sym.isRoot || sym == NoSymbol - def isNeitherInClass = memberClass != clazz && otherClass != clazz + val isMemberClass = memberClass == clazz + def isNeitherInClass = !isMemberClass && otherClass != clazz + + /** Emit an error if member is owned by current class, using the member position. + * Otherwise, accumulate the error, to be emitted after other messages, using the class position. + */ + def emitOverrideError(fullmsg: String, actions: List[CodeAction] = Nil, s3Migration: Boolean = false): Unit = + if (isMemberClass) issue(member.pos, fullmsg, actions, s3Migration) + else mixinOverrideErrors += MixinOverrideError(member, fullmsg, actions, s3Migration) - val indent = " " def overriddenWithAddendum(msg: String, foundReq: Boolean = settings.isDebug): String = { val isConcreteOverAbstract = - (otherClass isSubClass memberClass) && other.isDeferred && !member.isDeferred + otherClass.isSubClass(memberClass) && other.isDeferred && !member.isDeferred val addendum = if (isConcreteOverAbstract) - s";\n${indent}(note that ${infoStringWithLocation(other)} is abstract,\n" + - s"${indent}and is therefore overridden by concrete ${infoStringWithLocation(member)})" + sm"""|; + |${indent}(note that ${infoStringWithLocation(other)} is abstract, + |${indent}and is therefore overridden by concrete ${infoStringWithLocation(member)})""" else if (foundReq) { def info(sym: Symbol) = self.memberInfo(sym) match { case tp if sym.isGetter || sym.isValue && !sym.isMethod => tp.resultType case tp => tp } analyzer.foundReqMsg(info(member), info(other)) } else "" + val msg1 = if (!msg.isEmpty) s"\n$indent$msg" else msg - infoStringWithLocation(other) + (if (msg.isEmpty) "" else s"\n$indent") + msg + addendum + s"${infoStringWithLocation(other)}${msg1}${addendum}" } - def emitOverrideError(fullmsg: String, actions: List[CodeAction] = Nil): Unit = { - if (memberClass == clazz) runReporting.error(member.pos, fullmsg, actions) - else mixinOverrideErrors += MixinOverrideError(member, fullmsg) - } - - def overrideErrorWithMemberInfo(msg: String, actions: List[CodeAction] = Nil): Unit = - if (noErrorType) emitOverrideError(msg + "\n" + overriddenWithAddendum(if (member.owner == clazz) "" else s"with ${infoString(member)}"), actions) def overrideError(msg: String): Unit = if (noErrorType) emitOverrideError(msg) - def overrideTypeError(): Unit = { + def getWithIt = if (isMemberClass) "" else s"with ${infoString(member)}" + + def overrideErrorWithMemberInfo(msg: String, actions: List[CodeAction] = Nil, s3Migration: Boolean = false): Unit = + if (noErrorType) emitOverrideError(s"${msg}\n${overriddenWithAddendum(getWithIt)}", actions, s3Migration) + + def overrideErrorOrNullaryWarning(msg: String, actions: List[CodeAction]): Unit = if (isMemberClass || !member.owner.isSubClass(other.owner)) + if (currentRun.isScala3) + overrideErrorWithMemberInfo(msg, actions, s3Migration = true) + else if (isMemberClass) + refchecksWarning(member.pos, msg, WarningCategory.OtherNullaryOverride, actions) + else + refchecksWarning(clazz.pos, msg, WarningCategory.OtherNullaryOverride, actions) + + def overrideTypeError(): Unit = if (member.isModule && other.isModule) - overrideError(s"overriding ${other.fullLocationString} with ${member.fullLocationString}:\n" + - "an overriding object must conform to the overridden object's class bound" + - analyzer.foundReqMsg(pair.lowClassBound, pair.highClassBound)) + overrideError(sm"""|overriding ${other.fullLocationString} with ${member.fullLocationString}: + |an overriding object must conform to the overridden object's class bound${ + analyzer.foundReqMsg(pair.lowClassBound, pair.highClassBound)}""") else { val needSameType = !other.isDeferred && other.isAliasType - val msg = - (if (member.owner == clazz) "" else s"with ${infoString(member)}") + - (if (needSameType) " (Equivalent type required when overriding a type alias.)" else "") - - overrideError("incompatible type in overriding\n" + overriddenWithAddendum(msg, foundReq = !needSameType)) + val msg = s"${getWithIt}${if (needSameType) " (Equivalent type required when overriding a type alias.)" else ""}" + overrideError(sm"""|incompatible type in overriding + |${overriddenWithAddendum(msg, foundReq = !needSameType)}""") } - } - def overrideErrorConcreteMissingOverride() = { - if (isNeitherInClass && !(otherClass isSubClass memberClass)) + def overrideErrorConcreteMissingOverride() = + if (isNeitherInClass && !otherClass.isSubClass(memberClass)) emitOverrideError(sm"""|$clazz inherits conflicting members: |$indent${infoStringWithLocation(other)} and |$indent${infoStringWithLocation(member)} |$indent(note: this can be resolved by declaring an `override` in $clazz.)""") else overrideErrorWithMemberInfo("`override` modifier required to override concrete member:") - } def weakerAccessError(advice: String): Unit = overrideError(sm"""|weaker access privileges in overriding @@ -390,90 +408,93 @@ abstract class RefChecks extends Transform { !isRootOrNone(ob) && (ob.hasTransOwner(mb) || companionBoundaryOK) } @inline def otherIsJavaProtected = other.isJavaDefined && other.isProtected - def isOverrideAccessOK = + val isOverrideAccessOK = member.isPublic || // member is public, definitely same or relaxed access protectedOK && // if o is protected, so is m (accessBoundaryOK || // m relaxes o's access boundary otherIsJavaProtected // overriding a protected java member, see #3946 #12349 ) - if (!isOverrideAccessOK) { + if (!isOverrideAccessOK) overrideAccessError() - } else if (other.isClass) { + else if (other.isClass) overrideErrorWithMemberInfo("class definitions cannot be overridden:") - } else if (!other.isDeferred && member.isClass) { + else if (!other.isDeferred && member.isClass) overrideErrorWithMemberInfo("classes can only override abstract types; cannot override:") - } else if (other.isEffectivelyFinal) { // (1.2) + else if (other.isEffectivelyFinal) // (1.2) overrideErrorWithMemberInfo("cannot override final member:") - } else { + else { // In Java, the OVERRIDE flag is implied val memberOverrides = member.isAnyOverride || (member.isJavaDefined && !member.isDeferred) // Concrete `other` requires `override` for `member`. - // Synthetic exclusion for (at least) default getters, fixes scala/bug#5178. We cannot assign the OVERRIDE flag to - // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket. - if (!(memberOverrides || other.isDeferred) && !member.isSynthetic) { + // Synthetic exclusion for (at least) default getters, fixes scala/bug#5178. + // We cannot assign the OVERRIDE flag to the default getter: + // one default getter might sometimes override, sometimes not. Example in comment on ticket. + if (!memberOverrides && !other.isDeferred && !member.isSynthetic) overrideErrorConcreteMissingOverride() - } else if (other.isAbstractOverride && other.isIncompleteIn(clazz) && !member.isAbstractOverride) { + else if (other.isAbstractOverride && other.isIncompleteIn(clazz) && !member.isAbstractOverride) overrideErrorWithMemberInfo("`abstract override` modifiers required to override:") - } - else if (memberOverrides && (other hasFlag ACCESSOR) && !(other hasFlag STABLE | DEFERRED)) { + else if (memberOverrides && other.hasFlag(ACCESSOR) && !other.hasFlag(STABLE | DEFERRED)) // TODO: this is not covered by the spec. overrideErrorWithMemberInfo("mutable variable cannot be overridden:") - } else if (memberOverrides && - !(memberClass.thisType.baseClasses exists (_ isSubClass otherClass)) && + !memberClass.thisType.baseClasses.exists(_.isSubClass(otherClass)) && !member.isDeferred && !other.isDeferred && - intersectionIsEmpty(member.extendedOverriddenSymbols, other.extendedOverriddenSymbols)) { + intersectionIsEmpty(member.extendedOverriddenSymbols, other.extendedOverriddenSymbols)) overrideErrorWithMemberInfo("cannot override a concrete member without a third member that's overridden by both " + "(this rule is designed to prevent accidental overrides)") - } else if (other.isStable && !member.isStable) { // (1.4) + else if (other.isStable && !member.isStable) // (1.4) overrideErrorWithMemberInfo("stable, immutable value required to override:") - } else if (member.isValue && member.isLazy && - other.isValue && other.hasFlag(STABLE) && !(other.isDeferred || other.isLazy)) { + else if (member.isValue && member.isLazy && + other.isValue && other.hasFlag(STABLE) && !other.isDeferred && !other.isLazy) overrideErrorWithMemberInfo("concrete non-lazy value cannot be overridden:") - } else if (other.isValue && other.isLazy && - member.isValue && !member.isLazy) { + else if (other.isValue && other.isLazy && member.isValue && !member.isLazy) overrideErrorWithMemberInfo("value must be lazy when overriding concrete lazy value:") - } else if (other.isDeferred && member.isTermMacro && member.extendedOverriddenSymbols.forall(_.isDeferred)) { // (1.9) + else if (other.isDeferred && member.isTermMacro && member.extendedOverriddenSymbols.forall(_.isDeferred)) // (1.9) overrideErrorWithMemberInfo("macro cannot override abstract method:") - } else if (other.isTermMacro && !member.isTermMacro) { // (1.10) + else if (other.isTermMacro && !member.isTermMacro) // (1.10) overrideErrorWithMemberInfo("macro can only be overridden by another macro:") - } else { + else { checkOverrideTypes() // Don't bother users with deprecations caused by classes they inherit. // Only warn for the pair that has one leg in `clazz`. - if (clazz == memberClass) checkOverrideDeprecated() + if (isMemberClass) checkOverrideDeprecated() def javaDetermined(sym: Symbol) = sym.isJavaDefined || isUniversalMember(sym) - if (member.hasAttachment[NullaryOverrideAdapted.type]) { - def exempt() = member.overrides.exists(sym => sym.isJavaDefined || isUniversalMember(sym)) - if (!exempt()) { - val msg = "method without a parameter list overrides a method with a single empty one" - val namePos = member.pos.focus.withEnd(member.pos.point + member.decodedName.length) - val action = - if (currentUnit.sourceAt(namePos) == member.decodedName) - runReporting.codeAction("add empty parameter list", namePos.focusEnd, "()", msg) - else Nil - if (currentRun.isScala3) - overrideErrorWithMemberInfo(msg, action) - else - refchecksWarning(member.pos, msg, WarningCategory.OtherNullaryOverride, action) - } + def exempted = javaDetermined(member) || member.overrides.exists(javaDetermined) + // warn that nilary member matched nullary other, so either it was adapted by namer or will be silently mixed in by mixin + def warnAdaptedNullaryOverride(): Unit = { + val named = if (isMemberClass) "" else s" (${member.fullLocationString})" + val msg = s"method$named without a parameter list overrides a method with a single empty one" + val namePos = member.pos + val action = + if (namePos.isDefined && currentUnit.sourceAt(namePos) == member.decodedName) + runReporting.codeAction("add empty parameter list", namePos.focusEnd, "()", msg) + else Nil + overrideErrorOrNullaryWarning(msg, action) } - else if (other.paramss.isEmpty && !member.paramss.isEmpty && - !javaDetermined(member) && !member.overrides.exists(javaDetermined) && - !member.hasAnnotation(BeanPropertyAttr) && !member.hasAnnotation(BooleanBeanPropertyAttr) && - member.pos.isDefined // scala/bug#12851 - ) { - val msg = "method with a single empty parameter list overrides method without any parameter list" - val namePos = member.pos.focus.withEnd(member.pos.point + member.decodedName.length) + def warnExtraParens(): Unit = { + val named = if (isMemberClass) "" else s" (${member.fullLocationString})" + val msg = s"method$named with a single empty parameter list overrides method without any parameter list" + val namePos = member.pos val action = - if (currentUnit.sourceAt(namePos) == member.decodedName) + if (namePos.isDefined && currentUnit.sourceAt(namePos) == member.decodedName) runReporting.codeAction("remove empty parameter list", namePos.focusEnd.withEnd(namePos.end + 2), "", msg, expected = Some(("()", currentUnit))) else Nil - if (currentRun.isScala3) - overrideErrorWithMemberInfo(msg, action) - else - refchecksWarning(member.pos, msg, WarningCategory.OtherNullaryOverride, action) + overrideErrorOrNullaryWarning(msg, action) + } + if (member.hasAttachment[NullaryOverrideAdapted.type]) { + if (!exempted) + warnAdaptedNullaryOverride() + } + else if (member.paramLists.isEmpty) { + // NullaryOverrideAdapted is only added to symbols being compiled, so check for a mismatch + // if both symbols are mixed in from the classpath + if (!member.isStable && other.paramLists.nonEmpty && !exempted && !other.isJavaDefined) + warnAdaptedNullaryOverride() + } + else if (other.paramLists.isEmpty) { + if (!exempted && !member.hasAnnotation(BeanPropertyAttr) && !member.hasAnnotation(BooleanBeanPropertyAttr)) + warnExtraParens() } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 571cb15e424b..8c07f451b4c5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4016,7 +4016,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper return finish(ErroneousAnnotation) } if (currentRun.isScala3 && (/*annTypeSym.eq(SpecializedClass) ||*/ annTypeSym.eq(ElidableMethodClass))) - context.deprecationWarning(ann.pos, annTypeSym, s"@${annTypeSym.fullNameString} is ignored in Scala 3", "2.13.12") + context.warning(ann.pos, s"@${annTypeSym.fullNameString} is ignored in Scala 3", WarningCategory.Scala3Migration) /* Calling constfold right here is necessary because some trees (negated * floats and literals in particular) are not yet folded. @@ -4972,19 +4972,22 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val result = typed(Function(Nil, methodValue) setSymbol funSym setPos pos, mode, pt) + val msg = "Methods without a parameter list and by-name params can no longer be converted to functions as `m _`, " + + "write a function literal `() => m` instead" + val action = { val etaPos = pos.withEnd(pos.end + 2) if (currentUnit.sourceAt(etaPos).endsWith(" _")) - runReporting.codeAction("replace by function literal", etaPos, s"() => ${currentUnit.sourceAt(pos)}", UnderscoreNullaryEtaWarnMsg) + runReporting.codeAction("replace by function literal", etaPos, s"() => ${currentUnit.sourceAt(pos)}", msg) else Nil } - if (currentRun.isScala3) { - UnderscoreNullaryEtaError(methodValue, action) - } else { - context.deprecationWarning(pos, NoSymbol, UnderscoreNullaryEtaWarnMsg, "2.13.2", action) - result - } + if (currentRun.isScala3) + context.warning(pos, msg, WarningCategory.Scala3Migration, action) + else + context.deprecationWarning(pos, NoSymbol, msg, "2.13.2", action) + + result case ErrorType => methodValue diff --git a/test/files/neg/deprecated-annots.check b/test/files/neg/deprecated-annots.check index e9f6237a039b..b85c663b1996 100644 --- a/test/files/neg/deprecated-annots.check +++ b/test/files/neg/deprecated-annots.check @@ -1,6 +1,6 @@ -deprecated-annots.scala:9: warning: @scala.annotation.elidable is ignored in Scala 3 +deprecated-annots.scala:9: error: @scala.annotation.elidable is ignored in Scala 3 +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=D @annotation.elidable(42) ^ -error: No warnings can be incurred under -Werror. -1 warning 1 error diff --git a/test/files/neg/nullary-override-3a.check b/test/files/neg/nullary-override-3a.check index ed95cbab30a2..bda1008b04f8 100644 --- a/test/files/neg/nullary-override-3a.check +++ b/test/files/neg/nullary-override-3a.check @@ -1,13 +1,25 @@ nullary-override-3a.scala:4: error: method with a single empty parameter list overrides method without any parameter list def x: Int (defined in class A) [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=B class B extends A { override def x(): Int = 4 } ^ nullary-override-3a.scala:16: error: method with a single empty parameter list overrides method without any parameter list def x: String (defined in trait T1) [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=Mix12b class Mix12b extends T1 with T2 { override def x() = "12b" } ^ +nullary-override-3a.scala:18: error: method without a parameter list overrides a method with a single empty one +def x(): String (defined in trait T2) [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=Mix21a +class Mix21a extends T2 with T1 { override def x = "21a" } + ^ nullary-override-3a.scala:19: error: method with a single empty parameter list overrides method without any parameter list def x: String (defined in trait T1) [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=Mix21b class Mix21b extends T2 with T1 { override def x() = "21b" } ^ -3 errors +4 errors diff --git a/test/files/neg/nullary-override-3b.check b/test/files/neg/nullary-override-3b.check index e4e66eca16f0..3877313510f9 100644 --- a/test/files/neg/nullary-override-3b.check +++ b/test/files/neg/nullary-override-3b.check @@ -1,9 +1,13 @@ nullary-override-3b.scala:6: error: method without a parameter list overrides a method with a single empty one def x(): Int (defined in class P) [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=Q class Q extends P { override def x: Int = 4 } ^ nullary-override-3b.scala:11: error: method without a parameter list overrides a method with a single empty one def x(): String (defined in trait T2) [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=Mix12a class Mix12a extends T1 with T2 { override def x = "12a" } ^ 2 errors diff --git a/test/files/neg/nullary-override.check b/test/files/neg/nullary-override.check index 8b3d9b54c5a4..1158dd272ec1 100644 --- a/test/files/neg/nullary-override.check +++ b/test/files/neg/nullary-override.check @@ -10,9 +10,12 @@ class Mix12a extends T1 with T2 { override def x = "12a" } nullary-override.scala:37: warning: method with a single empty parameter list overrides method without any parameter list [quickfixable] class Mix12b extends T1 with T2 { override def x() = "12b" } ^ +nullary-override.scala:39: warning: method without a parameter list overrides a method with a single empty one [quickfixable] +class Mix21a extends T2 with T1 { override def x = "21a" } + ^ nullary-override.scala:40: warning: method with a single empty parameter list overrides method without any parameter list [quickfixable] class Mix21b extends T2 with T1 { override def x() = "21b" } ^ error: No warnings can be incurred under -Werror. -5 warnings +6 warnings 1 error diff --git a/test/files/neg/t12851b.check b/test/files/neg/t12851b.check new file mode 100644 index 000000000000..27f1289f3f99 --- /dev/null +++ b/test/files/neg/t12851b.check @@ -0,0 +1,9 @@ +C_2.scala:2: warning: method (method f in trait T2) with a single empty parameter list overrides method without any parameter list +class C extends T1 with T2 + ^ +C_2.scala:2: warning: method (method g in trait T2) without a parameter list overrides a method with a single empty one +class C extends T1 with T2 + ^ +error: No warnings can be incurred under -Werror. +2 warnings +1 error diff --git a/test/files/neg/t12851b/C_2.scala b/test/files/neg/t12851b/C_2.scala new file mode 100644 index 000000000000..c6d4b70f2960 --- /dev/null +++ b/test/files/neg/t12851b/C_2.scala @@ -0,0 +1,2 @@ +// scalac: -Werror +class C extends T1 with T2 diff --git a/test/files/neg/t12851b/T_1.scala b/test/files/neg/t12851b/T_1.scala new file mode 100644 index 000000000000..e43a11ab2eb8 --- /dev/null +++ b/test/files/neg/t12851b/T_1.scala @@ -0,0 +1,11 @@ + +trait T1 { + def f: Int + def g(): Int + def v(): Int +} +trait T2 { + def f() = 42 + def g = 42 + val v = 42 +} diff --git a/test/files/neg/t7187-3.check b/test/files/neg/t7187-3.check index e7ccfb53ea20..cd6125f0e9f3 100644 --- a/test/files/neg/t7187-3.check +++ b/test/files/neg/t7187-3.check @@ -13,12 +13,14 @@ t7187-3.scala:16: error: type mismatch; required: SamZero val t2Sam: SamZero = m2 // error, nilary methods don't eta-expand to SAM types ^ -t7187-3.scala:27: error: Methods without a parameter list and by-name params can not be converted to functions as `m _`, write a function literal `() => m` instead [quickfixable] - val t7 = m1 _ // error: eta-expanding a nullary method - ^ t7187-3.scala:14: warning: An unapplied 0-arity method was eta-expanded (due to the expected type () => Any), rather than applied to `()`. Write m2() to invoke method m2, or change the expected type. val t2: () => Any = m2 // eta-expanded with lint warning ^ +t7187-3.scala:27: error: Methods without a parameter list and by-name params can no longer be converted to functions as `m _`, write a function literal `() => m` instead [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=EtaExpand214.t7 + val t7 = m1 _ // error: eta-expanding a nullary method + ^ 1 warning 4 errors diff --git a/test/files/neg/t7187-deprecation.check b/test/files/neg/t7187-deprecation.check index 33a935ce64d7..5b93c40b1c86 100644 --- a/test/files/neg/t7187-deprecation.check +++ b/test/files/neg/t7187-deprecation.check @@ -13,14 +13,16 @@ t7187-deprecation.scala:20: error: type mismatch; required: SamZero val t2Sam: SamZero = m2 // error, nilary methods don't eta-expand to SAM types ^ -t7187-deprecation.scala:31: error: Methods without a parameter list and by-name params can not be converted to functions as `m _`, write a function literal `() => m` instead [quickfixable] - val t7 = m1 _ // error: eta-expanding a nullary method - ^ t7187-deprecation.scala:24: warning: Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method m2, or remove the empty argument list from its definition (Java-defined methods are exempt). In Scala 3, an unapplied method like this will be eta-expanded into a function. [quickfixable] val t5 = m2 // warn: apply, ()-insertion ^ +t7187-deprecation.scala:31: error: Methods without a parameter list and by-name params can no longer be converted to functions as `m _`, write a function literal `() => m` instead [quickfixable] +Scala 3 migration messages are errors under -Xsource:3. Use -Wconf / @nowarn to filter them or add -Xmigration to demote them to warnings. +Applicable -Wconf / @nowarn filters for this fatal warning: msg=, cat=scala3-migration, site=EtaExpand214.t7 + val t7 = m1 _ // error: eta-expanding a nullary method + ^ t7187-deprecation.scala:40: warning: Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method boom, or remove the empty argument list from its definition (Java-defined methods are exempt). In Scala 3, an unapplied method like this will be eta-expanded into a function. [quickfixable] diff --git a/test/files/pos/t12851c/ScalaNumber.java b/test/files/pos/t12851c/ScalaNumber.java new file mode 100644 index 000000000000..5a6a8a7c65f5 --- /dev/null +++ b/test/files/pos/t12851c/ScalaNumber.java @@ -0,0 +1,20 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.math; + +/** A marker class for Number types introduced by Scala + */ +public abstract class ScalaNumber extends java.lang.Number { + protected abstract boolean isWhole(); + public abstract Object underlying(); +} diff --git a/test/files/pos/t12851c/ScalaNumericConversions.scala b/test/files/pos/t12851c/ScalaNumericConversions.scala new file mode 100644 index 000000000000..c53f2f225aa8 --- /dev/null +++ b/test/files/pos/t12851c/ScalaNumericConversions.scala @@ -0,0 +1,30 @@ +//> using option -Werror +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package math + +/** A slightly more specific conversion trait for classes which + * extend ScalaNumber (which excludes value classes.) + */ +trait ScalaNumericConversions extends ScalaNumber with ScalaNumericAnyConversions { + def underlying: Object +} + +/** Conversions which present a consistent conversion interface + * across all the numeric types, suitable for use in value classes. + */ +trait ScalaNumericAnyConversions extends Any { + /** @return `'''true'''` if this number has no decimal component, `'''false'''` otherwise. */ + def isWhole: Boolean +}