diff --git a/proposals/p3762.md b/proposals/p3762.md index 0a1255ff1fa40..7dd06283aa74d 100644 --- a/proposals/p3762.md +++ b/proposals/p3762.md @@ -12,27 +12,35 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ## Table of contents -- [Prior discussion](#prior-discussion) -- [Forward declarations in current design](#forward-declarations-in-current-design) -- [ODR (One definition rule)](#odr-one-definition-rule) -- [Requiring matching declarations to merge](#requiring-matching-declarations-to-merge) -- [`extern` keyword](#extern-keyword) -- [When declarations are allowed](#when-declarations-are-allowed) - - [No forward declarations after declarations](#no-forward-declarations-after-declarations) - - [Files must either use an imported declaration or declare their own](#files-must-either-use-an-imported-declaration-or-declare-their-own) - - [Libraries cannot both define an entity and declare it `extern`](#libraries-cannot-both-define-an-entity-and-declare-it-extern) - - [Type scopes may contain both a forward declaration and definition](#type-scopes-may-contain-both-a-forward-declaration-and-definition) -- [Merging `extern` declarations](#merging-extern-declarations) -- [Other modifier keyword merging approaches](#other-modifier-keyword-merging-approaches) -- [No `extern` keyword](#no-extern-keyword) -- [Looser restrictions on declarations](#looser-restrictions-on-declarations) -- [`extern` naming](#extern-naming) -- [Default `extern` to private](#default-extern-to-private) -- [Opaque types](#opaque-types) +- [Abstract](#abstract) +- [Problem](#problem) +- [Background](#background) + - [Prior discussion](#prior-discussion) + - [Forward declarations in current design](#forward-declarations-in-current-design) + - [ODR (One definition rule)](#odr-one-definition-rule) + - [Requiring matching declarations to merge](#requiring-matching-declarations-to-merge) +- [Proposal](#proposal) +- [Details](#details) + - [`extern` keyword](#extern-keyword) + - [When declarations are allowed](#when-declarations-are-allowed) + - [No forward declarations after declarations](#no-forward-declarations-after-declarations) + - [Files must either use an imported declaration or declare their own](#files-must-either-use-an-imported-declaration-or-declare-their-own) + - [Libraries cannot both define an entity and declare it `extern`](#libraries-cannot-both-define-an-entity-and-declare-it-extern) + - [Type scopes may contain both a forward declaration and definition](#type-scopes-may-contain-both-a-forward-declaration-and-definition) + - [Merging `extern` declarations](#merging-extern-declarations) + - [Modifier keywords](#modifier-keywords) +- [Rationale](#rationale) +- [Alternatives considered](#alternatives-considered) + - [Other modifier keyword merging approaches](#other-modifier-keyword-merging-approaches) + - [No `extern` keyword](#no-extern-keyword) + - [Looser restrictions on declarations](#looser-restrictions-on-declarations) + - [`extern` naming](#extern-naming) + - [Default `extern` to private](#default-extern-to-private) + - [Opaque types](#opaque-types) -# Abstract +## Abstract - Add the `extern` keyword for forward declarations in libraries that don't have the definition. @@ -41,7 +49,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - Clarify rules for when modifier keywords should be on forward declarations and definitions. -# Problem +## Problem A forward declaration can be merged with a definition when they match. However, there is ambiguity about behavior: @@ -52,9 +60,9 @@ there is ambiguity about behavior: - Whether modifier keywords need to match between forward declarations and definitions. -# Background +## Background -## Prior discussion +### Prior discussion - [Proposal #1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084) covered specifics for `impl` and `interface`. @@ -76,7 +84,7 @@ there is ambiguity about behavior: and has discussion about `extern` use. - This discussion led to a substantial fraction of this proposal. -## Forward declarations in current design +### Forward declarations in current design Example rules for forward declarations in the current design: @@ -88,7 +96,7 @@ Example rules for forward declarations in the current design: - [`interface`](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#declaring-interfaces-and-named-constraints) - [Matching and agreeing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#matching-and-agreeing) -## ODR (One definition rule) +### ODR (One definition rule) [C++'s ODR](https://en.cppreference.com/w/cpp/language/definition) requires each entity to have only one definition. C++ has trouble detecting issues at compile @@ -102,7 +110,7 @@ constitute a definition. Part of the goal in declaration syntax (`extern` in particular) is to be able to better diagnose ODR violations based on declarations. -## Requiring matching declarations to merge +### Requiring matching declarations to merge When two declarations have the same name, either within the same file or through imports, they need to "match", or will be diagnosed as a conflict. This is laid @@ -118,7 +126,7 @@ For example: - `fn F(); fn F(x: i32);` won't merge because they differ in parameters, resulting in a diagnostic. -# Proposal +## Proposal 1. `extern` is used to mark forward declarations of entities defined in a different library. @@ -141,9 +149,9 @@ For example: 5. Modifier keywords will be handled on a case-by-case basis for merging declarations. -# Details +## Details -## `extern` keyword +### `extern` keyword An `extern` modifier keyword is added. It modifies a forward declaration to indicate that the entity is not defined by the declaring library. A library @@ -171,7 +179,7 @@ keywords, and before other keywords. For example, declaration, only access modifiers are valid (see [Modifier keywords](#modifier-keywords)). -## When declarations are allowed +### When declarations are allowed When considering whether a declaration is allowed, we apply the rules: @@ -181,7 +189,7 @@ When considering whether a declaration is allowed, we apply the rules: 3. Support moving declarations between already-imported `api` files without affecting compilation of client libraries. -### No forward declarations after declarations +#### No forward declarations after declarations In a file, a forward declaration must never follow a forward declaration or definition for the same entity. @@ -202,7 +210,7 @@ class C; class C { ... } ``` -### Files must either use an imported declaration or declare their own +#### Files must either use an imported declaration or declare their own In a file, if a declaration or definition of an entity is imported, the file must choose between either using that version or declaring its own. It cannot do @@ -261,7 +269,7 @@ package Bar library "a" impl; class C; ``` -### Libraries cannot both define an entity and declare it `extern` +#### Libraries cannot both define an entity and declare it `extern` In a library, if the `impl` defines an entity, the `api` must not use `extern` when declaring it. @@ -285,7 +293,7 @@ In a library, the `api` might make an `extern` declaration that the `impl` imports and uses the definition of. This is consistent because the `impl` file is not declaring the entity. -### Type scopes may contain both a forward declaration and definition +#### Type scopes may contain both a forward declaration and definition The combination of a forward declaration and a definition is allowed in type scopes. @@ -307,7 +315,7 @@ class C { This is necessary because type bodies are not automatically moved out-of-line, unlike function types. -## Merging `extern` declarations +### Merging `extern` declarations For diagnostics, when merging imported declarations that don't differ (from different imported libraries): @@ -335,7 +343,7 @@ declaration will: - The `api` may forward declare when the `impl` defines, or the `impl` may repeat a forward declaration and also define. -# Modifier keywords +### Modifier keywords When considering various modifiers on a forward declaration versus definition: @@ -359,7 +367,7 @@ When considering various modifiers on a forward declaration versus definition: `private extern` declarations. - This affects both type-scoped names and namespace names. -# Rationale +## Rationale - [Software and language evolution](/docs/project/goals.md#software-and-language-evolution) - This proposal supports moving classes between libraries without @@ -399,9 +407,9 @@ When considering various modifiers on a forward declaration versus definition: supports developers making conclusions based on which keywords they see -- either by presence or absence. -# Alternatives considered +## Alternatives considered -## Other modifier keyword merging approaches +### Other modifier keyword merging approaches There has been intermittent discussion about which modifiers to allow or require on forward declarations versus definitions. There are advantages and @@ -470,7 +478,7 @@ on the definition are typically a superset of modifiers on the declaration. While looking at the declaration always gives an incomplete view, looking at the definition can give a complete view. -## No `extern` keyword +### No `extern` keyword If we had no `extern` keyword, then a declaration wouldn't give any hint of whether a library contains the definition. Given two forward declarations in @@ -514,7 +522,7 @@ that otherwise would either be linker diagnostics or missed. The `extern` keyword is being added mainly for diagnostics and readability. -## Looser restrictions on declarations +### Looser restrictions on declarations We are being restrictive with declarations and when they're allowed. Primarily, we want to avoid confusion with code such as: @@ -558,13 +566,13 @@ is simply disallowed. In the second case, library "b" cannot declare `C` as make code clearer by helping developers catch redundant, and possibly incorrect, code. -## `extern` naming +### `extern` naming Beyond `extern`, we also considered `external`. `extern` implies external linkage in C++. We're choosing `extern` mainly for the small consistency with C++. -## Default `extern` to private +### Default `extern` to private The `extern` keyword could have an access control implication equivalent to `private`. Then `extern` would need explicit work to export the symbol. The @@ -629,7 +637,7 @@ imported library. Considering the trade-offs involved combination of these three points, this proposal suggests using the regular access control semantic. -## Opaque types +### Opaque types Omitting the `extern` modifier means a definition is required in a library. There may be a use-case for opaque types which are "owned" by a library and have