diff --git a/mk/main.mk b/mk/main.mk index ac080c36fd1e0..27f491fcd75af 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.14.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.3 +CFG_PRERELEASE_VERSION=.4 ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" diff --git a/src/doc/book/syntax-index.md b/src/doc/book/syntax-index.md index 1e05b01d30d46..28403711cd701 100644 --- a/src/doc/book/syntax-index.md +++ b/src/doc/book/syntax-index.md @@ -94,6 +94,7 @@ * `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`). * `||` (`expr || expr`): logical or. * `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]). +* `?` (`expr?`): Error propagation. Returns early when `Err(_)` is encountered, unwraps otherwise. Similar to the [`try!` macro]. ## Other Syntax @@ -210,6 +211,7 @@ [Functions]: functions.html [Generics]: generics.html [Iterators]: iterators.html +[`try!` macro]: error-handling.html#the-try-macro [Lifetimes]: lifetimes.html [Loops (`for`)]: loops.html#for [Loops (`loop`)]: loops.html#loop diff --git a/src/doc/reference.md b/src/doc/reference.md index 98238e27133ca..711a13d21f0eb 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2858,8 +2858,8 @@ assert_eq!(x, y); ### Unary operator expressions -Rust defines the following unary operators. They are all written as prefix operators, -before the expression they apply to. +Rust defines the following unary operators. With the exception of `?`, they are +all written as prefix operators, before the expression they apply to. * `-` : Negation. Signed integer types and floating-point types support negation. It @@ -2888,6 +2888,10 @@ before the expression they apply to. If the `&` or `&mut` operators are applied to an rvalue, a temporary value is created; the lifetime of this temporary value is defined by [syntactic rules](#temporary-lifetimes). +* `?` + : Propagating errors if applied to `Err(_)` and unwrapping if + applied to `Ok(_)`. Only works on the `Result` type, + and written in postfix notation. ### Binary operator expressions diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index cae46a0dd0feb..23c2e2142c751 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -520,8 +520,7 @@ macro_rules! unimplemented { /// into libsyntax itself. /// /// For more information, see documentation for `std`'s macros. -#[cfg(dox)] -pub mod builtin { +mod builtin { /// The core macro for formatted string creation & output. /// /// For more information, see the documentation for [`std::format_args!`]. @@ -529,6 +528,7 @@ pub mod builtin { /// [`std::format_args!`]: ../std/macro.format_args.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) } @@ -540,6 +540,7 @@ pub mod builtin { /// [`std::env!`]: ../std/macro.env.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) } /// Optionally inspect an environment variable at compile time. @@ -549,6 +550,7 @@ pub mod builtin { /// [`std::option_env!`]: ../std/macro.option_env.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) } /// Concatenate identifiers into one identifier. @@ -558,6 +560,7 @@ pub mod builtin { /// [`std::concat_idents!`]: ../std/macro.concat_idents.html #[unstable(feature = "concat_idents_macro", issue = "29599")] #[macro_export] + #[cfg(dox)] macro_rules! concat_idents { ($($e:ident),*) => ({ /* compiler built-in */ }) } @@ -569,6 +572,7 @@ pub mod builtin { /// [`std::concat!`]: ../std/macro.concat.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) } /// A macro which expands to the line number on which it was invoked. @@ -578,6 +582,7 @@ pub mod builtin { /// [`std::line!`]: ../std/macro.line.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! line { () => ({ /* compiler built-in */ }) } /// A macro which expands to the column number on which it was invoked. @@ -587,6 +592,7 @@ pub mod builtin { /// [`std::column!`]: ../std/macro.column.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! column { () => ({ /* compiler built-in */ }) } /// A macro which expands to the file name from which it was invoked. @@ -596,6 +602,7 @@ pub mod builtin { /// [`std::file!`]: ../std/macro.file.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! file { () => ({ /* compiler built-in */ }) } /// A macro which stringifies its argument. @@ -605,6 +612,7 @@ pub mod builtin { /// [`std::stringify!`]: ../std/macro.stringify.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } /// Includes a utf8-encoded file as a string. @@ -614,6 +622,7 @@ pub mod builtin { /// [`std::include_str!`]: ../std/macro.include_str.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) } /// Includes a file as a reference to a byte array. @@ -623,6 +632,7 @@ pub mod builtin { /// [`std::include_bytes!`]: ../std/macro.include_bytes.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) } /// Expands to a string that represents the current module path. @@ -632,6 +642,7 @@ pub mod builtin { /// [`std::module_path!`]: ../std/macro.module_path.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! module_path { () => ({ /* compiler built-in */ }) } /// Boolean evaluation of configuration flags. @@ -641,6 +652,7 @@ pub mod builtin { /// [`std::cfg!`]: ../std/macro.cfg.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) } /// Parse a file as an expression or an item according to the context. @@ -650,5 +662,6 @@ pub mod builtin { /// [`std::include!`]: ../std/macro.include.html #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] + #[cfg(dox)] macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index ce882c48377f7..9db9e8812fd05 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1222,8 +1222,8 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( obligation, &closure_type.sig, util::TupleArgumentsFlag::No) - .with_addl_obligations(obligations) .with_addl_obligations(vtable.nested) + .with_addl_obligations(obligations) } fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 4d3361c1873f0..0f987933df980 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -689,9 +689,8 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D let lldiscr = C_integral(Type::from_integer(ccx, d), discr.0 as u64, true); let mut vals_with_discr = vec![lldiscr]; vals_with_discr.extend_from_slice(vals); - let mut contents = build_const_struct(ccx, &variant, - &vals_with_discr[..]); - let needed_padding = l.size(dl).bytes() - variant.min_size.bytes(); + let mut contents = build_const_struct(ccx, &variant, &vals_with_discr[..]); + let needed_padding = l.size(dl).bytes() - variant.stride().bytes(); if needed_padding > 0 { contents.push(padding(ccx, needed_padding)); } @@ -704,8 +703,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D } layout::Univariant { ref variant, .. } => { assert_eq!(discr, Disr(0)); - let contents = build_const_struct(ccx, - &variant, vals); + let contents = build_const_struct(ccx, &variant, vals); C_struct(ccx, &contents[..], variant.packed) } layout::Vector { .. } => { @@ -722,8 +720,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D } layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => { if discr.0 == nndiscr { - C_struct(ccx, &build_const_struct(ccx, &nonnull, vals), - false) + C_struct(ccx, &build_const_struct(ccx, &nonnull, vals), false) } else { let fields = compute_fields(ccx, t, nndiscr as usize, false); let vals = fields.iter().map(|&ty| { @@ -731,8 +728,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D // field; see #8506. C_null(type_of::sizing_type_of(ccx, ty)) }).collect::>(); - C_struct(ccx, &build_const_struct(ccx, &nonnull, &vals[..]), - false) + C_struct(ccx, &build_const_struct(ccx, &nonnull, &vals[..]), false) } } _ => bug!("trans_const: cannot handle type {} repreented as {:#?}", t, l) diff --git a/src/test/run-pass/issue-38002.rs b/src/test/run-pass/issue-38002.rs new file mode 100644 index 0000000000000..489d35e9147ad --- /dev/null +++ b/src/test/run-pass/issue-38002.rs @@ -0,0 +1,45 @@ +// Copyright 2016 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. + +// Check that constant ADTs are translated OK, part k of N. + +#![feature(slice_patterns)] + +enum Bar { + C +} + +enum Foo { + A {}, + B { + y: usize, + z: Bar + }, +} + +const LIST: [(usize, Foo); 2] = [ + (51, Foo::B { y: 42, z: Bar::C }), + (52, Foo::B { y: 45, z: Bar::C }), +]; + +pub fn main() { + match LIST { + [ + (51, Foo::B { y: 42, z: Bar::C }), + (52, Foo::B { y: 45, z: Bar::C }) + ] => {} + _ => { + // I would want to print the enum here, but if + // the discriminant is garbage this causes an + // `unreachable` and silent process exit. + panic!("trivial match failed") + } + } +} diff --git a/src/test/run-pass/issue-38033.rs b/src/test/run-pass/issue-38033.rs new file mode 100644 index 0000000000000..50549dc8b2380 --- /dev/null +++ b/src/test/run-pass/issue-38033.rs @@ -0,0 +1,88 @@ +// Copyright 2016 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. + +use std::marker; +use std::mem; + +fn main() { + let workers = (0..0).map(|_| result::()); + drop(join_all(workers).poll()); +} + +trait Future { + type Item; + type Error; + + fn poll(&mut self) -> Result; +} + +trait IntoFuture { + type Future: Future; + type Item; + type Error; + + fn into_future(self) -> Self::Future; +} + +impl IntoFuture for F { + type Future = F; + type Item = F::Item; + type Error = F::Error; + + fn into_future(self) -> F { + self + } +} + +struct FutureResult { + _inner: marker::PhantomData<(T, E)>, +} + +fn result() -> FutureResult { + loop {} +} + +impl Future for FutureResult { + type Item = T; + type Error = E; + + fn poll(&mut self) -> Result { + loop {} + } +} + +struct JoinAll + where I: IntoIterator, + I::Item: IntoFuture, +{ + elems: Vec<::Item>, +} + +fn join_all(_: I) -> JoinAll + where I: IntoIterator, + I::Item: IntoFuture, +{ + JoinAll { elems: vec![] } +} + +impl Future for JoinAll + where I: IntoIterator, + I::Item: IntoFuture, +{ + type Item = Vec<::Item>; + type Error = ::Error; + + fn poll(&mut self) -> Result { + let elems = mem::replace(&mut self.elems, Vec::new()); + Ok(elems.into_iter().map(|e| { + e + }).collect::>()) + } +}