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

Add spec section for given patterns reflecting existing semantics #19723

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

yilinwei
Copy link
Contributor

This needs #19718 to test locally from a fresh docker build.


A _given pattern_ introduces an _anonymous given instance_ of the _type_ matched by `TypePat` to the scope of the clause that a given pattern occurs _within_.

The rules for the _name_ synthesized for each anonymous instance is defined in the reference. If multiple names synthesized by the compiler are _not_ unique, this will result in an error.
Copy link
Contributor Author

@yilinwei yilinwei Feb 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not put a link here, because the implicit section has not been updated to reflect given/using yet and I do not know whether I should link to https://docs.scala-lang.org/scala3/reference/contextual/relationship-implicits.html.

@sjrd sjrd self-assigned this Feb 18, 2024
@@ -17,6 +17,8 @@ chapter: 8
| Pattern3
Pattern3 ::= SimplePattern
| SimplePattern {id [nl] SimplePattern}
| GivenPattern
GivenPattern ::= ‘given’ TypePat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parser considers that this a case of SimplePattern:
https://github.com/lampepfl/dotty/blob/7f410aa1b5cbb38dc4c51da0b5772c7babfaabf0/compiler/src/dotty/tools/dotc/parsing/Parsers.scala#L3026

Also, we should update docs/_docs/internals/syntax.md at the same time, to keep them in sync.

GivenPattern ::= TypePat
```

A _given pattern_ introduces an _anonymous given instance_ of the _type_ matched by `TypePat` to the scope of the clause that a given pattern occurs _within_.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what the last part of the sentence means, starting from "to the scope". It does not appear to be grammatically correct, or it's grammatically ambiguous at best. Rephrase?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the corresponding scrutinee is not statically known to have the type TypePat? Is that a compile error or a no-match at run-time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sjrd I was trying to refer to the scope of the case clause - is the term local scope fine?

I think that in the case that the scrutinee is known statically or not statically should be the same as for a TypePat without a given modifier.

Currently,

val x = 1
val y = x match {
  case y: String => ???
}

gives a compile error and

val x = "asd"

def foo[A](a: A): Unit = {
  a match {
    case s: Int=> 1
  }
}

foo(x)

Is a runtime error.


A _given pattern_ introduces an _anonymous given instance_ of the _type_ matched by `TypePat` to the scope of the clause that a given pattern occurs _within_.

The rules for the _name_ synthesized for each anonymous instance is defined in the reference.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, it does not exist in the spec; can I link to the reference in the spec or not?

```scala
def foo: Int =
List(1) match
case given List[_] => summon[List[?]].head // returns `1`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example does not illustrate that we statically receive an Int. Include a val x: Int = summon[List[Int]].head?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, the return type is Int of the function, but I can introduce a val if it would make it clearer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scala 2

scala> List(42) match { case xs @ (_: List[_]) => xs }
val res1: List[Any] = List(42)

scala 3

scala> List(42) match { case xs @ (_: List[_]) => xs }
val res0: List[Int] = List(42)

I'm not sure if scala 2 is plain wrong here. So any clarification would be helpful.
Oh nm it's REPL output bc:

scala> val ys: List[Int] = List(42) match { case xs @ (_: List[_]) => xs }
val ys: List[Int] = List(42)

but that goes to my point that a) a semi-casual reader might not have a preconceived notion and b) if I try it in the REPL, REPL may let me down, so I rely on your examples before giving up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, the return type is Int of the function, but I can introduce a val if it would make it clearer.

The reader of the spec does know that, and does not have an IDE or REPL to prove it. So yes, a val with an expected type would make it a lot clearer.

@sjrd sjrd assigned yilinwei and unassigned sjrd Feb 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants