Auto merge of #91692 - matthiaskrgr:rollup-u7dvh0n, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #87599 (Implement concat_bytes!)
 - #89999 (Update std::env::temp_dir to use GetTempPath2 on Windows when available.)
 - #90796 (Remove the reg_thumb register class for asm! on ARM)
 - #91042 (Use Vec extend instead of repeated pushes on several places)
 - #91634 (Do not attempt to suggest help for overly malformed struct/function call)
 - #91685 (Install llvm tools to sysroot when assembling local toolchain)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-12-09 07:08:32 +00:00
commit 600820da45
26 changed files with 542 additions and 98 deletions

View File

@ -0,0 +1,167 @@
use rustc_ast as ast;
use rustc_ast::{ptr::P, tokenstream::TokenStream};
use rustc_data_structures::sync::Lrc;
use rustc_errors::Applicability;
use rustc_expand::base::{self, DummyResult};
/// Emits errors for literal expressions that are invalid inside and outside of an array.
fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P<rustc_ast::Expr>, is_nested: bool) {
let lit = if let ast::ExprKind::Lit(lit) = &expr.kind {
lit
} else {
unreachable!();
};
match lit.kind {
ast::LitKind::Char(_) => {
let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals");
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
err.span_suggestion(
expr.span,
"try using a byte character",
format!("b{}", snippet),
Applicability::MachineApplicable,
)
.emit();
}
}
ast::LitKind::Str(_, _) => {
let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals");
// suggestion would be invalid if we are nested
if !is_nested {
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
err.span_suggestion(
expr.span,
"try using a byte string",
format!("b{}", snippet),
Applicability::MachineApplicable,
);
}
}
err.emit();
}
ast::LitKind::Float(_, _) => {
cx.span_err(expr.span, "cannot concatenate float literals");
}
ast::LitKind::Bool(_) => {
cx.span_err(expr.span, "cannot concatenate boolean literals");
}
ast::LitKind::Err(_) => {}
ast::LitKind::Int(_, _) if !is_nested => {
let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals");
if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) {
err.span_suggestion(
expr.span,
"try wrapping the number in an array",
format!("[{}]", snippet),
Applicability::MachineApplicable,
);
}
err.emit();
}
ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
) => {
assert!(val > u8::MAX.into()); // must be an error
cx.span_err(expr.span, "numeric literal is out of bounds");
}
ast::LitKind::Int(_, _) => {
cx.span_err(expr.span, "numeric literal is not a `u8`");
}
_ => unreachable!(),
}
}
pub fn expand_concat_bytes(
cx: &mut base::ExtCtxt<'_>,
sp: rustc_span::Span,
tts: TokenStream,
) -> Box<dyn base::MacResult + 'static> {
let es = match base::get_exprs_from_tts(cx, sp, tts) {
Some(e) => e,
None => return DummyResult::any(sp),
};
let mut accumulator = Vec::new();
let mut missing_literals = vec![];
let mut has_errors = false;
for e in es {
match e.kind {
ast::ExprKind::Array(ref exprs) => {
for expr in exprs {
match expr.kind {
ast::ExprKind::Array(_) => {
if !has_errors {
cx.span_err(expr.span, "cannot concatenate doubly nested array");
}
has_errors = true;
}
ast::ExprKind::Lit(ref lit) => match lit.kind {
ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed
| ast::LitIntType::Unsigned(ast::UintTy::U8),
) if val <= u8::MAX.into() => {
accumulator.push(val as u8);
}
ast::LitKind::Byte(val) => {
accumulator.push(val);
}
ast::LitKind::ByteStr(_) => {
if !has_errors {
cx.struct_span_err(
expr.span,
"cannot concatenate doubly nested array",
)
.note("byte strings are treated as arrays of bytes")
.help("try flattening the array")
.emit();
}
has_errors = true;
}
_ => {
if !has_errors {
invalid_type_err(cx, expr, true);
}
has_errors = true;
}
},
_ => {
missing_literals.push(expr.span);
}
}
}
}
ast::ExprKind::Lit(ref lit) => match lit.kind {
ast::LitKind::Byte(val) => {
accumulator.push(val);
}
ast::LitKind::ByteStr(ref bytes) => {
accumulator.extend_from_slice(&bytes);
}
_ => {
if !has_errors {
invalid_type_err(cx, &e, false);
}
has_errors = true;
}
},
ast::ExprKind::Err => {
has_errors = true;
}
_ => {
missing_literals.push(e.span);
}
}
}
if !missing_literals.is_empty() {
let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal");
err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
err.emit();
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
} else if has_errors {
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
}
let sp = cx.with_def_site_ctxt(sp);
base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(accumulator))))
}

