diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index b482afc5e9b3..7b2127bfea95 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2608,10 +2608,10 @@ class AnonymousInstanceCannotBeEmpty(impl: untpd.Template)(using Context) |""" } -class ModifierNotAllowedForDefinition(flag: Flag)(using Context) +class ModifierNotAllowedForDefinition(flag: Flag, explanation: String = "")(using Context) extends SyntaxMsg(ModifierNotAllowedForDefinitionID) { def msg(using Context) = i"Modifier ${hl(flag.flagsString)} is not allowed for this definition" - def explain(using Context) = "" + def explain(using Context) = explanation } class RedundantModifier(flag: Flag)(using Context) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 7ca99df2bea3..020a09f3c17c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -561,6 +561,8 @@ object Checking { fail(CannotHaveSameNameAs(sym, cls, CannotHaveSameNameAs.CannotBeOverridden)) sym.setFlag(Private) // break the overriding relationship by making sym Private } + if sym.isWrappedToplevelDef && !sym.isType && sym.flags.is(Infix, butNot = Extension) then + fail(ModifierNotAllowedForDefinition(Flags.Infix, s"A top-level ${sym.showKind} cannot be infix.")) checkApplicable(Erased, !sym.isOneOf(MutableOrLazy, butNot = Given) && !sym.isType || sym.isClass) checkCombination(Final, Open) diff --git a/tests/neg/i17738-toplevel-infix.check b/tests/neg/i17738-toplevel-infix.check new file mode 100644 index 000000000000..a4946e7afb97 --- /dev/null +++ b/tests/neg/i17738-toplevel-infix.check @@ -0,0 +1,45 @@ +-- [E156] Syntax Error: tests/neg/i17738-toplevel-infix.scala:14:10 ---------------------------------------------------- +14 |infix val toplevelVal = ??? // error + | ^ + | Modifier infix is not allowed for this definition + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A top-level value cannot be infix. + -------------------------------------------------------------------------------------------------------------------- +-- [E156] Syntax Error: tests/neg/i17738-toplevel-infix.scala:15:10 ---------------------------------------------------- +15 |infix var toplevelVar = ??? // error + | ^ + | Modifier infix is not allowed for this definition + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A top-level variable cannot be infix. + -------------------------------------------------------------------------------------------------------------------- +-- [E156] Syntax Error: tests/neg/i17738-toplevel-infix.scala:16:10 ---------------------------------------------------- +16 |infix def toplevelDef = ??? // error + | ^ + | Modifier infix is not allowed for this definition + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A top-level method cannot be infix. + -------------------------------------------------------------------------------------------------------------------- +-- [E156] Syntax Error: tests/neg/i17738-toplevel-infix.scala:17:12 ---------------------------------------------------- +17 |infix given toplevelGiven: Int = ??? // error + | ^ + | Modifier infix is not allowed for this definition + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A top-level given instance cannot be infix. + -------------------------------------------------------------------------------------------------------------------- +-- [E156] Syntax Error: tests/neg/i17738-toplevel-infix.scala:18:19 ---------------------------------------------------- +18 |infix implicit val toplevelImplicit: Int = ??? // error + | ^ + | Modifier infix is not allowed for this definition + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A top-level value cannot be infix. + -------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i17738-toplevel-infix.scala b/tests/neg/i17738-toplevel-infix.scala new file mode 100644 index 000000000000..a67ef9618446 --- /dev/null +++ b/tests/neg/i17738-toplevel-infix.scala @@ -0,0 +1,18 @@ +// scalac: -explain +infix type A[b, a] = Nothing + +infix type B[b, a] = b match { + case Int => a +} + +infix class C[A, B] +infix trait D[A, B] + +extension (x: Boolean) + infix def or (y: => Boolean) = x || y + +infix val toplevelVal = ??? // error +infix var toplevelVar = ??? // error +infix def toplevelDef = ??? // error +infix given toplevelGiven: Int = ??? // error +infix implicit val toplevelImplicit: Int = ??? // error