diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 907983d43ade7..298330869b684 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -125,7 +125,9 @@ def v(*args): "arm-unknown-linux-musleabihf install directory") v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root", "armv5te-unknown-linux-musleabi install directory") -v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root", +v("musl-root-armv7", "target.armv7-unknown-linux-musleabi.musl-root", + "armv7-unknown-linux-musleabi install directory") +v("musl-root-armv7hf", "target.armv7-unknown-linux-musleabihf.musl-root", "armv7-unknown-linux-musleabihf install directory") v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root", "aarch64-unknown-linux-musl install directory") diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index c2e64ef51a746..c8ea3157dc92b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -125,7 +125,7 @@ use std::os::unix::fs::symlink as symlink_file; use std::os::windows::fs::symlink_file; use build_helper::{ - mtime, output, run_silent, run_suppressed, t, try_run_silent, try_run_suppressed, + mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, }; use filetime::FileTime; @@ -682,7 +682,7 @@ impl Build { fn run(&self, cmd: &mut Command) { if self.config.dry_run { return; } self.verbose(&format!("running: {:?}", cmd)); - run_silent(cmd) + run(cmd) } /// Runs a command, printing out nice contextual information if it fails. @@ -698,7 +698,7 @@ impl Build { fn try_run(&self, cmd: &mut Command) -> bool { if self.config.dry_run { return true; } self.verbose(&format!("running: {:?}", cmd)); - try_run_silent(cmd) + try_run(cmd) } /// Runs a command, printing out nice contextual information if it fails. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index fec7f73f3b7e5..1f81efd16a7e4 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1527,7 +1527,7 @@ impl Step for RustcGuide { fn run(self, builder: &Builder<'_>) { let src = builder.src.join("src/doc/rustc-guide"); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - try_run_quiet(builder, rustbook_cmd.arg("linkcheck").arg(&src)); + try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)); } } diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index c30307f3a1b28..a1aa18922b5c5 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -45,18 +45,19 @@ pub fn restore_library_path() { } } -pub fn run(cmd: &mut Command) { +/// Run the command, printing what we are running. +pub fn run_verbose(cmd: &mut Command) { println!("running: {:?}", cmd); - run_silent(cmd); + run(cmd); } -pub fn run_silent(cmd: &mut Command) { - if !try_run_silent(cmd) { +pub fn run(cmd: &mut Command) { + if !try_run(cmd) { std::process::exit(1); } } -pub fn try_run_silent(cmd: &mut Command) -> bool { +pub fn try_run(cmd: &mut Command) -> bool { let status = match cmd.status() { Ok(status) => status, Err(e) => fail(&format!( diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index ce11cd846f5ed..ae2ea8ef95a6a 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -64,7 +64,7 @@ RUN env \ env \ CC=arm-linux-gnueabihf-gcc CFLAGS="-march=armv7-a" \ CXX=arm-linux-gnueabihf-g++ CXXFLAGS="-march=armv7-a" \ - bash musl.sh armv7 && \ + bash musl.sh armv7hf && \ env \ CC=aarch64-linux-gnu-gcc \ CXX=aarch64-linux-gnu-g++ \ @@ -137,7 +137,7 @@ ENV RUST_CONFIGURE_ARGS \ --musl-root-armv5te=/musl-armv5te \ --musl-root-arm=/musl-arm \ --musl-root-armhf=/musl-armhf \ - --musl-root-armv7=/musl-armv7 \ + --musl-root-armv7hf=/musl-armv7hf \ --musl-root-aarch64=/musl-aarch64 \ --musl-root-mips=/musl-mips \ --musl-root-mipsel=/musl-mipsel \ diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index 53523d41a5580..2ae6c58941e4c 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -8,7 +8,8 @@ RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ build-essential \ - gcc-multilib \ +# gcc-multilib can not be installed together with gcc-arm-linux-gnueabi + gcc-7-multilib \ libedit-dev \ libgmp-dev \ libisl-dev \ @@ -21,11 +22,20 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no unzip \ # Needed for apt-key to work: dirmngr \ - gpg-agent + gpg-agent \ + g++-7-arm-linux-gnueabi RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2 main' +WORKDIR /build +COPY scripts/musl.sh /build +RUN env \ + CC=arm-linux-gnueabi-gcc-7 CFLAGS="-march=armv7-a" \ + CXX=arm-linux-gnueabi-g++-7 CXXFLAGS="-march=armv7-a" \ + bash musl.sh armv7 && \ + rm -rf /build/* + WORKDIR /tmp COPY dist-various-2/shared.sh /tmp/ COPY dist-various-2/build-cloudabi-toolchain.sh /tmp/ @@ -58,7 +68,11 @@ ENV \ CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-g++ \ AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \ CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \ - CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ + CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ \ + CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-7 \ + CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-7 \ + CC=gcc-7 \ + CXX=g++-7 ENV CARGO_TARGET_X86_64_FUCHSIA_AR /usr/local/bin/llvm-ar ENV CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS \ @@ -81,9 +95,19 @@ ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda +ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi +ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV X86_FORTANIX_SGX_LIBS="/x86_64-fortanix-unknown-sgx/lib/" +# As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 +# we need asm in the search path for gcc-7 (for gnux32) but not in the search path of the +# cross compilers. +# Luckily one of the folders is /usr/local/include so symlink /usr/include/asm-generic there +RUN ln -s /usr/include/asm-generic /usr/local/include/asm + ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \ - --set target.wasm32-wasi.wasi-root=/wasm32-wasi + --set target.wasm32-wasi.wasi-root=/wasm32-wasi \ + --musl-root-armv7=/musl-armv7 + ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index bb81d7b794bea..86dae985fdb00 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -414,10 +414,10 @@ pub const fn needs_drop() -> bool { intrinsics::needs_drop::() } -/// Creates a value whose bytes are all zero. +/// Returns the value of type `T` represented by the all-zero byte-pattern. /// -/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. -/// It is useful for FFI sometimes, but should generally be avoided. +/// This means that, for example, the padding byte in `(u8, u16)` is not +/// necessarily zeroed. /// /// There is no guarantee that an all-zero byte-pattern represents a valid value of /// some type `T`. For example, the all-zero byte-pattern is not a valid value @@ -425,6 +425,9 @@ pub const fn needs_drop() -> bool { /// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv] /// that there always is a valid value in a variable it considers initialized. /// +/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. +/// It is useful for FFI sometimes, but should generally be avoided. +/// /// [zeroed]: union.MaybeUninit.html#method.zeroed /// [ub]: ../../reference/behavior-considered-undefined.html /// [inv]: union.MaybeUninit.html#initialization-invariant diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 83e24a48ea008..985abaf2c1bd5 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -56,16 +56,20 @@ pub struct Argument<'a> { /// Specification for the formatting of an argument in the format string. #[derive(Copy, Clone, PartialEq)] pub struct FormatSpec<'a> { - /// Optionally specified character to fill alignment with + /// Optionally specified character to fill alignment with. pub fill: Option, - /// Optionally specified alignment + /// Optionally specified alignment. pub align: Alignment, - /// Packed version of various flags provided + /// Packed version of various flags provided. pub flags: u32, - /// The integer precision to use + /// The integer precision to use. pub precision: Count, - /// The string width requested for the resulting format + /// The span of the precision formatting flag (for diagnostics). + pub precision_span: Option, + /// The string width requested for the resulting format. pub width: Count, + /// The span of the width formatting flag (for diagnostics). + pub width_span: Option, /// The descriptor string representing the name of the format desired for /// this argument, this can be empty or any number of characters, although /// it is required to be one word. @@ -282,19 +286,24 @@ impl<'a> Parser<'a> { } /// Optionally consumes the specified character. If the character is not at - /// the current position, then the current iterator isn't moved and false is - /// returned, otherwise the character is consumed and true is returned. + /// the current position, then the current iterator isn't moved and `false` is + /// returned, otherwise the character is consumed and `true` is returned. fn consume(&mut self, c: char) -> bool { - if let Some(&(_, maybe)) = self.cur.peek() { + self.consume_pos(c).is_some() + } + + /// Optionally consumes the specified character. If the character is not at + /// the current position, then the current iterator isn't moved and `None` is + /// returned, otherwise the character is consumed and the current position is + /// returned. + fn consume_pos(&mut self, c: char) -> Option { + if let Some(&(pos, maybe)) = self.cur.peek() { if c == maybe { self.cur.next(); - true - } else { - false + return Some(pos); } - } else { - false } + None } fn to_span_index(&self, pos: usize) -> InnerOffset { @@ -462,7 +471,9 @@ impl<'a> Parser<'a> { align: AlignUnknown, flags: 0, precision: CountImplied, + precision_span: None, width: CountImplied, + width_span: None, ty: &self.input[..0], }; if !self.consume(':') { @@ -499,6 +510,7 @@ impl<'a> Parser<'a> { } // Width and precision let mut havewidth = false; + if self.consume('0') { // small ambiguity with '0$' as a format string. In theory this is a // '0' flag and then an ill-formatted format string with just a '$' @@ -512,17 +524,28 @@ impl<'a> Parser<'a> { } } if !havewidth { - spec.width = self.count(); + let width_span_start = if let Some((pos, _)) = self.cur.peek() { + *pos + } else { + 0 + }; + let (w, sp) = self.count(width_span_start); + spec.width = w; + spec.width_span = sp; } - if self.consume('.') { - if self.consume('*') { + if let Some(start) = self.consume_pos('.') { + if let Some(end) = self.consume_pos('*') { // Resolve `CountIsNextParam`. // We can do this immediately as `position` is resolved later. let i = self.curarg; self.curarg += 1; spec.precision = CountIsParam(i); + spec.precision_span = + Some(self.to_span_index(start).to(self.to_span_index(end + 1))); } else { - spec.precision = self.count(); + let (p, sp) = self.count(start); + spec.precision = p; + spec.precision_span = sp; } } // Optional radix followed by the actual format specifier @@ -551,24 +574,25 @@ impl<'a> Parser<'a> { /// Parses a Count parameter at the current position. This does not check /// for 'CountIsNextParam' because that is only used in precision, not /// width. - fn count(&mut self) -> Count { + fn count(&mut self, start: usize) -> (Count, Option) { if let Some(i) = self.integer() { - if self.consume('$') { - CountIsParam(i) + if let Some(end) = self.consume_pos('$') { + let span = self.to_span_index(start).to(self.to_span_index(end + 1)); + (CountIsParam(i), Some(span)) } else { - CountIs(i) + (CountIs(i), None) } } else { let tmp = self.cur.clone(); let word = self.word(); if word.is_empty() { self.cur = tmp; - CountImplied + (CountImplied, None) } else if self.consume('$') { - CountIsName(Symbol::intern(word)) + (CountIsName(Symbol::intern(word)), None) } else { self.cur = tmp; - CountImplied + (CountImplied, None) } } } diff --git a/src/libfmt_macros/tests.rs b/src/libfmt_macros/tests.rs index 7282d4a5f248b..e2ddb8810e90a 100644 --- a/src/libfmt_macros/tests.rs +++ b/src/libfmt_macros/tests.rs @@ -12,6 +12,8 @@ fn fmtdflt() -> FormatSpec<'static> { flags: 0, precision: CountImplied, width: CountImplied, + precision_span: None, + width_span: None, ty: "", }; } @@ -79,165 +81,204 @@ fn format_position_nothing_else() { } #[test] fn format_type() { - same("{3:a}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignUnknown, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "a", - }, - })]); + same( + "{3:a}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountImplied, + width: CountImplied, + precision_span: None, + width_span: None, + ty: "a", + }, + })]); } #[test] fn format_align_fill() { - same("{3:>}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: None, - align: AlignRight, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{3:0<}", - &[NextArgument(Argument { - position: ArgumentIs(3), - format: FormatSpec { - fill: Some('0'), - align: AlignLeft, - flags: 0, - precision: CountImplied, - width: CountImplied, - ty: "", - }, - })]); - same("{3:*}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: None, + align: AlignRight, + flags: 0, + precision: CountImplied, + width: CountImplied, + precision_span: None, + width_span: None, + ty: "", + }, + })]); + same( + "{3:0<}", + &[NextArgument(Argument { + position: ArgumentIs(3), + format: FormatSpec { + fill: Some('0'), + align: AlignLeft, + flags: 0, + precision: CountImplied, + width: CountImplied, + precision_span: None, + width_span: None, + ty: "", + }, + })]); + same( + "{3:* LayoutCx<'tcx, TyCtxt<'tcx>> { Ok(variant) }).collect::, _>>()?; + size = size.align_to(align.abi); + let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi.is_uninhabited()) { Abi::Uninhabited diff --git a/src/librustc_target/spec/armv7_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv7_unknown_linux_gnueabi.rs new file mode 100644 index 0000000000000..441cb9bfff3eb --- /dev/null +++ b/src/librustc_target/spec/armv7_unknown_linux_gnueabi.rs @@ -0,0 +1,29 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +// This target is for glibc Linux on ARMv7 without thumb-mode, NEON or +// hardfloat. + +pub fn target() -> TargetResult { + let base = super::linux_base::opts(); + Ok(Target { + llvm_target: "armv7-unknown-linux-gnueabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + features: "+v7,+thumb2,+soft-float,-neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), + abi_blacklist: super::arm_base::abi_blacklist(), + target_mcount: "\u{1}__gnu_mcount_nc".to_string(), + .. base + } + }) +} diff --git a/src/librustc_target/spec/armv7_unknown_linux_musleabi.rs b/src/librustc_target/spec/armv7_unknown_linux_musleabi.rs new file mode 100644 index 0000000000000..c0368e5f0768a --- /dev/null +++ b/src/librustc_target/spec/armv7_unknown_linux_musleabi.rs @@ -0,0 +1,34 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +// This target is for musl Linux on ARMv7 without thumb-mode, NEON or +// hardfloat. + +pub fn target() -> TargetResult { + let base = super::linux_musl_base::opts(); + // Most of these settings are copied from the armv7_unknown_linux_gnueabi + // target. + Ok(Target { + // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it + // to determine the calling convention and float ABI, and it doesn't + // support the "musleabi" value. + llvm_target: "armv7-unknown-linux-gnueabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + features: "+v7,+thumb2,+soft-float,-neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), + abi_blacklist: super::arm_base::abi_blacklist(), + target_mcount: "\u{1}mcount".to_string(), + .. base + } + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 53d66186c368c..b7b6627bbd8ab 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -359,8 +359,10 @@ supported_targets! { ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi), ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi), ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi), + ("armv7-unknown-linux-gnueabi", armv7_unknown_linux_gnueabi), ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf), ("thumbv7neon-unknown-linux-gnueabihf", thumbv7neon_unknown_linux_gnueabihf), + ("armv7-unknown-linux-musleabi", armv7_unknown_linux_musleabi), ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf), ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu), ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl), diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index 9fce5f5811f35..397200c39c2d7 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -403,67 +403,3 @@ impl ExitCode { self.0 as i32 } } - -#[cfg(all(test, not(target_os = "emscripten")))] -mod tests { - use super::*; - - use crate::ffi::OsStr; - use crate::mem; - use crate::ptr; - use crate::sys::cvt; - - macro_rules! t { - ($e:expr) => { - match $e { - Ok(t) => t, - Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), - } - } - } - - extern { - fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int; - fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; - } - - #[test] - fn test_process_mask() { - unsafe { - // Test to make sure that a signal mask does not get inherited. - let mut cmd = Command::new(OsStr::new("cat")); - - let mut set: libc::sigset_t = mem::uninitialized(); - let mut old_set: libc::sigset_t = mem::uninitialized(); - t!(cvt(sigemptyset(&mut set))); - t!(cvt(sigaddset(&mut set, libc::SIGINT))); - t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set))); - - cmd.stdin(Stdio::MakePipe); - cmd.stdout(Stdio::MakePipe); - - let (mut cat, mut pipes) = t!(cmd.spawn(Stdio::Null, true)); - let stdin_write = pipes.stdin.take().unwrap(); - let stdout_read = pipes.stdout.take().unwrap(); - - t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set, - ptr::null_mut()))); - - t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT))); - // We need to wait until SIGINT is definitely delivered. The - // easiest way is to write something to cat, and try to read it - // back: if SIGINT is unmasked, it'll get delivered when cat is - // next scheduled. - let _ = stdin_write.write(b"Hello"); - drop(stdin_write); - - // Either EOF or failure (EPIPE) is okay. - let mut buf = [0; 5]; - if let Ok(ret) = stdout_read.read(&mut buf) { - assert_eq!(ret, 0); - } - - t!(cat.wait()); - } - } -} diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3645ab88d552f..07b1aef337fdc 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2622,27 +2622,23 @@ impl<'a> State<'a> { self.s.word("<"); self.commasep(Inconsistent, &generic_params, |s, param| { + s.print_outer_attributes_inline(¶m.attrs); + match param.kind { ast::GenericParamKind::Lifetime => { - s.print_outer_attributes_inline(¶m.attrs); let lt = ast::Lifetime { id: param.id, ident: param.ident }; s.print_lifetime_bounds(lt, ¶m.bounds) } ast::GenericParamKind::Type { ref default } => { - s.print_outer_attributes_inline(¶m.attrs); s.print_ident(param.ident); s.print_type_bounds(":", ¶m.bounds); - match default { - Some(ref default) => { - s.s.space(); - s.word_space("="); - s.print_type(default) - } - _ => {} + if let Some(ref default) = default { + s.s.space(); + s.word_space("="); + s.print_type(default) } } ast::GenericParamKind::Const { ref ty } => { - s.print_outer_attributes_inline(¶m.attrs); s.word_space("const"); s.print_ident(param.ident); s.s.space(); @@ -2743,6 +2739,9 @@ impl<'a> State<'a> { crate fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) { self.ibox(INDENT_UNIT); + + self.print_outer_attributes_inline(&input.attrs); + match input.ty.node { ast::TyKind::Infer if is_closure => self.print_pat(&input.pat), _ => { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index e53660b656865..fe9cad1e32fca 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -109,6 +109,8 @@ struct Context<'a, 'b> { invalid_refs: Vec<(usize, usize)>, /// Spans of all the formatting arguments, in order. arg_spans: Vec, + /// All the formatting arguments that have formatting flags set, in order for diagnostics. + arg_with_formatting: Vec>, /// Whether this formatting string is a literal or it comes from a macro. is_literal: bool, } @@ -273,31 +275,44 @@ impl<'a, 'b> Context<'a, 'b> { } else { MultiSpan::from_span(self.fmtsp) }; - let refs_len = self.invalid_refs.len(); - let mut refs = self + let refs = self .invalid_refs .iter() .map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos))); - if self.names.is_empty() && !numbered_position_args { + let mut zero_based_note = false; + + let count = self.pieces.len() + self.arg_with_formatting + .iter() + .filter(|fmt| fmt.precision_span.is_some()) + .count(); + if self.names.is_empty() && !numbered_position_args && count != self.args.len() { e = self.ecx.mut_span_err( sp, &format!( "{} positional argument{} in format string, but {}", - self.pieces.len(), - if self.pieces.len() > 1 { "s" } else { "" }, - self.describe_num_args() + count, + if count > 1 { "s" } else { "" }, + self.describe_num_args(), ), ); } else { - let (arg_list, mut sp) = if refs_len == 1 { - let (reg, pos) = refs.next().unwrap(); + let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); + // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)` + // for `println!("{7:7$}", 1);` + refs.sort(); + refs.dedup(); + let (arg_list, mut sp) = if refs.len() == 1 { + let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.map(|sp| *sp)).collect(); ( - format!("argument {}", reg), - MultiSpan::from_span(*pos.unwrap_or(&self.fmtsp)), + format!("argument {}", refs[0]), + if spans.is_empty() { + MultiSpan::from_span(self.fmtsp) + } else { + MultiSpan::from_spans(spans) + }, ) } else { - let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect()); let reg = refs.pop().unwrap(); ( @@ -317,9 +332,70 @@ impl<'a, 'b> Context<'a, 'b> { &format!("invalid reference to positional {} ({})", arg_list, self.describe_num_args())); - e.note("positional arguments are zero-based"); + zero_based_note = true; }; + for fmt in &self.arg_with_formatting { + if let Some(span) = fmt.precision_span { + let span = self.fmtsp.from_inner(span); + match fmt.precision { + parse::CountIsParam(pos) if pos > self.args.len() => { + e.span_label(span, &format!( + "this precision flag expects an `usize` argument at position {}, \ + but {}", + pos, + self.describe_num_args(), + )); + zero_based_note = true; + } + parse::CountIsParam(pos) => { + let count = self.pieces.len() + self.arg_with_formatting + .iter() + .filter(|fmt| fmt.precision_span.is_some()) + .count(); + e.span_label(span, &format!( + "this precision flag adds an extra required argument at position {}, \ + which is why there {} expected", + pos, + if count == 1 { + "is 1 argument".to_string() + } else { + format!("are {} arguments", count) + }, + )); + e.span_label( + self.args[pos].span, + "this parameter corresponds to the precision flag", + ); + zero_based_note = true; + } + _ => {} + } + } + if let Some(span) = fmt.width_span { + let span = self.fmtsp.from_inner(span); + match fmt.width { + parse::CountIsParam(pos) if pos > self.args.len() => { + e.span_label(span, &format!( + "this width flag expects an `usize` argument at position {}, \ + but {}", + pos, + self.describe_num_args(), + )); + zero_based_note = true; + } + _ => {} + } + } + } + if zero_based_note { + e.note("positional arguments are zero-based"); + } + if !self.arg_with_formatting.is_empty() { + e.note("for information about formatting flags, visit \ + https://doc.rust-lang.org/std/fmt/index.html"); + } + e.emit(); } @@ -435,10 +511,11 @@ impl<'a, 'b> Context<'a, 'b> { /// Builds a static `rt::Argument` from a `parse::Piece` or append /// to the `literal` string. - fn build_piece(&mut self, - piece: &parse::Piece<'_>, - arg_index_consumed: &mut Vec) - -> Option> { + fn build_piece( + &mut self, + piece: &parse::Piece<'a>, + arg_index_consumed: &mut Vec, + ) -> Option> { let sp = self.macsp; match *piece { parse::String(s) => { @@ -496,7 +573,9 @@ impl<'a, 'b> Context<'a, 'b> { align: parse::AlignUnknown, flags: 0, precision: parse::CountImplied, + precision_span: None, width: parse::CountImplied, + width_span: None, ty: arg.format.ty, }, }; @@ -506,6 +585,9 @@ impl<'a, 'b> Context<'a, 'b> { let pos_simple = arg.position.index() == simple_arg.position.index(); + if arg.format.precision_span.is_some() || arg.format.width_span.is_some() { + self.arg_with_formatting.push(arg.format); + } if !pos_simple || arg.format != simple_arg.format || fill != ' ' { self.all_pieces_simple = false; } @@ -530,7 +612,7 @@ impl<'a, 'b> Context<'a, 'b> { let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec")); let fmt = self.ecx.expr_struct( sp, - path, + path, vec![ self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill), self.ecx.field_imm(sp, self.ecx.ident_of("align"), align), @@ -657,12 +739,13 @@ impl<'a, 'b> Context<'a, 'b> { self.ecx.expr_call_global(self.macsp, path, fn_args) } - fn format_arg(ecx: &ExtCtxt<'_>, - macsp: Span, - mut sp: Span, - ty: &ArgumentType, - arg: ast::Ident) - -> P { + fn format_arg( + ecx: &ExtCtxt<'_>, + macsp: Span, + mut sp: Span, + ty: &ArgumentType, + arg: ast::Ident, + ) -> P { sp = sp.apply_mark(ecx.current_expansion.id); let arg = ecx.expr_ident(sp, arg); let trait_ = match *ty { @@ -678,7 +761,21 @@ impl<'a, 'b> Context<'a, 'b> { "x" => "LowerHex", "X" => "UpperHex", _ => { - ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname)); + let mut err = ecx.struct_span_err( + sp, + &format!("unknown format trait `{}`", *tyname), + ); + err.note("the only appropriate formatting traits are:\n\ + - ``, which uses the `Display` trait\n\ + - `?`, which uses the `Debug` trait\n\ + - `e`, which uses the `LowerExp` trait\n\ + - `E`, which uses the `UpperExp` trait\n\ + - `o`, which uses the `Octal` trait\n\ + - `p`, which uses the `Pointer` trait\n\ + - `b`, which uses the `Binary` trait\n\ + - `x`, which uses the `LowerHex` trait\n\ + - `X`, which uses the `UpperHex` trait"); + err.emit(); return DummyResult::raw_expr(sp, true); } } @@ -941,6 +1038,7 @@ pub fn expand_preparsed_format_args( fmtsp: fmt.span, invalid_refs: Vec::new(), arg_spans, + arg_with_formatting: Vec::new(), is_literal, }; diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index fa6e3609138e6..02a7433d9469d 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -1402,6 +1402,7 @@ pub struct MalformedSourceMapPositions { pub end_pos: BytePos } +/// Range inside of a `Span` used for diagnostics when we only have access to relative positions. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct InnerSpan { pub start: usize, diff --git a/src/test/ui/async-await/issue-62658.rs b/src/test/ui/async-await/issue-62658.rs new file mode 100644 index 0000000000000..90fbb47bffda8 --- /dev/null +++ b/src/test/ui/async-await/issue-62658.rs @@ -0,0 +1,29 @@ +// This test created a generator whose size was not rounded to a multiple of its +// alignment. This caused an assertion error in codegen. + +// build-pass +// edition:2018 + +#![feature(async_await)] + +async fn noop() {} + +async fn foo() { + // This suspend should be the largest variant. + { + let x = [0u8; 17]; + noop().await; + println!("{:?}", x); + } + + // Add one variant that's aligned to 8 bytes. + { + let x = 0u64; + noop().await; + println!("{:?}", x); + } +} + +fn main() { + let _ = foo(); +} diff --git a/src/test/ui/if/ifmt-bad-arg.rs b/src/test/ui/if/ifmt-bad-arg.rs index 0ebe1fa2dff92..ba897f171af25 100644 --- a/src/test/ui/if/ifmt-bad-arg.rs +++ b/src/test/ui/if/ifmt-bad-arg.rs @@ -75,4 +75,15 @@ ninth number: { tenth number: {}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); //~^^ ERROR: invalid format string + println!("{} {:.*} {}", 1, 3.2, 4); + //~^ ERROR 4 positional arguments in format string, but there are 3 arguments + //~| ERROR mismatched types + println!("{} {:07$.*} {}", 1, 3.2, 4); + //~^ ERROR 4 positional arguments in format string, but there are 3 arguments + //~| ERROR mismatched types + println!("{} {:07$} {}", 1, 3.2, 4); + //~^ ERROR invalid reference to positional argument 7 (there are 3 arguments) + println!("{:foo}", 1); //~ ERROR unknown format trait `foo` + println!("{5} {:4$} {6:7$}", 1); + //~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument) } diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 835b5b6592b78..336ea2254bf5a 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -220,5 +220,87 @@ LL | tenth number: {}", | = note: if you intended to print `{`, you can escape it using `{{` -error: aborting due to 28 previous errors +error: 4 positional arguments in format string, but there are 3 arguments + --> $DIR/ifmt-bad-arg.rs:78:15 + | +LL | println!("{} {:.*} {}", 1, 3.2, 4); + | ^^ ^^--^ ^^ --- this parameter corresponds to the precision flag + | | + | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: 4 positional arguments in format string, but there are 3 arguments + --> $DIR/ifmt-bad-arg.rs:81:15 + | +LL | println!("{} {:07$.*} {}", 1, 3.2, 4); + | ^^ ^^^----^ ^^ --- this parameter corresponds to the precision flag + | | | + | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected + | this width flag expects an `usize` argument at position 7, but there are 3 arguments + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: invalid reference to positional argument 7 (there are 3 arguments) + --> $DIR/ifmt-bad-arg.rs:84:18 + | +LL | println!("{} {:07$} {}", 1, 3.2, 4); + | ^^^--^ + | | + | this width flag expects an `usize` argument at position 7, but there are 3 arguments + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: unknown format trait `foo` + --> $DIR/ifmt-bad-arg.rs:86:24 + | +LL | println!("{:foo}", 1); + | ^ + | + = note: the only appropriate formatting traits are: + - ``, which uses the `Display` trait + - `?`, which uses the `Debug` trait + - `e`, which uses the `LowerExp` trait + - `E`, which uses the `UpperExp` trait + - `o`, which uses the `Octal` trait + - `p`, which uses the `Pointer` trait + - `b`, which uses the `Binary` trait + - `x`, which uses the `LowerHex` trait + - `X`, which uses the `UpperHex` trait + +error: invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument) + --> $DIR/ifmt-bad-arg.rs:87:15 + | +LL | println!("{5} {:4$} {6:7$}", 1); + | ^^^ ^^--^ ^^^--^ + | | | + | | this width flag expects an `usize` argument at position 7, but there is 1 argument + | this width flag expects an `usize` argument at position 4, but there is 1 argument + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error[E0308]: mismatched types + --> $DIR/ifmt-bad-arg.rs:78:32 + | +LL | println!("{} {:.*} {}", 1, 3.2, 4); + | ^^^ expected usize, found floating-point number + | + = note: expected type `&usize` + found type `&{float}` + +error[E0308]: mismatched types + --> $DIR/ifmt-bad-arg.rs:81:35 + | +LL | println!("{} {:07$.*} {}", 1, 3.2, 4); + | ^^^ expected usize, found floating-point number + | + = note: expected type `&usize` + found type `&{float}` + +error: aborting due to 35 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/if/ifmt-unknown-trait.stderr b/src/test/ui/if/ifmt-unknown-trait.stderr index 9ea367c81ec0a..7853b5ca0c9a6 100644 --- a/src/test/ui/if/ifmt-unknown-trait.stderr +++ b/src/test/ui/if/ifmt-unknown-trait.stderr @@ -3,6 +3,17 @@ error: unknown format trait `notimplemented` | LL | format!("{:notimplemented}", "3"); | ^^^ + | + = note: the only appropriate formatting traits are: + - ``, which uses the `Display` trait + - `?`, which uses the `Debug` trait + - `e`, which uses the `LowerExp` trait + - `E`, which uses the `UpperExp` trait + - `o`, which uses the `Octal` trait + - `p`, which uses the `Pointer` trait + - `b`, which uses the `Binary` trait + - `x`, which uses the `LowerHex` trait + - `X`, which uses the `UpperHex` trait error: aborting due to previous error diff --git a/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs new file mode 100644 index 0000000000000..71815e3c08974 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs @@ -0,0 +1,34 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +macro_rules! checker { + ($attr_name:ident, $expected:literal) => { + #[proc_macro_attribute] + pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(input.to_string(), $expected); + TokenStream::new() + } + } +} + +checker!(attr_extern, r#"extern "C" { + fn ffi(#[a1] arg1: i32, #[a2] ...); +}"#); +checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) { }"#); +checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...);"); +checker!(attr_free, "fn free(#[a1] arg1: u8) { let lam = |#[a2] W(x), #[a3] y| (); }"); +checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) { }"); +checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) { }"); +checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) { }"); +checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box, #[a2] arg1: u8) { }"); +checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);"); +checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);"); +checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);"); +checker!(attr_trait_4, "fn trait4<'a>(#[a1] self: Box, #[a2] arg1: u8, #[a3] Vec);"); diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs new file mode 100644 index 0000000000000..1a7e948174506 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs @@ -0,0 +1,56 @@ +// aux-build:param-attrs.rs + +// check-pass + +#![feature(param_attrs)] +#![feature(c_variadic)] + +extern crate param_attrs; + +use param_attrs::*; + +struct W(u8); + +#[attr_extern] +extern "C" { fn ffi(#[a1] arg1: i32, #[a2] ...); } + +#[attr_extern_cvar] +unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) {} + +#[attr_alias] +type Alias = fn(#[a1] u8, #[a2] ...); + +#[attr_free] +fn free(#[a1] arg1: u8) { + let lam = |#[a2] W(x), #[a3] y| (); +} + +impl W { + #[attr_inherent_1] + fn inherent1(#[a1] self, #[a2] arg1: u8) {} + + #[attr_inherent_2] + fn inherent2(#[a1] &self, #[a2] arg1: u8) {} + + #[attr_inherent_3] + fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) {} + + #[attr_inherent_4] + fn inherent4<'a>(#[a1] self: Box, #[a2] arg1: u8) {} +} + +trait A { + #[attr_trait_1] + fn trait1(#[a1] self, #[a2] arg1: u8); + + #[attr_trait_2] + fn trait2(#[a1] &self, #[a2] arg1: u8); + + #[attr_trait_3] + fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8); + + #[attr_trait_4] + fn trait4<'a>(#[a1] self: Box, #[a2] arg1: u8, #[a3] Vec); +} + +fn main() {} diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index a935bc6a4ded9..2d1a52c920bae 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -56,8 +56,10 @@ static TARGETS: &[&str] = &[ "armv7-apple-ios", "armv7-linux-androideabi", "thumbv7neon-linux-androideabi", + "armv7-unknown-linux-gnueabi", "armv7-unknown-linux-gnueabihf", "thumbv7neon-unknown-linux-gnueabihf", + "armv7-unknown-linux-musleabi", "armv7-unknown-linux-musleabihf", "armebv7r-none-eabi", "armebv7r-none-eabihf",