diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 16f4b29dcceef..de785b13d067d 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -272,6 +272,12 @@ impl Step for TheBook { name: INTERNER.intern_string(format!("{}/second-edition", name)), }); + // build book 2018 edition + builder.ensure(Rustbook { + target, + name: INTERNER.intern_string(format!("{}/2018-edition", name)), + }); + // build the version info page and CSS builder.ensure(Standalone { compiler, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index e53fef0678613..f64161fb0272c 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -592,12 +592,20 @@ impl Build { Path::new(llvm_bindir.trim()).join(exe("FileCheck", &*target)) } else { let base = self.llvm_out(self.config.build).join("build"); - let exe = exe("FileCheck", &*target); - if !self.config.ninja && self.config.build.contains("msvc") { - base.join("Release/bin").join(exe) + let base = if !self.config.ninja && self.config.build.contains("msvc") { + if self.config.llvm_optimize { + if self.config.llvm_release_debuginfo { + base.join("RelWithDebInfo") + } else { + base.join("Release") + } + } else { + base.join("Debug") + } } else { - base.join("bin").join(exe) - } + base + }; + base.join("bin").join(exe("FileCheck", &*target)) } } diff --git a/src/doc/book b/src/doc/book index f51127530d46b..36d65d00164d1 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3 +Subproject commit 36d65d00164d1750f6fa7f8b0f52dabc3fea500b diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 4427ac004f97a..161493f389226 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -119,8 +119,8 @@ pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; -#[unstable(feature = "from_ref", issue = "45703")] -pub use core::slice::{from_ref, from_ref_mut}; +#[stable(feature = "from_ref", since = "1.28.0")] +pub use core::slice::{from_ref, from_mut}; #[unstable(feature = "slice_get_slice", issue = "35729")] pub use core::slice::SliceIndex; #[unstable(feature = "exact_chunks", issue = "47115")] diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9a46c6106db57..d50ad580ed574 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1257,7 +1257,7 @@ impl<'a, T: ?Sized + fmt::Display> fmt::Display for RefMut<'a, T> { /// To assist with proper design, the following scenarios are explicitly declared legal /// for single-threaded code: /// -/// 1. A `&T` reference can be released to safe code and there it can co-exit with other `&T` +/// 1. A `&T` reference can be released to safe code and there it can co-exist with other `&T` /// references, but not with a `&mut T` /// /// 2. A `&mut T` reference may be released to safe code provided neither other `&mut T` nor `&T` diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 77b5488084d99..d37629ced11db 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -119,6 +119,9 @@ #![feature(powerpc_target_feature)] #![feature(mips_target_feature)] #![feature(aarch64_target_feature)] +#![feature(const_slice_len)] +#![feature(const_str_as_bytes)] +#![feature(const_str_len)] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 3b19a401859ee..ab986e4c86d88 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -59,9 +59,16 @@ mod rotate; mod sort; #[repr(C)] -struct Repr { - pub data: *const T, - pub len: usize, +union Repr<'a, T: 'a> { + rust: &'a [T], + rust_mut: &'a mut [T], + raw: FatPtr, +} + +#[repr(C)] +struct FatPtr { + data: *const T, + len: usize, } // @@ -119,9 +126,10 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn len(&self) -> usize { + #[rustc_const_unstable(feature = "const_slice_len")] + pub const fn len(&self) -> usize { unsafe { - mem::transmute::<&[T], Repr>(self).len + Repr { rust: self }.raw.len } } @@ -135,7 +143,8 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_slice_len")] + pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -418,7 +427,8 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn as_ptr(&self) -> *const T { + #[rustc_const_unstable(feature = "const_slice_as_ptr")] + pub const fn as_ptr(&self) -> *const T { self as *const [T] as *const T } @@ -3856,8 +3866,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] { - mem::transmute(Repr { data: p, len: len }) +pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { + Repr { raw: FatPtr { data, len } }.rust } /// Performs the same functionality as `from_raw_parts`, except that a mutable @@ -3869,12 +3879,12 @@ pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] { /// `from_raw_parts`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { - mem::transmute(Repr { data: p, len: len }) +pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { + Repr { raw: FatPtr { data, len} }.rust_mut } /// Converts a reference to T into a slice of length 1 (without copying). -#[unstable(feature = "from_ref", issue = "45703")] +#[stable(feature = "from_ref", since = "1.28.0")] pub fn from_ref(s: &T) -> &[T] { unsafe { from_raw_parts(s, 1) @@ -3882,8 +3892,8 @@ pub fn from_ref(s: &T) -> &[T] { } /// Converts a reference to T into a slice of length 1 (without copying). -#[unstable(feature = "from_ref", issue = "45703")] -pub fn from_ref_mut(s: &mut T) -> &mut [T] { +#[stable(feature = "from_ref", since = "1.28.0")] +pub fn from_mut(s: &mut T) -> &mut [T] { unsafe { from_raw_parts_mut(s, 1) } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 82bead0ab4676..70aaf10f4213e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2166,7 +2166,8 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn len(&self) -> usize { + #[rustc_const_unstable(feature = "const_str_len")] + pub const fn len(&self) -> usize { self.as_bytes().len() } @@ -2185,7 +2186,8 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_str_len")] + pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2242,8 +2244,15 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - pub fn as_bytes(&self) -> &[u8] { - unsafe { &*(self as *const str as *const [u8]) } + #[rustc_const_unstable(feature="const_str_as_bytes")] + pub const fn as_bytes(&self) -> &[u8] { + unsafe { + union Slices<'a> { + str: &'a str, + slice: &'a [u8], + } + Slices { str: self }.slice + } } /// Converts a mutable string slice to a mutable byte slice. To convert the @@ -2303,7 +2312,8 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn as_ptr(&self) -> *const u8 { + #[rustc_const_unstable(feature = "const_str_as_ptr")] + pub const fn as_ptr(&self) -> *const u8 { self as *const str as *const u8 } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 66b08f5c3b00b..ffb8031b83bc6 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -948,7 +948,7 @@ impl<'tcx> TerminatorKind<'tcx> { Drop { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { - Some(t).into_iter().chain(slice::from_ref_mut(u)) + Some(t).into_iter().chain(slice::from_mut(u)) } SwitchInt { ref mut targets, .. } => { None.into_iter().chain(&mut targets[..]) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c3b5b8e6fb35f..7a52a5cbf5acc 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3356,13 +3356,28 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { predicate: predicate.value })) }).collect(); + // We are performing deduplication here to avoid exponential blowups // (#38528) from happening, but the real cause of the duplication is // unknown. What we know is that the deduplication avoids exponential - // amount of predicates being propogated when processing deeply nested + // amount of predicates being propagated when processing deeply nested // types. - let mut seen = FxHashSet(); - predicates.retain(|i| seen.insert(i.clone())); + // + // This code is hot enough that it's worth avoiding the allocation + // required for the FxHashSet when possible. Special-casing lengths 0, + // 1 and 2 covers roughly 75--80% of the cases. + if predicates.len() <= 1 { + // No possibility of duplicates. + } else if predicates.len() == 2 { + // Only two elements. Drop the second if they are equal. + if predicates[0] == predicates[1] { + predicates.truncate(1); + } + } else { + // Three or more elements. Use a general deduplication process. + let mut seen = FxHashSet(); + predicates.retain(|i| seen.insert(i.clone())); + } self.infcx().plug_leaks(skol_map, snapshot, predicates) } } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 065b7939ac362..c43b7e95b35e3 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -105,6 +105,10 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// start executing the query, or it returns with the result of the query. /// If the query is executing elsewhere, this will wait for it. /// If the query panicked, this will silently panic. + /// + /// This function is inlined because that results in a noticeable speedup + /// for some compile-time benchmarks. + #[inline(always)] pub(super) fn try_get( tcx: TyCtxt<'a, 'tcx, '_>, span: Span, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 5d6d4619c5e05..4ec75d3b5ec74 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1853,6 +1853,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { for index in ii { if flow_state.ever_inits.contains(index) { self.used_mut.insert(*local); + break; } } } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index ac37937509eac..4719f00b4d259 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -82,7 +82,8 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprLoop(ref b, _, source) => { self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b)); } - hir::ExprClosure(.., b, _, _) => { + hir::ExprClosure(_, ref function_decl, b, _, _) => { + self.visit_fn_decl(&function_decl); self.with_context(Closure, |v| v.visit_nested_body(b)); } hir::ExprBlock(ref b, Some(_label)) => { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 5b3484dcccb85..76219c6971b22 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -537,8 +537,9 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let mut selcx = traits::SelectionContext::new(self); - // Use a FIFO queue for this custom fulfillment procedure. - let mut queue = VecDeque::new(); + // Use a FIFO queue for this custom fulfillment procedure. (The maximum + // length is almost always 1.) + let mut queue = VecDeque::with_capacity(1); // Create an obligation for `Source: CoerceUnsized`. let cause = ObligationCause::misc(self.cause.span, self.body_id); diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index d5e0f95ddf435..dceb04a7daa2b 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -138,7 +138,7 @@ impl Cfg { /// Renders the configuration for human display, as a short HTML description. pub(crate) fn render_short_html(&self) -> String { - let mut msg = ShortHtml(self).to_string(); + let mut msg = Html(self, true).to_string(); if self.should_capitalize_first_letter() { if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { msg[i .. i+1].make_ascii_uppercase(); @@ -155,7 +155,7 @@ impl Cfg { "on" }; - let mut msg = format!("This is supported {} {}", on, Html(self)); + let mut msg = format!("This is supported {} {}", on, Html(self, false)); if self.should_append_only_to_description() { msg.push_str(" only"); } @@ -265,7 +265,9 @@ impl ops::BitOr for Cfg { } } -struct Html<'a>(&'a Cfg); +/// Pretty-print wrapper for a `Cfg`. Also indicates whether the "short-form" rendering should be +/// used. +struct Html<'a>(&'a Cfg, bool); fn write_with_opt_paren( fmt: &mut fmt::Formatter, @@ -295,12 +297,12 @@ impl<'a> fmt::Display for Html<'a> { }; for (i, sub_cfg) in sub_cfgs.iter().enumerate() { fmt.write_str(if i == 0 { "neither " } else { separator })?; - write_with_opt_paren(fmt, !sub_cfg.is_all(), Html(sub_cfg))?; + write_with_opt_paren(fmt, !sub_cfg.is_all(), Html(sub_cfg, self.1))?; } Ok(()) } - ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Html(simple)), - ref c => write!(fmt, "not ({})", Html(c)), + ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Html(simple, self.1)), + ref c => write!(fmt, "not ({})", Html(c, self.1)), }, Cfg::Any(ref sub_cfgs) => { @@ -313,7 +315,7 @@ impl<'a> fmt::Display for Html<'a> { if i != 0 { fmt.write_str(separator)?; } - write_with_opt_paren(fmt, !sub_cfg.is_all(), Html(sub_cfg))?; + write_with_opt_paren(fmt, !sub_cfg.is_all(), Html(sub_cfg, self.1))?; } Ok(()) }, @@ -323,7 +325,7 @@ impl<'a> fmt::Display for Html<'a> { if i != 0 { fmt.write_str(" and ")?; } - write_with_opt_paren(fmt, !sub_cfg.is_simple(), Html(sub_cfg))?; + write_with_opt_paren(fmt, !sub_cfg.is_simple(), Html(sub_cfg, self.1))?; } Ok(()) }, @@ -390,7 +392,11 @@ impl<'a> fmt::Display for Html<'a> { ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian), ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits), ("target_feature", Some(feat)) => - return write!(fmt, "target feature {}", feat), + if self.1 { + return write!(fmt, "{}", feat); + } else { + return write!(fmt, "target feature {}", feat); + }, _ => "", }; if !human_readable.is_empty() { @@ -405,19 +411,6 @@ impl<'a> fmt::Display for Html<'a> { } } -struct ShortHtml<'a>(&'a Cfg); - -impl<'a> fmt::Display for ShortHtml<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self.0 { - Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => { - write!(fmt, "{}", vendor) - }, - ref cfg => write!(fmt, "{}", Html(cfg)), - } - } -} - #[cfg(test)] mod test { use super::Cfg; @@ -740,6 +733,13 @@ mod test { name_value_cfg("target_feature", "sse2").render_short_html(), "sse2" ); + assert_eq!( + ( + name_value_cfg("target_arch", "x86_64") & + name_value_cfg("target_feature", "sse2") + ).render_short_html(), + "x86-64 and sse2" + ); }) } @@ -818,6 +818,14 @@ mod test { name_value_cfg("target_feature", "sse2").render_long_html(), "This is supported with target feature sse2 only." ); + assert_eq!( + ( + name_value_cfg("target_arch", "x86_64") & + name_value_cfg("target_feature", "sse2") + ).render_long_html(), + "This is supported on x86-64 and target feature \ + sse2 only." + ); }) } } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index d6b3ab26af8ae..4939505c53144 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1010,6 +1010,8 @@ span.since { pre.rust { position: relative; + tab-width: 4; + -moz-tab-width: 4; } .search-failed { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 729ad491fd544..62d007b424025 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5807,9 +5807,18 @@ impl<'a> Parser<'a> { return Err(err); } } - _ => return Err(self.span_fatal_help(self.span, - &format!("expected `,`, or `}}`, found `{}`", self.this_token_to_string()), - "struct fields should be separated by commas")), + _ => { + let sp = self.sess.codemap().next_point(self.prev_span); + let mut err = self.struct_span_err(sp, &format!("expected `,`, or `}}`, found `{}`", + self.this_token_to_string())); + if self.token.is_ident() { + // This is likely another field; emit the diagnostic and keep going + err.span_suggestion(sp, "try adding a comma", ",".into()); + err.emit(); + } else { + return Err(err) + } + } } Ok(a_var) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 034be6a6864ce..ed28d5f33b921 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -22,6 +22,7 @@ use serialize::{Decodable, Decoder, Encodable, Encoder}; use symbol::keywords; use syntax::parse::parse_stream_from_source_str; use syntax_pos::{self, Span, FileName}; +use syntax_pos::symbol::{self, Symbol}; use tokenstream::{TokenStream, TokenTree}; use tokenstream; @@ -478,7 +479,13 @@ impl Token { _ => return None, }, SingleQuote => match joint { - Ident(ident, false) => Lifetime(ident), + Ident(ident, false) => { + let name = Symbol::intern(&format!("'{}", ident)); + Lifetime(symbol::Ident { + name, + span: ident.span, + }) + } _ => return None, }, diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index 99e7bb4baeff4..cbd6a257b77e8 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -76,8 +76,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur } } StaticEnum(..) => { - cx.span_err(trait_span, - "`Default` cannot be derived for enums, only structs"); + span_err_if_not_stage0!(cx, trait_span, E0665, + "`Default` cannot be derived for enums, only structs"); // let compilation continue cx.expr_usize(trait_span, 0) } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 6bc4ee0b399f9..0dd55f8d77738 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -19,6 +19,17 @@ use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; +macro_rules! span_err_if_not_stage0 { + ($cx:expr, $sp:expr, $code:ident, $text:tt) => { + #[cfg(not(stage0))] { + span_err!($cx, $sp, $code, $text) + } + #[cfg(stage0)] { + $cx.span_err($sp, $text) + } + } +} + macro path_local($x:ident) { generic::ty::Path::new_local(stringify!($x)) } diff --git a/src/libsyntax_ext/diagnostics.rs b/src/libsyntax_ext/diagnostics.rs index 33ae24c37e53f..f99a6c3c2166d 100644 --- a/src/libsyntax_ext/diagnostics.rs +++ b/src/libsyntax_ext/diagnostics.rs @@ -82,7 +82,7 @@ A clobber was surrounded by braces in the `asm` macro. Erroneous code example: -```compile_fail,E0663 +```compile_fail,E0664 asm!("mov $$0x200, %eax" : : @@ -94,4 +94,38 @@ Considering that this would be a long explanation, we instead recommend you to take a look at the unstable book: https://doc.rust-lang.org/unstable-book/language-features/asm.html "##, + +E0665: r##" +The `Default` trait was derived on an enum. + +Erroneous code example: + +```compile_fail,E0665 +#[derive(Default)] +enum Food { + Sweet, + Salty, +} +``` + +The `Default` cannot be derived on an enum for the simple reason that the +compiler doesn't know which value to pick by default whereas it can for a +struct as long as all its fields implement the `Default` trait as well. + +If you still want to implement `Default` on your enum, you'll have to do it "by +hand": + +``` +enum Food { + Sweet, + Salty, +} + +impl Default for Food { + fn default() -> Food { + Food::Sweet + } +} +``` +"##, } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 15fcfac13adf2..af3ef181c59dc 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -31,8 +31,12 @@ extern crate rustc_target; mod diagnostics; -mod assert; +#[macro_use] +// for custom_derive +pub mod deriving; + mod asm; +mod assert; mod cfg; mod compile_error; mod concat; @@ -46,8 +50,6 @@ mod trace_macros; pub mod proc_macro_registrar; -// for custom_derive -pub mod deriving; pub mod proc_macro_impl; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/gen-lifetime-token.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/gen-lifetime-token.rs new file mode 100644 index 0000000000000..e288050a928b0 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/gen-lifetime-token.rs @@ -0,0 +1,35 @@ +// Copyright 2018 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. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro)] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn bar(_input: TokenStream) -> TokenStream { + let mut ret = Vec::::new(); + ret.push(Ident::new("static", Span::call_site()).into()); + ret.push(Ident::new("FOO", Span::call_site()).into()); + ret.push(Punct::new(':', Spacing::Alone).into()); + ret.push(Punct::new('&', Spacing::Alone).into()); + ret.push(Punct::new('\'', Spacing::Joint).into()); + ret.push(Ident::new("static", Span::call_site()).into()); + ret.push(Ident::new("i32", Span::call_site()).into()); + ret.push(Punct::new('=', Spacing::Alone).into()); + ret.push(Punct::new('&', Spacing::Alone).into()); + ret.push(Literal::i32_unsuffixed(1).into()); + ret.push(Punct::new(';', Spacing::Alone).into()); + ret.into_iter().collect() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/gen-lifetime-token.rs b/src/test/run-pass-fulldeps/proc-macro/gen-lifetime-token.rs new file mode 100644 index 0000000000000..539e3aa8ecbb2 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/gen-lifetime-token.rs @@ -0,0 +1,22 @@ +// Copyright 2018 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. + +// aux-build:gen-lifetime-token.rs + +#![feature(proc_macro)] + +extern crate gen_lifetime_token as bar; + +bar::bar!(); + +fn main() { + let x: &'static i32 = FOO; + assert_eq!(*x, 1); +} diff --git a/src/test/ui/E0665.rs b/src/test/ui/E0665.rs new file mode 100644 index 0000000000000..8888bedf01687 --- /dev/null +++ b/src/test/ui/E0665.rs @@ -0,0 +1,20 @@ +// Copyright 2018 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. + +// ignore-stage1 + +#[derive(Default)] //~ ERROR E0665 +enum Food { + Sweet, + Salty, +} + +fn main() { +} diff --git a/src/test/ui/E0665.stderr b/src/test/ui/E0665.stderr new file mode 100644 index 0000000000000..c97e9e5ea89d0 --- /dev/null +++ b/src/test/ui/E0665.stderr @@ -0,0 +1,9 @@ +error[E0665]: `Default` cannot be derived for enums, only structs + --> $DIR/E0665.rs:13:10 + | +LL | #[derive(Default)] //~ ERROR E0665 + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0665`. diff --git a/src/test/ui/const-eval/strlen.rs b/src/test/ui/const-eval/strlen.rs new file mode 100644 index 0000000000000..dfa41c491fa89 --- /dev/null +++ b/src/test/ui/const-eval/strlen.rs @@ -0,0 +1,33 @@ +// Copyright 2018 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. + +// run-pass + +#![feature(const_str_len, const_str_as_bytes)] + +const S: &str = "foo"; +pub const B: &[u8] = S.as_bytes(); + +pub fn foo() -> [u8; S.len()] { + let mut buf = [0; S.len()]; + for (i, &c) in S.as_bytes().iter().enumerate() { + buf[i] = c; + } + buf +} + +fn main() { + assert_eq!(&foo()[..], b"foo"); + assert_eq!(foo().len(), S.len()); + const LEN: usize = S.len(); + assert_eq!(LEN, S.len()); + assert_eq!(B, foo()); + assert_eq!(B, b"foo"); +} diff --git a/src/test/ui/struct-missing-comma.rs b/src/test/ui/struct-missing-comma.rs new file mode 100644 index 0000000000000..87ae8ab26051a --- /dev/null +++ b/src/test/ui/struct-missing-comma.rs @@ -0,0 +1,23 @@ +// Copyright 2018 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. + +// compile-flags: -Z parse-only + +// Issue #50636 + +struct S { + foo: u32 //~ expected `,`, or `}`, found `bar` + // ~^ HELP try adding a comma: ',' + bar: u32 +} + +fn main() { + let s = S { foo: 5, bar: 6 }; +} diff --git a/src/test/ui/struct-missing-comma.stderr b/src/test/ui/struct-missing-comma.stderr new file mode 100644 index 0000000000000..28283bfb71364 --- /dev/null +++ b/src/test/ui/struct-missing-comma.stderr @@ -0,0 +1,8 @@ +error: expected `,`, or `}`, found `bar` + --> $DIR/struct-missing-comma.rs:16:13 + | +LL | foo: u32 //~ expected `,`, or `}`, found `bar` + | ^ help: try adding a comma: `,` + +error: aborting due to previous error +