Skip to content

Commit e3d2964

Browse files
committed
---
yaml --- r: 95231 b: refs/heads/dist-snap c: dd98f70 h: refs/heads/master i: 95229: dc0e294 95227: 5c6767e 95223: ab7e9c1 95215: 1a56ecb 95199: 2c42789 95167: 3d74637 95103: 953638f 94975: 1fc2bcc 94719: d67ffae 94207: b7dba88 v: v3
1 parent 9abaa3a commit e3d2964

File tree

25 files changed

+576
-417
lines changed

25 files changed

+576
-417
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: c274a6888410ce3e357e014568b43310ed787d36
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: 4db6eba3a24778bd64260e5fcae24a41575c4d7b
9+
refs/heads/dist-snap: dd98f7089fec5ee8bc908089bcb89c6e352d8726
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/doc/rust.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,58 @@ fn main() {
18331833
> individual functions, structs, methods and enum variants, *not* to
18341834
> entire modules, traits, impls or enums themselves.
18351835
1836+
### Compiler Features
1837+
1838+
Certain aspects of Rust may be implemented in the compiler, but they're not
1839+
necessarily ready for every-day use. These features are often of "prototype
1840+
quality" or "almost production ready", but may not be stable enough to be
1841+
considered a full-fleged language feature.
1842+
1843+
For this reason, rust recognizes a special crate-level attribute of the form:
1844+
1845+
~~~ {.xfail-test}
1846+
#[feature(feature1, feature2, feature3)]
1847+
~~~
1848+
1849+
This directive informs the compiler that the feature list: `feature1`,
1850+
`feature2`, and `feature3` should all be enabled. This is only recognized at a
1851+
crate-level, not at a module-level. Without this directive, all features are
1852+
considered off, and using the features will result in a compiler error.
1853+
1854+
The currently implemented features of the compiler are:
1855+
1856+
* `macro_rules` - The definition of new macros. This does not encompass
1857+
macro-invocation, that is always enabled by default, this only
1858+
covers the definition of new macros. There are currently
1859+
various problems with invoking macros, how they interact with
1860+
their environment, and possibly how they are used outside of
1861+
location in which they are defined. Macro definitions are
1862+
likely to change slightly in the future, so they are currently
1863+
hidden behind this feature.
1864+
1865+
* `globs` - Importing everything in a module through `*`. This is currently a
1866+
large source of bugs in name resolution for Rust, and it's not clear
1867+
whether this will continue as a feature or not. For these reasons,
1868+
the glob import statement has been hidden behind this feature flag.
1869+
1870+
* `struct_variant` - Structural enum variants (those with named fields). It is
1871+
currently unknown whether this style of enum variant is as
1872+
fully supported as the tuple-forms, and it's not certain
1873+
that this style of variant should remain in the language.
1874+
For now this style of variant is hidden behind a feature
1875+
flag.
1876+
1877+
If a feature is promoted to a language feature, then all existing programs will
1878+
start to receive compilation warnings about #[feature] directives which enabled
1879+
the new feature (because the directive is no longer necessary). However, if
1880+
a feature is decided to be removed from the language, errors will be issued (if
1881+
there isn't a parser error first). The directive in this case is no longer
1882+
necessary, and it's likely that existing code will break if the feature isn't
1883+
removed.
1884+
1885+
If a unknown feature is found in a directive, it results in a compiler error. An
1886+
unknown feature is one which has never been recognized by the compiler.
1887+
18361888
# Statements and expressions
18371889

18381890
Rust is _primarily_ an expression language. This means that most forms of

branches/dist-snap/doc/tutorial-rustpkg.md

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -206,54 +206,6 @@ note: Installed package github.com/YOUR_USERNAME/hello-0.1 to /home/yourusername
206206

207207
That's it!
208208

209-
# Testing your Package
210-
211-
Testing your package is simple as well. First, let's change `src/hello/lib.rs` to contain
212-
a function that can be sensibly tested:
213-
214-
~~~
215-
#[desc = "A Rust package for determining whether unsigned integers are even."];
216-
#[license = "MIT"];
217-
218-
pub fn is_even(i: uint) -> bool {
219-
i % 2 == 0
220-
}
221-
~~~
222-
223-
Once you've edited `lib.rs`, you can create a second crate file, `src/hello/test.rs`,
224-
to put tests in:
225-
226-
~~~
227-
#[license = "MIT"];
228-
extern mod hello;
229-
use hello::is_even;
230-
231-
#[test]
232-
fn test_is_even() {
233-
assert!(is_even(0));
234-
assert!(!is_even(1));
235-
assert!(is_even(2));
236-
}
237-
~~~
238-
239-
Note that you have to import the crate you just created in `lib.rs` with the
240-
`extern mod hello` directive. That's because you're putting the tests in a different
241-
crate from the main library that you created.
242-
243-
Now, you can use the `rustpkg test` command to build this test crate (and anything else
244-
it depends on) and run the tests, all in one step:
245-
246-
~~~ {.notrust}
247-
$ rustpkg test hello
248-
WARNING: The Rust package manager is experimental and may be unstable
249-
note: Installed package hello-0.1 to /Users/tjc/.rust
250-
251-
running 1 test
252-
test test_is_even ... ok
253-
254-
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
255-
~~~
256-
257209
# More resources
258210

259211
There's a lot more going on with `rustpkg`, this is just to get you started.

branches/dist-snap/doc/tutorial.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,10 @@ fn area(sh: Shape) -> f64 {
746746
}
747747
~~~~
748748

749+
> ***Note:*** This feature of the compiler is currently gated behind the
750+
> `#[feature(struct_variant)]` directive. More about these directives can be
751+
> found in the manual.
752+
749753
## Tuples
750754

751755
Tuples in Rust behave exactly like structs, except that their fields
@@ -2665,6 +2669,10 @@ use farm::*;
26652669
# fn main() { cow(); chicken() }
26662670
~~~
26672671

2672+
> ***Note:*** This feature of the compiler is currently gated behind the
2673+
> `#[feature(globs)]` directive. More about these directives can be found in
2674+
> the manual.
2675+
26682676
However, that's not all. You can also rename an item while you're bringing it into scope:
26692677

26702678
~~~

branches/dist-snap/src/libextra/extra.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Rust extras are part of the standard Rust distribution.
3333
#[license = "MIT/ASL2"];
3434
#[crate_type = "lib"];
3535

36+
#[feature(macro_rules, globs)];
37+
3638
#[deny(non_camel_case_types)];
3739
#[deny(missing_doc)];
3840

branches/dist-snap/src/librustc/driver/driver.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ pub fn phase_2_configure_and_expand(sess: Session,
159159
*sess.building_library = session::building_library(sess.opts.crate_type,
160160
&crate, sess.opts.test);
161161

162+
time(time_passes, ~"gated feature checking", (), |_|
163+
front::feature_gate::check_crate(sess, &crate));
162164

163165
// strip before expansion to allow macros to depend on
164166
// configuration variables e.g/ in
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Feature gating
12+
//!
13+
//! This modules implements the gating necessary for preventing certain compiler
14+
//! features from being used by default. This module will crawl a pre-expanded
15+
//! AST to ensure that there are no features which are used that are not
16+
//! enabled.
17+
//!
18+
//! Features are enabled in programs via the crate-level attributes of
19+
//! #[feature(...)] with a comma-separated list of features.
20+
21+
use syntax::ast;
22+
use syntax::attr::AttrMetaMethods;
23+
use syntax::codemap::Span;
24+
use syntax::visit;
25+
use syntax::visit::Visitor;
26+
27+
use driver::session::Session;
28+
29+
/// This is a list of all known features since the beginning of time. This list
30+
/// can never shrink, it may only be expanded (in order to prevent old programs
31+
/// from failing to compile). The status of each feature may change, however.
32+
static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
33+
("globs", Active),
34+
("macro_rules", Active),
35+
("struct_variant", Active),
36+
37+
// These are used to test this portion of the compiler, they don't actually
38+
// mean anything
39+
("test_accepted_feature", Accepted),
40+
("test_removed_feature", Removed),
41+
];
42+
43+
enum Status {
44+
/// Represents an active feature that is currently being implemented or
45+
/// currently being considered for addition/removal.
46+
Active,
47+
48+
/// Represents a feature which has since been removed (it was once Active)
49+
Removed,
50+
51+
/// This language feature has since been Accepted (it was once Active)
52+
Accepted,
53+
}
54+
55+
struct Context {
56+
features: ~[&'static str],
57+
sess: Session,
58+
}
59+
60+
impl Context {
61+
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
62+
if !self.has_feature(feature) {
63+
self.sess.span_err(span, explain);
64+
self.sess.span_note(span, format!("add \\#[feature({})] to the \
65+
crate attributes to enable",
66+
feature));
67+
}
68+
}
69+
70+
fn has_feature(&self, feature: &str) -> bool {
71+
self.features.iter().any(|n| n.as_slice() == feature)
72+
}
73+
}
74+
75+
impl Visitor<()> for Context {
76+
fn visit_view_item(&mut self, i: &ast::view_item, _: ()) {
77+
match i.node {
78+
ast::view_item_use(ref paths) => {
79+
for path in paths.iter() {
80+
match path.node {
81+
ast::view_path_glob(*) => {
82+
self.gate_feature("globs", path.span,
83+
"glob import statements are \
84+
experimental and possibly buggy");
85+
}
86+
_ => {}
87+
}
88+
}
89+
}
90+
_ => {}
91+
}
92+
visit::walk_view_item(self, i, ())
93+
}
94+
95+
fn visit_item(&mut self, i: @ast::item, _:()) {
96+
match i.node {
97+
ast::item_enum(ref def, _) => {
98+
for variant in def.variants.iter() {
99+
match variant.node.kind {
100+
ast::struct_variant_kind(*) => {
101+
self.gate_feature("struct_variant", variant.span,
102+
"enum struct variants are \
103+
experimental and possibly buggy");
104+
}
105+
_ => {}
106+
}
107+
}
108+
}
109+
110+
ast::item_mac(ref mac) => {
111+
match mac.node {
112+
ast::mac_invoc_tt(ref path, _, _) => {
113+
let rules = self.sess.ident_of("macro_rules");
114+
if path.segments.last().identifier == rules {
115+
self.gate_feature("macro_rules", i.span,
116+
"macro definitions are not \
117+
stable enough for use and are \
118+
subject to change");
119+
}
120+
}
121+
}
122+
}
123+
124+
_ => {}
125+
}
126+
127+
visit::walk_item(self, i, ());
128+
}
129+
}
130+
131+
pub fn check_crate(sess: Session, crate: &ast::Crate) {
132+
let mut cx = Context {
133+
features: ~[],
134+
sess: sess,
135+
};
136+
137+
for attr in crate.attrs.iter() {
138+
if "feature" != attr.name() { continue }
139+
140+
match attr.meta_item_list() {
141+
None => {
142+
sess.span_err(attr.span, "malformed feature attribute, \
143+
expected #[feature(...)]");
144+
}
145+
Some(list) => {
146+
for &mi in list.iter() {
147+
let name = match mi.node {
148+
ast::MetaWord(word) => word,
149+
_ => {
150+
sess.span_err(mi.span, "malformed feature, expected \
151+
just one word");
152+
continue
153+
}
154+
};
155+
match KNOWN_FEATURES.iter().find(|& &(n, _)| n == name) {
156+
Some(&(name, Active)) => { cx.features.push(name); }
157+
Some(&(_, Removed)) => {
158+
sess.span_err(mi.span, "feature has been removed");
159+
}
160+
Some(&(_, Accepted)) => {
161+
sess.span_warn(mi.span, "feature has added to rust, \
162+
directive not necessary");
163+
}
164+
None => {
165+
sess.span_err(mi.span, "unknown feature");
166+
}
167+
}
168+
}
169+
}
170+
}
171+
}
172+
173+
visit::walk_crate(&mut cx, crate, ());
174+
175+
sess.abort_if_errors();
176+
}

0 commit comments

Comments
 (0)