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

Check that name shadowing with "simple" local variables is still prohibited #1131

Open
jskeet opened this issue Jun 12, 2024 · 4 comments
Open
Assignees

Comments

@jskeet
Copy link
Contributor

jskeet commented Jun 12, 2024

This is for Jon to convince himself (and document here) that the concern in #608 is not a problem.

@jskeet jskeet self-assigned this Jun 12, 2024
@jskeet jskeet added the meeting: discuss This issue should be discussed at the next TC49-TG2 meeting label Jul 1, 2024
@jskeet
Copy link
Contributor Author

jskeet commented Jul 1, 2024

Hmm. 7.3 still contains:

Local variable declaration spaces may be nested, but it is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name. Thus, within a nested declaration space it is not possible to declare a local variable, local function or constant with the same name as a parameter, type parameter, local variable, local function or constant in an enclosing declaration space. It is possible for two declaration spaces to contain elements with the same name as long as neither declaration space contains the other. Local declaration spaces are created by the following constructs

Notes on this:

  • "Local declaration spaces" in the final sentence should probably be "local variable declaration spaces"
  • This paragraph prohibits what we want to prohibit - but it's possible that it also prohibits what Add Support for Name shadowing #608 was intended to allow.

Effectively, I think we want to have a concept that differentiates between just "local variable declaration space X with a nested local variable declaration space Y" and "local variable declaration space X with a nested local variable declaration space Y that's introduced by a anonymous-function/local-function". If each local variable declaration space had an "owner" which was one of:

  • A member declaration
  • A local function declaration
  • An anonymous function declaration

... then we could say "it is an error for a local variable declaration space and a nested local variable declaration space with the same owner to contain elements with the same name".

I don't think "owner" is the right term here, but I think that's what we want in some form. Let's discuss.

@Nigel-Ecma
Copy link
Contributor

@jskeet is correct, #608 got it wrong or at least didn't go far enough…

The text in question is at the end, I've changed bullets to numbers to make it easier.

So #608 altered (7) with the intention of covering function-like things (™ 😉) declared within function-like things allowing hiding.

However (8.ii) contradicts this for function members, anonymous functions and local functions.

Facing this might be as simple as removing (8.ii), removing any references to local functions and friends from (8), and making sure we’re happy (7) is correct – which we were when we looked at it in isolation…

I’m not suggesting changes right now, got to be somewhere else, I may or may not get back to this before the meeting so I'm posting this to give Jon something to work on 😉.

Disclaimer: I could of course be wrong…

  1. Each method declaration, property declaration, property accessor declaration, indexer declaration, indexer accessor declaration, operator declaration, instance constructor declaration, anonymous function, and local function creates a new declaration space called a local variable declaration space. Names are introduced into this declaration space through formal parameters (fixed_parameters and parameter_arrays) and type_parameters. The set accessor for a property or an indexer introduces the name value as a formal parameter. The body of the function member, anonymous function, or local function, if any, is considered to be nested within the local variable declaration space. When a local variable declaration space and a nested local variable declaration space contain elements with the same name, within the scope of the nested local name, the outer local name is hidden (§7.7.1) by the nested local name.
  2. Additional local variable declaration spaces may occur within member declarations, anonymous functions and local functions. Names are introduced into these declaration spaces through patterns, declaration_expressions, declaration_statements and exception_specifiers. Local variable declaration spaces may be nested, but it is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name. Thus, within a nested declaration space it is not possible to declare a local variable, local function or constant with the same name as a parameter, type parameter, local variable, local function or constant in an enclosing declaration space. It is possible for two declaration spaces to contain elements with the same name as long as neither declaration space contains the other. Local declaration spaces are created by the following constructs:
    1. Each variable_initializer in a field and property declaration introduces its own local variable declaration space, that is not nested within any other local variable declaration space.
    2. The body of a function member, anonymous function, or local function, if any, creates a local variable declaration space that is considered to be nested within the function’s local variable declaration space.
    3. Each constructor_initializer creates a local variable declaration space nested within the instance constructor declaration. The local variable declaration space for the constructor body is in turn nested within this local variable declaration space.
    4. Each block, switch_block, specific_catch_clause, iteration_statement and using_statement creates a nested local variable declaration space.
    5. Each embedded_statement that is not directly part of a statement_list creates a nested local variable declaration space.
    6. Each switch_section creates a nested local variable declaration space. However, variables declared directly within the statement_list of the switch_section (but not within a nested local variable declaration space inside the statement_list) are added directly to the local variable declaration space of the enclosing switch_block, instead of that of the switch_section.
    7. The syntactic translation of a query_expression (§12.20.3) may introduce one or more lambda expressions. As anonymous functions, each of these creates a local variable declaration space as described above.
  3. Each block or switch_block creates a separate declaration space for labels. Names are introduced into this declaration space through labeled_statements, and the names are referenced through goto_statements. The label declaration space of a block includes any nested blocks. Thus, within a nested block it is not possible to declare a label with the same name as a label in an enclosing block.

@jskeet
Copy link
Contributor Author

jskeet commented Jul 10, 2024

Jon to see if he can come up with different names for the different kinds of local variable declaration spaces - and apply them accurately.

@jskeet
Copy link
Contributor Author

jskeet commented Jul 10, 2024

Also, within 13.6.2.1:

Within the scope of a local variable, it is a compile-time error to declare another local variable, local function or constant with the same name.

That is no longer correct, and will need addressing too.

@jskeet jskeet removed the meeting: discuss This issue should be discussed at the next TC49-TG2 meeting label Jul 10, 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

No branches or pull requests

2 participants