Skip to content

Fix #4815: Illegal modifier on local def #4850

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

Merged
merged 1 commit into from
Jul 27, 2018

Conversation

abeln
Copy link
Contributor

@abeln abeln commented Jul 26, 2018

During typechecking, disallow the use of final in local defs.

e.g.

def foo = {
  final def bar = 42 // error: final in local def is disallowed
}

@abeln abeln changed the title Fix 4815: Illegal modifier on local def Fix #4815: Illegal modifier on local def Jul 26, 2018
Copy link
Contributor

@allanrenucci allanrenucci left a comment

Choose a reason for hiding this comment

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

This should be fixed in the parser. The parser currently rejects:

class Test {
  def foo = {
    private def bar = 1
  }
}

I would check why final is not rejected as well

@@ -0,0 +1,24 @@
class Test {
def foo = {
final def bar = 1 // error: local def may not be final
Copy link
Contributor

Choose a reason for hiding this comment

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

scalac rejects this. I think we should reject it as well

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'm not sure I understand. We do reject this. This is what this PR does.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, it was meant for the line below (i.e. final val v = 42)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I see. There's at least one test that uses this feature (constant value expression):

A constant value definition is of the form

final val x = e

where e is a constant expression. The final modifier must be present and no type annotation may be given. References to the constant value x are themselves treated as constant expressions; in the generated code they are replaced by the definition's right-hand side e.

Copy link
Contributor

Choose a reason for hiding this comment

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

This part of the spec only specifies what a constant value is, not where it is allowed. Looking at the syntax part of the spec, it doesn't seems to be allowed

  BlockStat         ::=  Import
                      |  {Annotation} [‘implicit’ | ‘lazy’] Def
                      |  {Annotation} {LocalModifier} TmplDef
                      |  Expr1
  Def               ::=  PatVarDef
                      |  ‘def’ FunDef
                      |  ‘type’ {nl} TypeDef
                      |  TmplDef
  PatVarDef         ::=  ‘val’ PatDef
                      |  ‘var’ VarDef

@abeln
Copy link
Contributor Author

abeln commented Jul 27, 2018

Thanks for taking a look. Here's why I ended up adding the check in the typer.

There are four places I considered doing the check on:

def foo = {
  final class Bar;
}

This seemed rather ugly because the first thing defOrDcldoes is dispatches based on the next token, so we would add a bit of code duplication.

Does that make sense? Is there a reason the check should be shoehorned into the Parser?

@allanrenucci
Copy link
Contributor

@abeln
Copy link
Contributor Author

abeln commented Jul 27, 2018

Thanks for the link. I think I see how to make the Dotty version of localDef similar to the scalac one, but first we need to figure out the question in the comment above about constant value expressions. WDYT?

@abeln
Copy link
Contributor Author

abeln commented Jul 27, 2018

Moved the change to the parser a la scalac. PTAL.

Copy link
Contributor

@allanrenucci allanrenucci left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks @abeln 🎉

You can change the final val in dotty.tools.languageserver.Memory to a normal val

During parsing, disallow the use of "final" in local definitions.

e.g.

def foo = {
  final def bar = 42 // error: final in local def is disallowed
  final var x = 42 // error
  final type X = Int // error
}
@abeln
Copy link
Contributor Author

abeln commented Jul 27, 2018

Done. PTAL.

@allanrenucci allanrenucci merged commit c2de29d into scala:master Jul 27, 2018
@abeln abeln deleted the local-def-mod branch July 30, 2018 10:31
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.

2 participants