View File

@ -27,6 +27,7 @@ mod cfg_accessible;
mod cfg_eval;
mod compile_error;
mod concat;
mod concat_bytes;
mod concat_idents;
mod derive;
mod deriving;
@ -65,6 +66,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
cfg: cfg::expand_cfg,
column: source_util::expand_column,
compile_error: compile_error::expand_compile_error,
concat_bytes: concat_bytes::expand_concat_bytes,
concat_idents: concat_idents::expand_concat_idents,
concat: concat::expand_concat,
env: env::expand_env,

View File

@ -568,7 +568,6 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(),
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(),
@ -628,8 +627,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
unimplemented!()
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)=> cx.type_i32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
@ -737,8 +735,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
unimplemented!()
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)

View File

@ -632,7 +632,6 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
unreachable!("clobber-only")
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => "t",
@ -703,8 +702,7 @@ fn modifier_to_llvm(
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None,
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None,
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None,
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
@ -785,8 +783,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)

View File

@ -35,6 +35,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
// since it should be enabled per-function using #[instruction_set], not
// #[target_feature].
("thumb-mode", Some(sym::arm_target_feature)),
("thumb2", Some(sym::arm_target_feature)),
];
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[

View File

@ -1100,30 +1100,37 @@ impl<'a> Parser<'a> {
snapshot.bump(); // `(`
match snapshot.parse_struct_fields(path, false, token::Paren) {
Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
// We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
// We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
// `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
*self = snapshot;
let close_paren = self.prev_token.span;
let span = lo.to(self.prev_token.span);
if !fields.is_empty() {
err.cancel();
self.struct_span_err(
let mut err = self.struct_span_err(
span,
"invalid `struct` delimiters or `fn` call arguments",
)
.multipart_suggestion(
);
err.multipart_suggestion(
&format!("if `{}` is a struct, use braces as delimiters", name),
vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())],
vec![
(open_paren, " { ".to_string()),
(close_paren, " }".to_string()),
],
Applicability::MaybeIncorrect,
)
.multipart_suggestion(
);
err.multipart_suggestion(
&format!("if `{}` is a function, use the arguments directly", name),
fields
.into_iter()
.map(|field| (field.span.until(field.expr.span), String::new()))
.collect(),
Applicability::MaybeIncorrect,
)
.emit();
);
err.emit();
} else {
err.emit();
}
return Some(self.mk_expr_err(span));
}
Ok(_) => {}

View File

