Skip to content

Commit 89be57f

Browse files
jonmeowjosh11b
andauthored
Add documentation for entity declaration design work (#4230)
Trying to pull in key elements of #3762, #3763, and #3980 (decl matching and `extern`, essentially). These aren't specific to any particular declaration type, but are common to entities, so suggesting a new doc oriented on that. There's probably more that could be said here, I'm just focused on getting the recent formal discussion mirrored into the design. --------- Co-authored-by: josh11b <[email protected]>
1 parent f75cbea commit 89be57f

File tree

1 file changed

+240
-0
lines changed

1 file changed

+240
-0
lines changed

docs/design/declaring_entities.md

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# Declaring entities
2+
3+
<!--
4+
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
5+
Exceptions. See /LICENSE for license information.
6+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
-->
8+
9+
<!-- toc -->
10+
11+
## Table of contents
12+
13+
- [Overview](#overview)
14+
- [Matching redeclarations of an entity](#matching-redeclarations-of-an-entity)
15+
- [Details](#details)
16+
- [`extern` and `extern library`](#extern-and-extern-library)
17+
- [Valid scopes for `extern`](#valid-scopes-for-extern)
18+
- [Effect on indirect imports](#effect-on-indirect-imports)
19+
- [Alternatives considered](#alternatives-considered)
20+
- [References](#references)
21+
22+
<!-- tocstop -->
23+
24+
## Overview
25+
26+
Entities may have up to three declarations:
27+
28+
- An optional, owning forward declaration.
29+
- For example, `class MyClass;`.
30+
- This must come before the definition. The API file is considered to be
31+
before the implementation file.
32+
- A required, owning definition.
33+
- For example, `class MyClass { ... }`.
34+
- The definition might be the _only_ declaration.
35+
- An optional, non-owning `extern library "<owning_library>"` declaration.
36+
- For example, `extern library "OtherLibrary" class MyClass;`.
37+
- It must be in a separate library from the definition.
38+
- The owning library's API file must import the `extern` declaration, and
39+
must also contain a declaration.
40+
- The owning library's declarations must have the `extern` modifier
41+
(without `library`).
42+
- For example, `extern class MyClass;`.
43+
44+
For example, a library can have a forward declaration of an entity in the API
45+
file, and use the implementation file for the entity's definition. Putting the
46+
definition in an implementation file this way can reduce the dependencies for
47+
API file evaluation, improving compile time. This is commonly done with
48+
functions. For example:
49+
50+
```
51+
library "MyLibrary";
52+
53+
fn DoSomething();
54+
```
55+
56+
```
57+
impl library "MyLibrary";
58+
59+
fn DoSomething() {
60+
...
61+
}
62+
```
63+
64+
## Matching redeclarations of an entity
65+
66+
In order to determine whether two redeclarations refer to the same entity, we
67+
apply the rules:
68+
69+
- Two named declarations _declare the same entity_ if they have the same scope
70+
and the same name. This includes imported declarations.
71+
- When two named declarations declare the same entity, the second is said to
72+
be a _redeclaration_.
73+
- Two owned declarations _differ_ if they don't syntactically match.
74+
- Otherwise, if one is a non-owned `extern library` declaration,
75+
declarations differ if they don't match semantically.
76+
- The program is invalid if it contains two declarations of the same entity
77+
that differ.
78+
79+
```carbon
80+
class A {
81+
// This function will be redeclared in order to provide a definition.
82+
fn F(n: i32);
83+
}
84+
85+
// ✅ Valid: The declaration matches syntactically.
86+
fn A.F(n: i32) {}
87+
88+
// ❌ Invalid: The parameter name differs.
89+
fn A.F(m: i32) {}
90+
91+
// ❌ Invalid: The parameter type differs syntactically.
92+
fn A.F(n: (i32)) {}
93+
```
94+
95+
### Details
96+
97+
TODO: Figure out what details to pull from
98+
[#3762](https://github.com/carbon-language/carbon-lang/pull/3762) and
99+
[#3763](https://github.com/carbon-language/carbon-lang/pull/3763).
100+
101+
## `extern` and `extern library`
102+
103+
There are two forms of the `extern` modifier:
104+
105+
- On an owning declaration, `extern` limits access to the definition.
106+
- The entity must be directly imported in order to use of the definition.
107+
- An `extern library` declaration is optional.
108+
- On a non-owning declaration, `extern library` allows references to an entity
109+
without depending on the owning library.
110+
- The library name indicates where the entity is defined.
111+
- This can be used to improve build performance, such as by splitting out
112+
a declaration in order to reduce a library's dependencies.
113+
114+
For example, a use of both might look like:
115+
116+
```
117+
library "owner";
118+
119+
// This `import` is required due to the `extern library`, but we also make use
120+
// of `MyClassFactory` below. This is a circular use of `MyClass` that we
121+
// couldn't split between libraries without `extern`.
122+
import library "factory";
123+
124+
extern class MyClass {
125+
fn Make() -> MyClass* {
126+
return MyClassFactory();
127+
}
128+
129+
var val: i32 = 0;
130+
}
131+
```
132+
133+
```
134+
library "factory";
135+
136+
// Declares `MyClass` so that `MyClassFactory` can return it.
137+
extern library "owner" class MyClass;
138+
139+
fn MyClassFactory(val: i32) -> MyClass*;
140+
```
141+
142+
```
143+
impl library "factory";
144+
145+
// Imports the definition of `MyClass`.
146+
import library "owner";
147+
148+
extern fn MyClassFactory(val: i32) -> MyClass* {
149+
var c: MyClass* = new MyClass();
150+
c->val = val;
151+
return c;
152+
}
153+
```
154+
155+
### Valid scopes for `extern`
156+
157+
The `extern` modifier is only valid on namespace-scoped entities, including in
158+
the file scope. In other words, `class C { extern fn F(); }` is invalid.
159+
160+
### Effect on indirect imports
161+
162+
Indirect imports won't see the definition of an `extern` entity. We expect this
163+
to primarily affect return types of functions. If an incomplete type is
164+
encountered this way, it can be resolved by directly importing the definition.
165+
For example:
166+
167+
```
168+
library "type";
169+
170+
// Because this is `extern`, the definition must be directly imported.
171+
extern class MyType { var x: i32 }
172+
```
173+
174+
```
175+
library "make_type";
176+
177+
import library "type";
178+
179+
// Here we have a function which returns the type.
180+
fn MakeMyType() -> MyType*;
181+
```
182+
183+
```
184+
library "invalid_use";
185+
186+
import library "make_type";
187+
188+
fn InvalidUse() -> i32 {
189+
// ❌ Invalid: `MyType` is incomplete because it's `extern` and not directly
190+
// imported. `x` cannot be accessed.
191+
return MakeMyType()->x;
192+
}
193+
```
194+
195+
```
196+
library "valid_use";
197+
198+
import library "make_type";
199+
200+
// ✅ Valid: By directly importing the definition, we can now access `x`.
201+
import library "type";
202+
203+
fn ValidUse() -> i32 {
204+
return MakeMyType()->x;
205+
}
206+
```
207+
208+
## Alternatives considered
209+
210+
- [Other modifier keyword merging approaches](/proposals/p3762.md#other-modifier-keyword-merging-approaches)
211+
- [No `extern` keyword](/proposals/p3762.md#no-extern-keyword)
212+
- [Looser restrictions on declarations](/proposals/p3762.md#looser-restrictions-on-declarations)
213+
- [`extern` naming](/proposals/p3762.md#extern-naming)
214+
- [Default `extern` to private](/proposals/p3762.md#default-extern-to-private)
215+
- [Opaque types](/proposals/p3762.md#opaque-types)
216+
- [Require a library provide its own `extern` declarations](/proposals/p3762.md#require-a-library-provide-its-own-extern-declarations)
217+
- [Allow cross-package `extern` declarations](/proposals/p3762.md#allow-cross-package-extern-declarations)
218+
- [Use a partially or fully semantic rule](/proposals/p3763.md#use-a-partially-or-fully-semantic-rule)
219+
- [Use package-wide name poisoning](/proposals/p3763.md#use-package-wide-name-poisoning)
220+
- [Allow shadowing in implementation file after use in API file](/proposals/p3763.md#allow-shadowing-in-implementation-file-after-use-in-api-file)
221+
- [Allow multiple non-owning declarations, remove the import requirement, or both](/proposals/p3980.md#allow-multiple-non-owning-declarations-remove-the-import-requirement-or-both)
222+
- [Total number of allowed declarations (owning and non-owning)](/proposals/p3980.md#total-number-of-allowed-declarations-owning-and-non-owning)
223+
- [Do not restrict the number of forward declarations](/proposals/p3980.md#do-not-restrict-the-number-of-forward-declarations)
224+
- [Allow up to two declarations total](/proposals/p3980.md#allow-up-to-two-declarations-total)
225+
- [Allow up to four declarations total](/proposals/p3980.md#allow-up-to-four-declarations-total)
226+
- [Don't require a modifier on the owning declarations](/proposals/p3980.md#dont-require-a-modifier-on-the-owning-declarations)
227+
- [Only require `extern` on the first owning declaration](/proposals/p3980.md#only-require-extern-on-the-first-owning-declaration)
228+
- [Separate require-direct-import from non-owning declarations](/proposals/p3980.md#separate-require-direct-import-from-non-owning-declarations)
229+
- [Other `extern` syntaxes](/proposals/p3980.md#other-extern-syntaxes)
230+
- [Have types with `extern` members re-export them](/proposals/p3980.md#have-types-with-extern-members-re-export-them)
231+
- [Require syntactic matching for `extern library` declarations](/proposals/p3980.md#require-syntactic-matching-for-extern-library-declarations)
232+
233+
## References
234+
235+
- Proposal
236+
[#3762: Merging forward declarations](https://github.com/carbon-language/carbon-lang/pull/3762)
237+
- Proposal
238+
[#3763: Matching redeclarations](https://github.com/carbon-language/carbon-lang/pull/3763)
239+
- Proposal
240+
[#3980: Singular `extern` declarations](https://github.com/carbon-language/carbon-lang/pull/3980)

0 commit comments

Comments
 (0)