Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into amend-static-vs-const
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Oct 14, 2014
2 parents 809b9f2 + 091e5fa commit 14bd7da
Show file tree
Hide file tree
Showing 71 changed files with 320 additions and 17 deletions.
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Rust RFCs
[Rust RFCs]: #rust-rfcs

(jump forward to: [Table of Contents], [Active RFC List])

Many changes, including bug fixes and documentation improvements can be
implemented and reviewed via the normal GitHub pull request workflow.
Expand All @@ -12,7 +15,54 @@ consistent and controlled path for new features to enter the language
and standard libraries, so that all stakeholders can be confident about
the direction the language is evolving in.

## Active RFC List
[Active RFC List]: #active-rfc-list

* [0002-rfc-process.md](text/0002-rfc-process.md)
* [0008-new-intrinsics.md](text/0008-new-intrinsics.md)
* [0016-more-attributes.md](text/0016-more-attributes.md)
* [0019-opt-in-builtin-traits.md](text/0019-opt-in-builtin-traits.md)
* [0048-traits.md](text/0048-traits.md)
* [0066-better-temporary-lifetimes.md](text/0066-better-temporary-lifetimes.md)
* [0090-lexical-syntax-simplification.md](text/0090-lexical-syntax-simplification.md)
* [0107-pattern-guards-with-bind-by-move.md](text/0107-pattern-guards-with-bind-by-move.md)
* [0114-closures.md](text/0114-closures.md)
* [0131-target-specification.md](text/0131-target-specification.md)
* [0132-ufcs.md](text/0132-ufcs.md)
* [0135-where.md](text/0135-where.md)
* [0141-lifetime-elision.md](text/0141-lifetime-elision.md)
* [0151-capture-by-value.md](text/0151-capture-by-value.md)
* [0195-associated-items.md](text/0195-associated-items.md)
* [0198-slice-notation.md](text/0198-slice-notation.md)
* [0199-ownership-variants.md](text/0199-ownership-variants.md)
* [0201-error-chaining.md](text/0201-error-chaining.md)
* [0212-restore-int-fallback.md](text/0212-restore-int-fallback.md)
* [0214-while-let.md](text/0214-while-let.md)
* [0216-collection-views.md](text/0216-collection-views.md)
* [0221-panic.md](text/0221-panic.md)
* [0230-remove-runtime.md](text/0230-remove-runtime.md)
* [0231-upvar-capture-inference.md](text/0231-upvar-capture-inference.md)
* [0240-unsafe-api-location.md](text/0240-unsafe-api-location.md)
* [0246-const-vs-static.md](text/0246-const-vs-static.md)
* [0341-remove-virtual-structs.md](text/0341-remove-virtual-structs.md)
* [0342-keywords.md](text/0342-keywords.md)

