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

Accept and ignore using in method calls (to aid cross-building with Scala 3) #10064

Merged
merged 1 commit into from Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions spec/06-expressions.md
Expand Up @@ -240,6 +240,7 @@ depending on whether `B` is mixed in with class `Root` or `A`.
```ebnf
SimpleExpr ::= SimpleExpr1 ArgumentExprs
ArgumentExprs ::= ‘(’ [Exprs] ‘)’
| ‘(’ ‘using’ Exprs ‘)’
| ‘(’ [Exprs ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’
| [nl] BlockExpr
Exprs ::= Expr {‘,’ Expr}
Expand Down Expand Up @@ -328,6 +329,9 @@ sum(List(1, 2, 3, 4))

would not typecheck.

An argument list may begin with the soft keyword `using` to facilitate cross-compilation with Scala 3.
The keyword is ignored.

### Named and Default Arguments

If an application is to use named arguments ´p = e´ or default
Expand Down
13 changes: 10 additions & 3 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -1916,6 +1916,7 @@ self =>

/** {{{
* ArgumentExprs ::= `(` [Exprs] `)`
* | `(` `using` Exprs `)`
* | [nl] BlockExpr
* }}}
*/
Expand All @@ -1924,9 +1925,15 @@ self =>
if (isIdent) treeInfo.assignmentToMaybeNamedArg(expr()) else expr()
)
in.token match {
case LBRACE => List(blockExpr())
case LPAREN => inParens(if (in.token == RPAREN) Nil else args())
case _ => Nil
case LBRACE => List(blockExpr())
case LPAREN => inParens {
in.token match {
case RPAREN => Nil
case IDENTIFIER if in.name == nme.using && lookingAhead(isExprIntro) => in.nextToken() ; args()
case _ => args()
}
}
case _ => Nil
}
}
/** A succession of argument lists. */
Expand Down
1 change: 1 addition & 0 deletions src/reflect/scala/reflect/internal/StdNames.scala
Expand Up @@ -684,6 +684,7 @@ trait StdNames {
// Scala 3 soft keywords
val infix: NameType = nameType("infix")
val open: NameType = nameType("open")
val using: NameType = nameType("using")

// Compiler utilized names

Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/i15552.check
@@ -0,0 +1,7 @@
i15552.scala:4: error: not found: value g
def f() = g(42)(using ctx) // error: no g
^
i15552.scala:22: error: not found: value using
def f() = g(using) // error: no using, does not actually suggest Using
^
2 errors
40 changes: 40 additions & 0 deletions test/files/neg/i15552.scala
@@ -0,0 +1,40 @@
// scalac: -Werror
class C {
val ctx: C = new C()
def f() = g(42)(using ctx) // error: no g
}

class Innocent {
val using = 42
def g(i: Int) = i
def f() = g(using)
Copy link
Member

Choose a reason for hiding this comment

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

g(using using) works too 😀

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wish I had thought of that one. Maybe I'll add another test class MaliciousPuns.

}

class Malicious {
val using = 42
def g(i: Int) = i
def f() = g(using using)
}

class Suggest {
import scala.util._
def g(i: Int) = i
def f() = g(using) // error: no using, does not actually suggest Using
}

class Fancy {
def g(i: Int) = i
def f() = g(using if (true) 42 else 17)
}

/*
was:

i15552.scala:4: error: not found: value g
def f() = g(42)(using ctx)
^
i15552.scala:4: error: not found: value using
def f() = g(42)(using ctx)
^
i15552.scala:4: error: postfix operator ctx needs to be enabled
*/