@ -439,6 +439,7 @@ symbols! {
compiler_builtins,
compiler_fence,
concat,
concat_bytes,
concat_idents,
conservative_impl_trait,
console,
@ -1058,7 +1059,6 @@ symbols! {
reg_nonzero,
reg_pair,
reg_ptr,
reg_thumb,
reg_upper,
register_attr,
register_tool,

View File

@ -6,7 +6,6 @@ use std::fmt;
def_reg_class! {
Arm ArmInlineAsmRegClass {
reg,
reg_thumb,
sreg,
sreg_low16,
dreg,
@ -47,7 +46,7 @@ impl ArmInlineAsmRegClass {
_arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
match self {
Self::reg | Self::reg_thumb => types! { _: I8, I16, I32, F32; },
Self::reg => types! { _: I8, I16, I32, F32; },
Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; },
Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! {
"vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
@ -88,20 +87,32 @@ fn frame_pointer_r7(
}
}
fn not_thumb1(
_arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool,
_target: &Target,
) -> Result<(), &'static str> {
if has_feature("thumb-mode") && !has_feature("thumb2") {
Err("high registers (r8+) cannot be used in Thumb-1 code")
} else {
Ok(())
}
}
def_regs! {
Arm ArmInlineAsmReg ArmInlineAsmRegClass {
r0: reg, reg_thumb = ["r0", "a1"],
r1: reg, reg_thumb = ["r1", "a2"],
r2: reg, reg_thumb = ["r2", "a3"],
r3: reg, reg_thumb = ["r3", "a4"],
r4: reg, reg_thumb = ["r4", "v1"],
r5: reg, reg_thumb = ["r5", "v2"],
r7: reg, reg_thumb = ["r7", "v4"] % frame_pointer_r7,
r8: reg = ["r8", "v5"],
r10: reg = ["r10", "sl"],
r0: reg = ["r0", "a1"],
r1: reg = ["r1", "a2"],
r2: reg = ["r2", "a3"],
r3: reg = ["r3", "a4"],
r4: reg = ["r4", "v1"],
r5: reg = ["r5", "v2"],
r7: reg = ["r7", "v4"] % frame_pointer_r7,
r8: reg = ["r8", "v5"] % not_thumb1,
r10: reg = ["r10", "sl"] % not_thumb1,
r11: reg = ["r11", "fp"] % frame_pointer_r11,
r12: reg = ["r12", "ip"],
r14: reg = ["r14", "lr"],
r12: reg = ["r12", "ip"] % not_thumb1,
r14: reg = ["r14", "lr"] % not_thumb1,
s0: sreg, sreg_low16 = ["s0"],
s1: sreg, sreg_low16 = ["s1"],
s2: sreg, sreg_low16 = ["s2"],

View File

@ -967,6 +967,34 @@ pub(crate) mod builtin {
($($e:ident),+ $(,)?) => {{ /* compiler built-in */ }};
}
/// Concatenates literals into a byte slice.
///
/// This macro takes any number of comma-separated literals, and concatenates them all into
/// one, yielding an expression of type `&[u8, _]`, which represents all of the literals
/// concatenated left-to-right. The literals passed can be any combination of:
///
/// - byte literals (`b'r'`)
/// - byte strings (`b"Rust"`)
/// - arrays of bytes/numbers (`[b'A', 66, b'C']`)
///
/// # Examples
///
/// ```
/// #![feature(concat_bytes)]
///
/// # fn main() {
/// let s: &[u8; 6] = concat_bytes!(b'A', b"BC", [68, b'E', 70]);
/// assert_eq!(s, b"ABCDEF");
/// # }
/// ```
#[cfg(not(bootstrap))]
#[unstable(feature = "concat_bytes", issue = "87555")]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! concat_bytes {
($($e:literal),+ $(,)?) => {{ /* compiler built-in */ }};
}
/// Concatenates literals into a static string slice.
///
/// This macro takes any number of comma-separated literals, yielding an

View File

@ -60,6 +60,15 @@ pub use crate::{
option_env, stringify, trace_macros,
};
#[unstable(
feature = "concat_bytes",
issue = "87555",
reason = "`concat_bytes` is not stable enough for use and is subject to change"
)]
#[cfg(not(bootstrap))]
#[doc(no_inline)]
pub use crate::concat_bytes;
#[unstable(
feature = "asm",
issue = "72016",

View File

@ -583,28 +583,25 @@ pub fn home_dir() -> Option<PathBuf> {
/// may result in "insecure temporary file" security vulnerabilities. Consider
/// using a crate that securely creates temporary files or directories.
///
/// # Unix
/// # Platform-specific behavior
///
/// Returns the value of the `TMPDIR` environment variable if it is
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
/// [`GetTempPath`][GetTempPath], which this function uses internally.
/// Note that, this [may change in the future][changes].
///
/// # Windows
///
/// Returns the value of, in order, the `TMP`, `TEMP`,
/// `USERPROFILE` environment variable if any are set and not the empty
/// string. Otherwise, `temp_dir` returns the path of the Windows directory.
/// This behavior is identical to that of [`GetTempPath`][msdn], which this
/// function uses internally.
///
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
/// [changes]: io#platform-specific-behavior
/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
///
/// ```no_run
/// use std::env;
///
/// fn main() {
/// let mut dir = env::temp_dir();
/// let dir = env::temp_dir();
/// println!("Temporary directory: {}", dir.display());
/// }
/// ```

View File

@ -250,6 +250,7 @@
#![feature(cfg_target_thread_local)]
#![feature(char_error_internals)]
#![feature(char_internals)]
#![cfg_attr(not(bootstrap), feature(concat_bytes))]
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![feature(const_fn_floating_point_arithmetic)]
@ -576,6 +577,14 @@ pub use core::{
log_syntax, module_path, option_env, stringify, trace_macros,
};
#[unstable(
feature = "concat_bytes",
issue = "87555",
reason = "`concat_bytes` is not stable enough for use and is subject to change"
)]
#[cfg(not(bootstrap))]
pub use core::concat_bytes;
#[stable(feature = "core_primitive", since = "1.43.0")]
pub use core::primitive;

View File

@ -45,6 +45,15 @@ pub use core::prelude::v1::{
PartialOrd,
};
#[unstable(
feature = "concat_bytes",
issue = "87555",
reason = "`concat_bytes` is not stable enough for use and is subject to change"
)]
#[cfg(not(bootstrap))]
#[doc(no_inline)]
pub use core::prelude::v1::concat_bytes;
#[unstable(
feature = "asm",
issue = "72016",