## Table of Contents
[Table of Contents]: #table-of-contents
* [Opening](#rust-rfcs)
* [Active RFC List]
* [Table of Contents]
* [When you need to follow this process]
* [What the process is]
* [The role of the shepherd]
* [The RFC life-cycle]
* [Implementing an RFC]
* [Reviewing RFC's]
* [RFC Postponement]
* [Help this is all too informal!]

## When you need to follow this process
[When you need to follow this process]: #when-you-need-to-follow-this-process

You need to follow this process if you intend to make "substantial"
changes to the Rust distribution. What constitutes a "substantial"
Expand All @@ -39,7 +89,7 @@ through the RFC process, it may be closed with a polite request to
submit an RFC first.

## What the process is

[What the process is]: #what-the-process-is
In short, to get a major feature added to Rust, one must first get the
RFC merged into the RFC repo as a markdown file. At that point the RFC
is 'active' and may be implemented with the goal of eventual inclusion
Expand All @@ -62,6 +112,7 @@ merging the pull request and assigning the RFC a number, at which point
the RFC is 'active', or reject it by closing the pull request.

## The role of the shepherd
[The role of the shepherd]: the-role-of-the-shepherd

During triage, every RFC will either be closed or assigned a shepherd.
The role of the shepherd is to move the RFC through the process. This
Expand All @@ -74,6 +125,7 @@ here is to "front-load" as much of the feedback as possible before the
point where we actually reach a decision.

## The RFC life-cycle
[The RFC life-cycle]: #the-rfc-life-cycle

Once an RFC becomes active then authors may implement it and submit the
feature as a pull request to the Rust repo. An 'active' is not a rubber
Expand All @@ -100,6 +152,7 @@ that fails after becoming active is 'inactive' and moves to the
'inactive' folder.

## Implementing an RFC
[Implementing an RFC]: #implementing-an-rfc

Some accepted RFC's represent vital features that need to be
implemented right away. Other accepted RFC's can represent features
Expand All @@ -118,6 +171,7 @@ RFC, but cannot determine if someone else is already working on it,
feel free to ask (e.g. by leaving a comment on the associated issue).

## Reviewing RFC's
[Reviewing RFC's]: #reviewing-rfcs

Each week the [core team] will attempt to review some set of open RFC
pull requests. The choice of pull requests to review is largely
Expand All @@ -144,6 +198,7 @@ should act as a "shepherd" for the feature. The shepherd need not
its virtues and the community’s desire for it.

## RFC Postponement
[RFC Postponement]: #rfc-postponement

Some RFC pull requests are tagged with the 'postponed' label when they
are closed (as part of the rejection process). An RFC closed with
Expand All @@ -161,6 +216,7 @@ response is to close the RFC, not postpone it.)


### Help this is all too informal!
[Help this is all too informal!]: #help-this-is-all-too-informal

The process is intended to be as lightweight as reasonable for the
present circumstances. As usual, we are trying to let the process be
Expand Down
File renamed without changes.
23 changes: 14 additions & 9 deletions active/0001-rfc-process.md → text/0002-rfc-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ is 'active' and may be implemented with the goal of eventual inclusion
into Rust.

* Fork the RFC repo https://github.com/rust-lang/rfcs
* Copy `0000-template.md` to `active/0000-my-feature.md` (where
* Copy `0000-template.md` to `text/0000-my-feature.md` (where
'my-feature' is descriptive. don't assign an RFC number yet).
* Fill in the RFC
* Submit a pull request. The pull request is the time to get review of
Expand All @@ -71,16 +71,19 @@ are much more likely to make progress than those that don't receive any
comments.

Eventually, somebody on the [core team] will either accept the RFC by
merging the pull request and assigning the RFC a number, at which point
the RFC is 'active', or reject it by closing the pull request.
merging the pull request, at which point the RFC is 'active', or
reject it by closing the pull request.

Whomever merges the RFC should do the following:

* Assign a sequential id.
* Add the file in the active directory.
* Create a corresponding issue on Rust.
* Fill in the remaining metadata in the RFC header, including the original
PR # and Rust issue #.
* Assign an id, using the PR number of the RFC pull request. (If the RFC
has multiple pull requests associated with it, choose one PR number,
preferably the minimal one.)
* Add the file in the `text/` directory.
* Create a corresponding issue on [Rust repo](https://github.com/rust-lang/rust)
* Fill in the remaining metadata in the RFC header, including links for
the original pull request(s) and the newly created Rust issue.
* Add an entry in the [Active RFC List] of the root `README.md`.
* Commit everything.

Once an RFC becomes active then authors may implement it and submit the
Expand All @@ -91,9 +94,11 @@ have agreed to the feature and are amenable to merging it.

Modifications to active RFC's can be done in followup PR's. An RFC that
makes it through the entire process to implementation is considered
'complete' and is moved to the 'complete' folder; an RFC that fails
'complete' and is removed from the [Active RFC List]; an RFC that fails
after becoming active is 'inactive' and moves to the 'inactive' folder.

[Active RFC List]: ../README.md#active-rfc-list

# Alternatives

Retain the current informal RFC process. The newly proposed RFC process is
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- Start Date: 2014-09-18
- RFC PR #: #127
- Rust Issue #: #13231
- RFC PR #: [rust-lang/rfcs#19](https://github.com/rust-lang/rfcs/pull/19), [rust-lang/rfcs#127](https://github.com/rust-lang/rfcs/pull/127)
- Rust Issue #: [rust-lang/rust#13231](https://github.com/rust-lang/rust/issues/13231)

# Summary

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- Start Date: 2014-04-05
- RFC PR:
- Rust Issue:
- RFC PR: [rust-lang/rfcs#34](https://github.com/rust-lang/rfcs/pull/34)
- Rust Issue: [rust-lang/rust#15759](https://github.com/rust-lang/rust/issues/15759)

# Summary

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- Start Date: 2014-06-15
- RFC PR #: [rust-lang/rfcs#123](https://github.com/rust-lang/rfcs/pull/123j)
- RFC PR #: [rust-lang/rfcs#123](https://github.com/rust-lang/rfcs/pull/123)
- Rust Issue #: [rust-lang/rust#16281](https://github.com/rust-lang/rust/issues/16281)

# Summary
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
- Start Date: 2014-07-04
- RFC PR #: 155
- Rust Issue #: 17059
- RFC PR #: [rust-lang/rfcs#155](https://github.com/rust-lang/rfcs/pull/155)
- Rust Issue #: [rust-lang/rust#17059](https://github.com/rust-lang/rust/issues/17059)

# Summary

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
162 changes: 162 additions & 0 deletions text/0240-unsafe-api-location.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
- Start Date: 2014-10-07
- RFC PR: [rust-lang/rfcs#240](https://github.com/rust-lang/rfcs/pull/240)
- Rust Issue: [rust-lang/rust#17863](https://github.com/rust-lang/rust/issues/17863)

# Summary

This is a *conventions RFC* for settling the location of `unsafe` APIs relative
to the types they work with, as well as the use of `raw` submodules.

The brief summary is:

* Unsafe APIs should be made into methods or static functions in the same cases
that safe APIs would be.

* `raw` submodules should be used only to *define* explicit low-level
representations.

# Motivation

Many data structures provide unsafe APIs either for avoiding checks or working
directly with their (otherwise private) representation. For example, `string`
provides:

* An `as_mut_vec` method on `String` that provides a `Vec<u8>` view of the
string. This method makes it easy to work with the byte-based representation
of the string, but thereby also allows violation of the utf8 guarantee.

* A `raw` submodule with a number of free functions, like `from_parts`, that
constructs a `String` instances from a raw-pointer-based representation, a
`from_utf8` variant that does not actually check for utf8 validity, and so
on. The unifying theme is that all of these functions avoid checking some key
invariant.

The problem is that currently, there is no clear/consistent guideline about
which of these APIs should live as methods/static functions associated with a
type, and which should live in a `raw` submodule. Both forms appear throughout
the standard library.

# Detailed design

The proposed convention is:

* When an unsafe function/method is clearly "about" a certain type (as a way of
constructing, destructuring, or modifying values of that type), it should be a
method or static function on that type. This is the same as the convention for
placement of safe functions/methods. So functions like
`string::raw::from_parts` would become static functions on `String`.

* `raw` submodules should only be used to *define* low-level
types/representations (and methods/functions on them). Methods for converting
to/from such low-level types should be available directly on the high-level
types. Examples: `core::raw`, `sync::raw`.

The benefits are:

* *Ergonomics*. You can gain easy access to unsafe APIs merely by having a value
of the type (or, for static functions, importing the type).

* *Consistency and simplicity*. The rules for placement of unsafe APIs are the
same as those for safe APIs.

The perspective here is that marking APIs `unsafe` is enough to deter their use
in ordinary situations; they don't need to be further distinguished by placement
into a separate module.

There are also some naming conventions to go along with unsafe static functions
and methods:

* When an unsafe function/method is an unchecked variant of an otherwise safe
API, it should be marked using an `_unchecked` suffix.

For example, the `String` module should provide both `from_utf8` and
`from_utf8_unchecked` constructors, where the latter does not actually check
the utf8 encoding. The `string::raw::slice_bytes` and
`string::raw::slice_unchecked` functions should be merged into a single
`slice_unchecked` method on strings that checks neither bounds nor utf8
boundaries.

* When an unsafe function/method produces or consumes a low-level representation
of a data structure, the API should use `raw` in its name. Specifically,
`from_raw_parts` is the typical name used for constructing a value from e.g. a
pointer-based representation.

* Otherwise, *consider* using a name that suggests *why* the API is unsafe. In
some cases, like `String::as_mut_vec`, other stronger conventions apply, and the
`unsafe` qualifier on the signature (together with API documentation) is
enough.

The unsafe methods and static functions for a given type should be placed in
their own `impl` block, at the end of the module defining the type; this will
ensure that they are grouped together in rustdoc. (Thanks @kballard for the
suggestion.)

# Drawbacks

One potential drawback of these conventions is that the documentation for a
module will be cluttered with rarely-used `unsafe` APIs, whereas the `raw`
submodule approach neatly groups these APIs. But rustdoc could easily be
changed to either hide or separate out `unsafe` APIs by default, and in the
meantime the `impl` block grouping should help.

More specifically, the convention of placing unsafe constructors in `raw` makes
them very easy to find. But the usual `from_` convention, together with the
naming conventions suggested above, should make it fairly easy to discover such
constructors even when they're supplied directly as static functions.

More generally, these conventions give `unsafe` APIs more equal status with safe
APIs. Whether this is a *drawback* depends on your philosophy about the status
of unsafe programming. But on a technical level, the key point is that the APIs
are marked `unsafe`, so users still have to opt-in to using them. *Ed note: from
my perspective, low-level/unsafe programming is important to support, and there
is no reason to penalize its ergonomics given that it's opt-in anyway.*

# Alternatives

There are a few alternatives:

* Rather than providing unsafe APIs directly as methods/static functions, they
could be grouped into a single extension trait. For example, the `String` type
could be accompanied by a `StringRaw` extension trait providing APIs for
working with raw string representations. This would allow a clear grouping of
unsafe APIs, while still providing them as methods/static functions and
allowing them to easily be imported with e.g. `use std::string::StringRaw`.
On the other hand, it still further penalizes the raw APIs (beyond marking
them `unsafe`), and given that rustdoc could easily provide API grouping, it's
unclear exactly what the benefit is.

* ([Suggested by @kballard](https://github.com/rust-lang/rfcs/pull/240#issuecomment-55635468)):

> Use `raw` for functions that construct a value of the type without checking
> for one or more invariants.
The advantage is that it's easy to find such invariant-ignoring functions. The
disadvantage is that their ergonomics is worsened, since they much be
separately imported or referenced through a lengthy path:

```rust
// Compare the ergonomics:
string::raw::slice_unchecked(some_string, start, end)
some_string.slice_unchecked(start, end)
```

* Another suggestion by @kballard is to keep the basic structure of `raw`
submodules, but use associated types to improve the ergonomics. Details (and
discussions of pros/cons) are in
[this comment](https://github.com/rust-lang/rfcs/pull/240/files#r17572875).

* Use `raw` submodules to group together *all* manipulation of low-level
representations. No module in `std` currently does this; existing modules
provide some free functions in `raw`, and some unsafe methods, without a clear
driving principle. The ergonomics of moving *everything* into free functions
in a `raw` submodule are quite poor.

# Unresolved questions

The `core::raw` module provides structs with public representations equivalent
to several built-in and library types (boxes, closures, slices, etc.). It's not
clear whether the name of this module, or the location of its contents, should
change as a result of this RFC. The module is a special case, because not all of
the types it deals with even have corresponding modules/type declarations -- so
it probably suffices to leave decisions about it to the API stabilization
process.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 14bd7da

Please sign in to comment.