Auto merge of #50968 - kennytm:rollup, r=kennytm
Rollup of 15 pull requests Successful merges: - #50846 (Add E0665) - #50849 (CheckLoopVisitor: also visit closure arguments) - #50863 (Make `[T]::len` and `str::len` const fn) - #50875 (rustdoc: use "short form" doc(cfg) printing even when combined with other conditionals) - #50913 (Fix typo in cell.rs) - #50914 (Issue #50636: Improve error diagnostic with missing commas after struct fields.) - #50931 (Inline `try_get`.) - #50932 (Optimize seen Predicate filtering.) - #50945 (Stabilize feature from_ref) - #50946 (rustc: Fix procedural macros generating lifetime tokens) - #50947 (rustdoc: set tab width in rust source blocks) - #50952 (Add the 2018 edition of the book to doc.rust-lang.org) - #50958 (Micro-optimization on PR#50697) - #50961 (Fix FileCheck finding with MSVC) - #50963 (Right-size the `VecDeque` in `coerce_unsized`.) Failed merges:
This commit is contained in:
commit
e0635188ed
@ -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,
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3
|
||||
Subproject commit 36d65d00164d1750f6fa7f8b0f52dabc3fea500b
|
@ -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")]
|
||||
|
@ -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`
|
||||
|
@ -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)]
|
||||
|
@ -59,9 +59,16 @@ mod rotate;
|
||||
mod sort;
|
||||
|
||||
#[repr(C)]
|
||||
struct Repr<T> {
|
||||
pub data: *const T,
|
||||
pub len: usize,
|
||||
union Repr<'a, T: 'a> {
|
||||
rust: &'a [T],
|
||||
rust_mut: &'a mut [T],
|
||||
raw: FatPtr<T>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct FatPtr<T> {
|
||||
data: *const T,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
//
|
||||
@ -119,9 +126,10 @@ impl<T> [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<T>>(self).len
|
||||
Repr { rust: self }.raw.len
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +143,8 @@ impl<T> [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> [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<T>(s: &T) -> &[T] {
|
||||
unsafe {
|
||||
from_raw_parts(s, 1)
|
||||
@ -3882,8 +3892,8 @@ pub fn from_ref<T>(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<T>(s: &mut T) -> &mut [T] {
|
||||
#[stable(feature = "from_ref", since = "1.28.0")]
|
||||
pub fn from_mut<T>(s: &mut T) -> &mut [T] {
|
||||
unsafe {
|
||||
from_raw_parts_mut(s, 1)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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[..])
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)) => {
|
||||
|
@ -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<Target>`.
|
||||
let cause = ObligationCause::misc(self.cause.span, self.body_id);
|
||||
|
@ -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 {} <strong>{}</strong>", on, Html(self));
|
||||
let mut msg = format!("This is supported {} <strong>{}</strong>", 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<T: fmt::Display>(
|
||||
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 <code>{}</code>", feat),
|
||||
if self.1 {
|
||||
return write!(fmt, "<code>{}</code>", feat);
|
||||
} else {
|
||||
return write!(fmt, "target feature <code>{}</code>", 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, "<code>{}</code>", 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(),
|
||||
"<code>sse2</code>"
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
name_value_cfg("target_arch", "x86_64") &
|
||||
name_value_cfg("target_feature", "sse2")
|
||||
).render_short_html(),
|
||||
"x86-64 and <code>sse2</code>"
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
@ -818,6 +818,14 @@ mod test {
|
||||
name_value_cfg("target_feature", "sse2").render_long_html(),
|
||||
"This is supported with <strong>target feature <code>sse2</code></strong> only."
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
name_value_cfg("target_arch", "x86_64") &
|
||||
name_value_cfg("target_feature", "sse2")
|
||||
).render_long_html(),
|
||||
"This is supported on <strong>x86-64 and target feature \
|
||||
<code>sse2</code></strong> only."
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1010,6 +1010,8 @@ span.since {
|
||||
|
||||
pre.rust {
|
||||
position: relative;
|
||||
tab-width: 4;
|
||||
-moz-tab-width: 4;
|
||||
}
|
||||
|
||||
.search-failed {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::<TokenTree>::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()
|
||||
}
|
22
src/test/run-pass-fulldeps/proc-macro/gen-lifetime-token.rs
Normal file
22
src/test/run-pass-fulldeps/proc-macro/gen-lifetime-token.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
|
||||
}
|
20
src/test/ui/E0665.rs
Normal file
20
src/test/ui/E0665.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
|
||||
}
|
9
src/test/ui/E0665.stderr
Normal file
9
src/test/ui/E0665.stderr
Normal file
@ -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`.
|
33
src/test/ui/const-eval/strlen.rs
Normal file
33
src/test/ui/const-eval/strlen.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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");
|
||||
}
|
23
src/test/ui/struct-missing-comma.rs
Normal file
23
src/test/ui/struct-missing-comma.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 };
|
||||
}
|
8
src/test/ui/struct-missing-comma.stderr
Normal file
8
src/test/ui/struct-missing-comma.stderr
Normal file
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user