View File

@ -1110,6 +1110,12 @@ compat_fn! {
-> () {
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
}
// >= Win11 / Server 2022
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD {
GetTempPathW(nBufferLength, lpBuffer)
}
}
compat_fn! {

View File

@ -275,7 +275,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
}
pub fn temp_dir() -> PathBuf {
super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap()
super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap()
}
#[cfg(not(target_vendor = "uwp"))]

View File

@ -28,6 +28,7 @@ use crate::dist;
use crate::native;
use crate::tool::SourceType;
use crate::util::{exe, is_debug_info, is_dylib, symlink_dir};
use crate::LLVM_TOOLS;
use crate::{Compiler, DependencyType, GitRepo, Mode};
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
@ -1164,6 +1165,16 @@ impl Step for Assemble {
let llvm_bin_dir = output(Command::new(llvm_config_bin).arg("--bindir"));
let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
builder.copy(&llvm_bin_dir.join(&src_exe), &libdir_bin.join(&dst_exe));
// Since we've already built the LLVM tools, install them to the sysroot.
// This is the equivalent of installing the `llvm-tools-preview` component via
// rustup, and lets developers use a locally built toolchain to
// build projects that expect llvm tools to be present in the sysroot
// (e.g. the `bootimage` crate).
for tool in LLVM_TOOLS {
let tool_exe = exe(tool, target_compiler.host);
builder.copy(&llvm_bin_dir.join(&tool_exe), &libdir_bin.join(&tool_exe));
}
}
}

View File

