Remove bound
Table of contents
Abstract
Remove the bound parameter modifier introduced in proposal #5434, as it is superseded by the upcoming memory safety design.
Problem
Proposal #5434 introduced the bound parameter modifier to mark parameters whose storage may be referenced by a function’s return value, modeled after Clang’s [[clang::lifetimebound]] attribute. This served two purposes:
- Allowing the compiler to diagnose some use-after-free bugs when a function’s return is used after the lifetime of a
boundargument ends. - Distinguishing
refparameters that may be referenced by the return value (captures(ret: address, provenance)) from those that cannot (captures(none)), so that non-boundrefparameters could use a “move-in-move-out” calling convention.
However, bound will be superseded by the upcoming memory safety design, which replaces this ad-hoc annotation with a more comprehensive lifetime model. Retaining bound in the meantime is a burden for other design work, such as pending proposal #5389.
Background
Proposal #5434: “ref parameters, arguments, returns and val returns” introduced ref bindings, ref and val returns, and the bound parameter modifier. Under proposal #5434:
- Any parameter whose storage could be referenced by the function’s return had to be marked
bound. - Function declarations in interfaces could mark parameters
bound, andimpldeclarations could omitboundfrom parameters markedboundin the interface, but could not addboundto parameters not markedboundin the interface. - The address of a
refbinding was specified as LLVM’snoaliasand eithercaptures(none)(if not markedbound) orcaptures(ret: address, provenance)(if markedbound).
Proposal
We remove the bound parameter modifier from Carbon:
- Parameters are no longer marked
boundwhen a function’s return may reference their storage. - The interface and
implmatching rules forboundparameters are removed. boundis removed from standard library interfaces such asDeref,IndexWith,IndirectIndexWith,BindToRef, andBindToValue.
For now:
- The address of a
refparameter will no lower with aliasing or capturing information. - Support for the “move-in-move-out” calling convention on
refparameters is removed.
These will be restored in a new form with the new memory safety design.
Details
It remains erroneous behavior to return something that references a local object whose lifetime ends when the function returns, including local variables, temporary objects, and var parameters.
Standard library interfaces
Standard library interfaces that previously used bound on parameters whose storage may be referenced by the return value now omit bound:
-
Deref:interface Deref { let Result: type; fn Op(ref self) -> ref Result; } final impl forall [T: type] T* as Deref { where .Result = T; fn Op(self) -> ref T = "builtin.deref"; } -
Indexing interfaces
IndexWithandIndirectIndexWith:interface IndexWith(SubscriptType: type) { let ElementType: type; fn At(self, subscript: SubscriptType) -> val ElementType; fn Ref(ref self, subscript: SubscriptType) -> ref ElementType; } interface IndirectIndexWith(SubscriptType: type) { require Self impls IndexWith(SubscriptType); fn Ref(self, subscript: SubscriptType) -> ref ElementType; } -
Member binding interfaces
BindToValueandBindToRef:interface BindToValue(T: type) { extend require impls Bind(T); fn Op(self, x: T) -> Result; } interface BindToRef(T: type) { extend require impls Bind(T); fn Op(self, ref p: T) -> ref Result; }
Rationale
- Software and language evolution
- There is no need to slow down language evolution at this early stage to keep compatibility with previous design proposals since
boundwas never implemented in the toolchain.
- There is no need to slow down language evolution at this early stage to keep compatibility with previous design proposals since
- Practical safety and testing mechanisms
- Lifetime relationships between parameters and return values will be handled cohesively by the memory safety design rather than a separate
[[clang::lifetimebound]]-style marker.
- Lifetime relationships between parameters and return values will be handled cohesively by the memory safety design rather than a separate
Alternatives considered
Alternatives to bound were considered as part of the upcoming memory safety design, and are out of scope for this proposal.