Skip to content

Rollup of 6 pull requests #26861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jul 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/doc/trpl/concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ system is up to the task, and gives you powerful ways to reason about
concurrent code at compile time.

Before we talk about the concurrency features that come with Rust, it's important
to understand something: Rust is low-level enough that all of this is provided
by the standard library, not by the language. This means that if you don't like
some aspect of the way Rust handles concurrency, you can implement an alternative
way of doing things. [mio](https://github.com/carllerche/mio) is a real-world
example of this principle in action.
to understand something: Rust is low-level enough that the vast majority of
this is provided by the standard library, not by the language. This means that
if you don't like some aspect of the way Rust handles concurrency, you can
implement an alternative way of doing things.
[mio](https://github.com/carllerche/mio) is a real-world example of this
principle in action.

## Background: `Send` and `Sync`

Expand Down
29 changes: 29 additions & 0 deletions src/doc/trpl/lifetimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
i32` as ‘a mutable reference to an i32’ and `&'a mut i32` as ‘a mutable
reference to an `i32` with the lifetime `'a`’.

# In `struct`s

You’ll also need explicit lifetimes when working with [`struct`][structs]s:

```rust
Expand Down Expand Up @@ -137,6 +139,33 @@ x: &'a i32,
uses it. So why do we need a lifetime here? We need to ensure that any reference
to a `Foo` cannot outlive the reference to an `i32` it contains.

## `impl` blocks

Let’s implement a method on `Foo`:

```rust
struct Foo<'a> {
x: &'a i32,
}

impl<'a> Foo<'a> {
fn x(&self) -> &'a i32 { self.x }
}

fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };

println!("x is: {}", f.x());
}
```

As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat
`'a` twice, just like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
uses it.

## Multiple lifetimes

If you have multiple references, you can use the same lifetime multiple times:

```rust
Expand Down
43 changes: 28 additions & 15 deletions src/doc/trpl/unsafe.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions
than normal code does.

Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in
two contexts. The first one is to mark a function as unsafe:
four contexts. The first one is to mark a function as unsafe:

```rust
unsafe fn danger_will_robinson() {
Expand All @@ -27,15 +27,40 @@ unsafe {
}
```

The third is for unsafe traits:

```rust
unsafe trait Scary { }
```

And the fourth is for `impl`ementing one of those traits:

```rust
# unsafe trait Scary { }
unsafe impl Scary for i32 {}
```

It’s important to be able to explicitly delineate code that may have bugs that
cause big problems. If a Rust program segfaults, you can be sure it’s somewhere
in the sections marked `unsafe`.

# What does ‘safe’ mean?

Safe, in the context of Rust, means “doesn’t do anything unsafe.” Easy!
Safe, in the context of Rust, means ‘doesn’t do anything unsafe’. It’s also
important to know that there are certain behaviors that are probably not
desirable in your code, but are expressly _not_ unsafe:

Okay, let’s try again: what is not safe to do? Here’s a list:
* Deadlocks
* Leaks of memory or other resources
* Exiting without calling destructors
* Integer overflow

Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things aren’t great, but they don’t qualify as `unsafe`
specifically.

In addition, the following are all undefined behaviors in Rust, and must be
avoided, even when writing `unsafe` code:

* Data races
* Dereferencing a null/dangling raw pointer
Expand Down Expand Up @@ -64,18 +89,6 @@ Okay, let’s try again: what is not safe to do? Here’s a list:
[undef]: http://llvm.org/docs/LangRef.html#undefined-values
[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules

Whew! That’s a bunch of stuff. It’s also important to notice all kinds of
behaviors that are certainly bad, but are expressly _not_ unsafe:

* Deadlocks
* Leaks of memory or other resources
* Exiting without calling destructors
* Integer overflow

Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things aren’t great, but they don’t qualify as `unsafe`
specifically.

# Unsafe Superpowers

In both unsafe functions and unsafe blocks, Rust will let you do three things
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
sess.diagnostic()));

krate = time(time_passes, "prelude injection", krate, |krate|
syntax::std_inject::maybe_inject_prelude(krate));
syntax::std_inject::maybe_inject_prelude(&sess.parse_sess, krate));

time(time_passes, "checking that all macro invocations are gone", &krate, |krate|
syntax::ext::expand::check_for_macros(&sess.parse_sess, krate));
Expand Down
83 changes: 80 additions & 3 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,62 @@ struct Foo {
```
"##,

E0128: r##"
Type parameter defaults can only use parameters that occur before them.
Erroneous code example:

```
pub struct Foo<T=U, U=()> {
field1: T,
filed2: U,
}
// error: type parameters with a default cannot use forward declared
// identifiers
```

Since type parameters are evaluated in-order, you may be able to fix this issue
by doing:

```
pub struct Foo<U=(), T=U> {
field1: T,
filed2: U,
}
```

Please also verify that this wasn't because of a name-clash and rename the type
parameter if so.
"##,

E0130: r##"
You declared a pattern as an argument in a foreign function declaration.
Erroneous code example:

```
extern {
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
// function declarations
}
```

Please replace the pattern argument with a regular one. Example:

```
struct SomeStruct {
a: u32,
b: u32,
}

extern {
fn foo(s: SomeStruct); // ok!
}
// or
extern {
fn foo(a: (u32, u32)); // ok!
}
```
"##,

E0131: r##"
It is not possible to define `main` with type parameters, or even with function
parameters. When `main` is present, it must take no arguments and return `()`.
Expand All @@ -1382,6 +1438,30 @@ fn(isize, *const *const u8) -> isize
```
"##,

E0159: r##"
You tried to use a trait as a struct constructor. Erroneous code example:

```
trait TraitNotAStruct {}

TraitNotAStruct{ value: 0 }; // error: use of trait `TraitNotAStruct` as a
// struct constructor
```

Please verify you used the correct type name or please implement the trait
on a struct and use this struct constructor. Example:

```
trait TraitNotAStruct {}

struct Foo {
value: i32
}

Foo{ value: 0 }; // ok!
```
"##,

E0166: r##"
This error means that the compiler found a return expression in a function
marked as diverging. A function diverges if it has `!` in the place of the
Expand Down Expand Up @@ -1979,11 +2059,8 @@ register_diagnostics! {
E0122,
E0123,
E0127,
E0128,
E0129,
E0130,
E0141,
E0159,
E0163,
E0164,
E0167,
Expand Down
6 changes: 5 additions & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[

// Allows the definition of `const fn` functions.
("const_fn", "1.2.0", Active),

// Allows using #[prelude_import] on glob `use` items.
("prelude_import", "1.2.0", Active),
];
// (changing above list without updating src/doc/reference.md makes @cmr sad)

Expand Down Expand Up @@ -265,7 +268,8 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
and may be removed in the future")),

// used in resolve
("prelude_import", Whitelisted),
("prelude_import", Gated("prelude_import",
"`#[prelude_import]` is for use by rustc only")),

// FIXME: #14407 these are only looked at on-demand so we can't
// guarantee they'll have already been checked
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,13 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
// of the feature gate, so we fake them up here.

let no_std_meta = attr::mk_word_item(InternedString::new("no_std"));
let prelude_import_meta = attr::mk_word_item(InternedString::new("prelude_import"));

// #![feature(no_std)]
let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(),
attr::mk_list_item(InternedString::new("feature"),
vec![no_std_meta.clone()]));
vec![no_std_meta.clone(),
prelude_import_meta]));
try!(s.print_attribute(&fake_attr));

