Right-associative infix operations and match expression precedence surprise

It seems that a match expression does not have precedence to the right of a right-associative operation (checked it both in Scala 2 and 3):

sealed trait Dir
case object Left extends Dir
case object Right extends Dir

implicit class Ext(arg: Int) {
  def := (arg2: Int): Unit = ???
}

object Test {
  val dir: Dir = ???
  val x: Int = ???
  
  x := dir match { //error
    case Left => 2
    case Right => 4
  }
}

So the compiler does (x := dir) match ... instead of x := (dir match ...).
I’m not an expert in understanding the parser spec. Is this the expected behavior? I found it incredibly surprising.

Isn’t := left-associative ?
And =: would be right-associative

Yes, I made several tests. Pasted the wrong example. For right associative it’s a different error, but still an error.

In any case, even without right-associativity, assignment operators should have the lowest priority nonetheless, no? How can match have a lower priority to an assignment?

https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html

Expr1        ::=  
               ...
               |  [SimpleExpr ‘.’] id ‘=’ Expr
               |  PostfixExpr
               |  PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’ // more specific
PostfixExpr  ::=  InfixExpr ...
InfixExpr    ::=  PrefixExpr
               |  InfixExpr id [nl] InfixExpr // a op b

From this it seems the regular assignment = has a slightly higher priority than the match (both are Expr1, but the assignment comes before), but this is not the case of infix expressions (InfixExpr), even if the operator contains the = symbol (because it simply isn’t checked)

This is the motivation for dotted match

scala> 1 + 2.match { case i => i * 2 }
val res0: Int = 5

though match is not an operator or member.

In Scala 2 the left operand is postfix:

scala> "hello" length match { case i => i * 2 }
val res0: Int = 10

Yeah, I figured out there could be working code that cannot allow changing the precedence.

However, I am considering creating a SIP to allow an if after an infix operator. It cirrently fails to compile and ai see no reason why not to allow it.

There is a suspended PR for indented infix operand.

My first reaction was that it is quite baroque (and I love baroque), but since I’ve learned a bit more about indentation (and used it more), I think it will be a feature that in retrospect we could never do without.

It’s not the same SIP. What you referenced still required an indentation before the if and did other stuff. I just want to wite something like val x = 1 + if cond then 2 else 3.