Skip to content
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

fix: disallow toplevel infix definitions for vals, vars, givens, methods and implicits #17994

Merged
merged 10 commits into from
Jul 13, 2023
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2551,10 +2551,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)
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
45 changes: 45 additions & 0 deletions tests/neg/i17738-toplevel-infix.check
Original file line number Diff line number Diff line change
@@ -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.
--------------------------------------------------------------------------------------------------------------------
18 changes: 18 additions & 0 deletions tests/neg/i17738-toplevel-infix.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// scalac: -explain
mbovel marked this conversation as resolved.
Show resolved Hide resolved
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