diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index ccd769089d251..15c19ece48a14 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -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` diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index 11d651c5778e3..8e02367b921bc 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -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 @@ -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 diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index e8f1b829061c2..80b0c87473fa2 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -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() { @@ -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 @@ -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 diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 80c4fc28703ac..ae6136a049ade 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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)); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 81d4a93a6fa5d..e2f35983eb411 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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 { + 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 { + 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 `()`. @@ -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 @@ -1979,11 +2059,8 @@ register_diagnostics! { E0122, E0123, E0127, - E0128, E0129, - E0130, E0141, - E0159, E0163, E0164, E0167, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 3d0cf9236c25c..ab8cf9ae6b64f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -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) @@ -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 diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3adb73cfa5d6f..6693eed6aced5 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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] diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 021ec4738ed94..3655058653188 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -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) -> ast::Crate { if use_std(&krate) { @@ -29,9 +48,12 @@ pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option) } } -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 } @@ -80,8 +102,9 @@ fn inject_crates_ref(krate: ast::Crate, alt_std_name: Option) -> 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 { @@ -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 { @@ -131,12 +154,12 @@ 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)), }), @@ -144,14 +167,9 @@ impl fold::Folder for PreludeInjector { }, }], 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) -} diff --git a/src/test/compile-fail/feature-gate-prelude_import.rs b/src/test/compile-fail/feature-gate-prelude_import.rs new file mode 100644 index 0000000000000..8bc3df247ec12 --- /dev/null +++ b/src/test/compile-fail/feature-gate-prelude_import.rs @@ -0,0 +1,14 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only +use std::prelude::v1::*; + +fn main() {} diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index c2ed10ce6a187..5f7ce68348a3d 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -1,4 +1,4 @@ -#![feature(no_std)] +#![feature(no_std, prelude_import)] #![no_std] #[prelude_import] use std::prelude::v1::*;