// #![no_std]
Expand Down
48 changes: 33 additions & 15 deletions src/libsyntax/std_inject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,35 @@

use ast;
use attr;
use codemap::DUMMY_SP;
use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
use codemap;
use fold::Folder;
use fold;
use parse::token::InternedString;
use parse::token::special_idents;
use parse::token;
use parse::{token, ParseSess};
use ptr::P;
use util::small_vector::SmallVector;

/// Craft a span that will be ignored by the stability lint's
/// call to codemap's is_internal check.
/// The expanded code uses the unstable `#[prelude_import]` attribute.
fn ignored_span(sess: &ParseSess, sp: Span) -> Span {
let info = ExpnInfo {
call_site: DUMMY_SP,
callee: NameAndSpan {
name: "std_inject".to_string(),
format: MacroAttribute,
span: None,
allow_internal_unstable: true,
}
};
let expn_id = sess.codemap().record_expansion(info);
let mut sp = sp;
sp.expn_id = expn_id;
return sp;
}

pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>)
-> ast::Crate {
if use_std(&krate) {
Expand All @@ -29,9 +48,12 @@ pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>)
}
}

pub fn maybe_inject_prelude(krate: ast::Crate) -> ast::Crate {
pub fn maybe_inject_prelude(sess: &ParseSess, krate: ast::Crate) -> ast::Crate {
if use_std(&krate) {
inject_prelude(krate)
let mut fold = PreludeInjector {
span: ignored_span(sess, DUMMY_SP)
};
fold.fold_crate(krate)
} else {
krate
}
Expand Down Expand Up @@ -80,8 +102,9 @@ fn inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>) -> ast::Cr
fold.fold_crate(krate)
}

struct PreludeInjector;

struct PreludeInjector {
span: Span
}

impl fold::Folder for PreludeInjector {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
Expand All @@ -107,7 +130,7 @@ impl fold::Folder for PreludeInjector {

fn fold_mod(&mut self, mut mod_: ast::Mod) -> ast::Mod {
let prelude_path = ast::Path {
span: DUMMY_SP,
span: self.span,
global: false,
segments: vec![
ast::PathSegment {
Expand All @@ -131,27 +154,22 @@ impl fold::Folder for PreludeInjector {
ident: special_idents::invalid,
node: ast::ItemUse(vp),
attrs: vec![ast::Attribute {
span: DUMMY_SP,
span: self.span,
node: ast::Attribute_ {
id: attr::mk_attr_id(),
style: ast::AttrOuter,
value: P(ast::MetaItem {
span: DUMMY_SP,
span: self.span,
node: ast::MetaWord(token::get_name(
special_idents::prelude_import.name)),
}),
is_sugared_doc: false,
},
}],
vis: ast::Inherited,
span: DUMMY_SP,
span: self.span,
}));

fold::noop_fold_mod(mod_, self)
}
}

fn inject_prelude(krate: ast::Crate) -> ast::Crate {
let mut fold = PreludeInjector;
fold.fold_crate(krate)
}
Loading