@ -564,12 +564,8 @@ Here is the list of currently supported register classes:
| AArch64 | `vreg` | `v[0-31]` | `w` |
| AArch64 | `vreg_low16` | `v[0-15]` | `x` |
| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers |
| ARM (ARM) | `reg` | `r[0-12]`, `r14` | `r` |
| ARM (Thumb2) | `reg` | `r[0-12]`, `r14` | `r` |
| ARM (ARM/Thumb2) | `reg` | `r[0-12]`, `r14` | `r` |
| ARM (Thumb1) | `reg` | `r[0-7]` | `r` |
| ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` |
| ARM (Thumb2) | `reg_thumb` | `r[0-7]` | `l` |
| ARM (Thumb1) | `reg_thumb` | `r[0-7]` | `l` |
| ARM | `sreg` | `s[0-31]` | `t` |
| ARM | `sreg_low16` | `s[0-15]` | `x` |
| ARM | `dreg` | `d[0-31]` | `w` |

View File

@ -59,12 +59,6 @@ macro_rules! check {
// CHECK: @NO_APP
check!(reg "" reg i32 "mov");
// CHECK-LABEL: reg_thumb:
// CHECK: @APP
// CHECK: mov r0, r0
// CHECK: @NO_APP
check!(reg_thumb "" reg_thumb i32 "mov");
// CHECK-LABEL: sreg:
// CHECK: @APP
// CHECK: vmov.f32 s0, s0

View File

@ -163,36 +163,6 @@ check!(reg_f32 f32 reg "mov");
// CHECK: @NO_APP
check!(reg_ptr ptr reg "mov");
// CHECK-LABEL: reg_thumb_i8:
// CHECK: @APP
// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
// CHECK: @NO_APP
check!(reg_thumb_i8 i8 reg_thumb "mov");
// CHECK-LABEL: reg_thumb_i16:
// CHECK: @APP
// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
// CHECK: @NO_APP
check!(reg_thumb_i16 i16 reg_thumb "mov");
// CHECK-LABEL: reg_thumb_i32:
// CHECK: @APP
// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
// CHECK: @NO_APP
check!(reg_thumb_i32 i32 reg_thumb "mov");
// CHECK-LABEL: reg_thumb_f32:
// CHECK: @APP
// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
// CHECK: @NO_APP
check!(reg_thumb_f32 f32 reg_thumb "mov");
// CHECK-LABEL: reg_thumb_ptr:
// CHECK: @APP
// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
// CHECK: @NO_APP
check!(reg_thumb_ptr ptr reg_thumb "mov");
// CHECK-LABEL: sreg_i32:
// CHECK: @APP
// CHECK: vmov.f32 s{{[0-9]+}}, s{{[0-9]+}}

View File

@ -0,0 +1,4 @@
fn main() {
let a = concat_bytes!(b'A', b"BC"); //~ ERROR use of unstable library feature 'concat_bytes'
assert_eq!(a, &[65, 66, 67]);
}

View File

@ -0,0 +1,12 @@
error[E0658]: use of unstable library feature 'concat_bytes'
--> $DIR/feature-gate-concat_bytes.rs:2:13
|
LL | let a = concat_bytes!(b'A', b"BC");
| ^^^^^^^^^^^^
|
= note: see issue #87555 <https://github.com/rust-lang/rust/issues/87555> for more information
= help: add `#![feature(concat_bytes)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,42 @@
#![feature(concat_bytes)]
fn main() {
concat_bytes!(pie); //~ ERROR expected a byte literal
concat_bytes!(pie, pie); //~ ERROR expected a byte literal
concat_bytes!("tnrsi", "tnri"); //~ ERROR cannot concatenate string literals
concat_bytes!(2.8); //~ ERROR cannot concatenate float literals
concat_bytes!(300); //~ ERROR cannot concatenate numeric literals
concat_bytes!('a'); //~ ERROR cannot concatenate character literals
concat_bytes!(true, false); //~ ERROR cannot concatenate boolean literals
concat_bytes!(42, b"va", b'l'); //~ ERROR cannot concatenate numeric literals
concat_bytes!(42, b"va", b'l', [1, 2]); //~ ERROR cannot concatenate numeric literals
concat_bytes!([
"hi", //~ ERROR cannot concatenate string literals
]);
concat_bytes!([
'a', //~ ERROR cannot concatenate character literals
]);
concat_bytes!([
true, //~ ERROR cannot concatenate boolean literals
]);
concat_bytes!([
false, //~ ERROR cannot concatenate boolean literals
]);
concat_bytes!([
2.6, //~ ERROR cannot concatenate float literals
]);
concat_bytes!([
265, //~ ERROR numeric literal is out of bounds
]);
concat_bytes!([
-33, //~ ERROR expected a byte literal
]);
concat_bytes!([
b"hi!", //~ ERROR cannot concatenate doubly nested array
]);
concat_bytes!([
[5, 6, 7], //~ ERROR cannot concatenate doubly nested array
]);
concat_bytes!(5u16); //~ ERROR cannot concatenate numeric literals
concat_bytes!([5u16]); //~ ERROR numeric literal is not a `u8`
}

View File

