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 documentation for entity declaration design work #4230

Merged
merged 6 commits into from
Aug 21, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 29 additions & 22 deletions docs/design/declaring_entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- [Matching redeclarations of an entity](#matching-redeclarations-of-an-entity)
- [Details](#details)
- [`extern` and `extern library`](#extern-and-extern-library)
- [Valid scopes for `extern`](#valid-scopes-for-extern)
- [Effect on indirect imports](#effect-on-indirect-imports)
- [Alternatives considered](#alternatives-considered)
- [References](#references)
Expand Down Expand Up @@ -55,7 +56,7 @@ fn DoSomething();
```
impl library "MyLibrary";

fn DoSomething {
fn DoSomething() {
...
}
```
Expand All @@ -66,36 +67,35 @@ In order to determine whether two redeclarations refer to the same entity, we
apply the rules:

- Two named declarations _declare the same entity_ if they have the same scope
and the same name.
- One declaration _redeclares_ another if they declare the same entity and the
second declaration appears after the first, including the case where the
first declaration is imported. In this case, the second declaration is said
to be a _redeclaration_ of the first.
- Two declarations _differ_ if the sequence of tokens in the declaration
following the introducer keyword and the optional scope, up to the semicolon
or open brace, is different, except for `unused` modifiers on parameters.
- The program is invalid if it contains two owning declarations of the same
entity that differ.
- The non-owned `extern library` declarations will only use semantic
matching for redeclarations, not syntactic matching.
and the same name. This includes imported declarations.
- When two named declarations declare the same entity, the second is said to
be a _redeclaration_.
- Two owned declarations _differ_ if they don't syntactically match.
- The non-owned `extern library` declarations only require semantic
matching.
- The program is invalid if it contains two declarations of the same entity
that differ.
jonmeow marked this conversation as resolved.
Show resolved Hide resolved

```carbon
class A {
// This function will be redeclared in order to provide a definition.
fn F(n: i32);
fn G(n: i32);
}

// ✅ Valid: The declaration matches syntactically.
fn A.F(n: i32) {}

// ❌ Invalid: The parameter name differs.
fn A.F(m: i32) {}

// ❌ Invalid: The parameter type differs syntactically.
fn A.G(n: (i32)) {}
fn A.F(n: (i32)) {}
```

### Details

TODO: Figure out what details to pull from
[#3762](https://github.com/carbon-language/carbon-lang/pull/3763) and
[#3762](https://github.com/carbon-language/carbon-lang/pull/3762) and
[#3763](https://github.com/carbon-language/carbon-lang/pull/3763).

## `extern` and `extern library`
Expand All @@ -105,10 +105,11 @@ There are two forms of the `extern` modifier:
- On an owning declaration, `extern` limits access to the definition.
- The entity must be directly imported in order to use of the definition.
- An `extern library` declaration is optional.
- On a non-owning declaration, `extern library` provides a tool for breaking
dependency cycles.
- On a non-owning declaration, `extern library` allows references to an entity
without depending on the owning library.
- The library name indicates where the entity is defined.
-
- This may be used to break dependency cycles between libraries, which
could be used to improve build parallelization.
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like this might be alternatively be used to improve build scalability by reducing dependencies. This is independent of breaking dependency cycles, and isn't specifically about build parallelization.

Suggested change
- This may be used to break dependency cycles between libraries, which
could be used to improve build parallelization.
- This may be used to break dependency cycles between libraries, which
could be used to improve build parallelization.
- This may be used to reduce transitive dependencies, improving build
scalability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How about this rephrasing... (to copy here)

    -   This can be used to improve build performance, such as by splitting out
        a declaration in order to reduce a library's dependencies.

Note, trying to step aside from specific ways it might improve build performance because I want these bullets to focus more on what the feature does, versus how it might be used.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine with the new text, but don't you want something about that it can allow you to break cycles 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.

To me, that sort of feels like details where if we really want to explain how to use the feature this way, we should have more examples of refactorings to do.

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.e., I'm trying to figure out the right line to draw between proposal advocating for adoption of the feature, design trying to explain what it is, and user guide explaining how to apply it in anger.

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like the design shouldn't just say what it is, but also the why, and the purpose of the feature is definitely in scope.


For example, a use of both might look like:

Expand Down Expand Up @@ -151,11 +152,17 @@ extern fn MyClassFactory(val: i32) -> MyClass* {
}
```

### Valid scopes for `extern`

The `extern` modifier is only valid on namespace-scoped entities, including in
the file scope. In other words, `class C { extern fn F(); }` is invalid.

### Effect on indirect imports

Indirect imports won't see the definition of an entity. We expect this to
primarily effect return types of functions. If an incomplete type is encountered
this way, it can be resolved by directly importing the definition. For example:
Indirect imports won't see the definition of an `extern` entity. We expect this
to primarily affect return types of functions. If an incomplete type is
encountered this way, it can be resolved by directly importing the definition.
For example:

```
library "type";
Expand Down
Loading