@ -0,0 +1,131 @@
error: expected a byte literal
--> $DIR/concat-bytes-error.rs:4:19
|
LL | concat_bytes!(pie);
| ^^^
|
= note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
error: expected a byte literal
--> $DIR/concat-bytes-error.rs:5:19
|
LL | concat_bytes!(pie, pie);
| ^^^ ^^^
|
= note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
error: cannot concatenate string literals
--> $DIR/concat-bytes-error.rs:6:19
|
LL | concat_bytes!("tnrsi", "tnri");
| ^^^^^^^ help: try using a byte string: `b"tnrsi"`
error: cannot concatenate float literals
--> $DIR/concat-bytes-error.rs:7:19
|
LL | concat_bytes!(2.8);
| ^^^
error: cannot concatenate numeric literals
--> $DIR/concat-bytes-error.rs:8:19
|
LL | concat_bytes!(300);
| ^^^ help: try wrapping the number in an array: `[300]`
error: cannot concatenate character literals
--> $DIR/concat-bytes-error.rs:9:19
|
LL | concat_bytes!('a');
| ^^^ help: try using a byte character: `b'a'`
error: cannot concatenate boolean literals
--> $DIR/concat-bytes-error.rs:10:19
|
LL | concat_bytes!(true, false);
| ^^^^
error: cannot concatenate numeric literals
--> $DIR/concat-bytes-error.rs:11:19
|
LL | concat_bytes!(42, b"va", b'l');
| ^^ help: try wrapping the number in an array: `[42]`
error: cannot concatenate numeric literals
--> $DIR/concat-bytes-error.rs:12:19
|
LL | concat_bytes!(42, b"va", b'l', [1, 2]);
| ^^ help: try wrapping the number in an array: `[42]`
error: cannot concatenate string literals
--> $DIR/concat-bytes-error.rs:14:9
|
LL | "hi",
| ^^^^
error: cannot concatenate character literals
--> $DIR/concat-bytes-error.rs:17:9
|
LL | 'a',
| ^^^ help: try using a byte character: `b'a'`
error: cannot concatenate boolean literals
--> $DIR/concat-bytes-error.rs:20:9
|
LL | true,
| ^^^^
error: cannot concatenate boolean literals
--> $DIR/concat-bytes-error.rs:23:9
|
LL | false,
| ^^^^^
error: cannot concatenate float literals
--> $DIR/concat-bytes-error.rs:26:9
|
LL | 2.6,
| ^^^
error: numeric literal is out of bounds
--> $DIR/concat-bytes-error.rs:29:9
|
LL | 265,
| ^^^
error: expected a byte literal
--> $DIR/concat-bytes-error.rs:32:9
|
LL | -33,
| ^^^
|
= note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
error: cannot concatenate doubly nested array
--> $DIR/concat-bytes-error.rs:35:9
|
LL | b"hi!",
| ^^^^^^
|
= note: byte strings are treated as arrays of bytes
= help: try flattening the array
error: cannot concatenate doubly nested array
--> $DIR/concat-bytes-error.rs:38:9
|
LL | [5, 6, 7],
| ^^^^^^^^^
error: cannot concatenate numeric literals
--> $DIR/concat-bytes-error.rs:40:19
|
LL | concat_bytes!(5u16);
| ^^^^ help: try wrapping the number in an array: `[5u16]`
error: numeric literal is not a `u8`
--> $DIR/concat-bytes-error.rs:41:20
|
LL | concat_bytes!([5u16]);
| ^^^^
error: aborting due to 20 previous errors

View File

@ -0,0 +1,7 @@
// run-pass
#![feature(concat_bytes)]
fn main() {
assert_eq!(concat_bytes!(), &[]);
assert_eq!(concat_bytes!(b'A', b"BC", [68, b'E', 70]), b"ABCDEF");
}

View File

@ -0,0 +1,6 @@
fn main() {
a(_:b:,)
//~^ ERROR: expected identifier, found reserved identifier `_`
//~| ERROR: expected type, found `,`
//~| ERROR: expected type, found `,`
}

View File

@ -0,0 +1,31 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-91461.rs:2:7
|
LL | a(_:b:,)
| ^ expected identifier, found reserved identifier
error: expected type, found `,`
--> $DIR/issue-91461.rs:2:11
|
LL | a(_:b:,)
| - -^ expected type
| | |
| | tried to parse a type due to this type ascription
| while parsing this struct
|
= note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
= note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
error: expected type, found `,`
--> $DIR/issue-91461.rs:2:11
|
LL | a(_:b:,)
| -^ expected type
| |
| tried to parse a type due to this type ascription
|
= note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
= note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
error: aborting due to 3 previous errors