mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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:
commit
600820da45
167
compiler/rustc_builtin_macros/src/concat_bytes.rs
Normal file
167
compiler/rustc_builtin_macros/src/concat_bytes.rs
Normal 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))))
|
||||
}
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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>)] = &[
|
||||
|
@ -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);
|
||||
err.cancel();
|
||||
self.struct_span_err(
|
||||
span,
|
||||
"invalid `struct` delimiters or `fn` call arguments",
|
||||
)
|
||||
.multipart_suggestion(
|
||||
&format!("if `{}` is a struct, use braces as delimiters", name),
|
||||
vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.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();
|
||||
if !fields.is_empty() {
|
||||
err.cancel();
|
||||
let mut err = self.struct_span_err(
|
||||
span,
|
||||
"invalid `struct` delimiters or `fn` call arguments",
|
||||
);
|
||||
err.multipart_suggestion(
|
||||
&format!("if `{}` is a struct, use braces as delimiters", name),
|
||||
vec![
|
||||
(open_paren, " { ".to_string()),
|
||||
(close_paren, " }".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
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,
|
||||
);
|
||||
err.emit();
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
return Some(self.mk_expr_err(span));
|
||||
}
|
||||
Ok(_) => {}
|
||||
|
@ -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,
|
||||
|
@ -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"],
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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());
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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! {
|
||||
|
@ -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"))]
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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` |
|
||||
|
@ -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
|
||||
|
@ -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]+}}
|
||||
|
4
src/test/ui/feature-gates/feature-gate-concat_bytes.rs
Normal file
4
src/test/ui/feature-gates/feature-gate-concat_bytes.rs
Normal 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]);
|
||||
}
|
12
src/test/ui/feature-gates/feature-gate-concat_bytes.stderr
Normal file
12
src/test/ui/feature-gates/feature-gate-concat_bytes.stderr
Normal 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`.
|
42
src/test/ui/macros/concat-bytes-error.rs
Normal file
42
src/test/ui/macros/concat-bytes-error.rs
Normal 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`
|
||||
}
|
131
src/test/ui/macros/concat-bytes-error.stderr
Normal file
131
src/test/ui/macros/concat-bytes-error.stderr
Normal 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
|
||||
|
7
src/test/ui/macros/concat-bytes.rs
Normal file
7
src/test/ui/macros/concat-bytes.rs
Normal 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");
|
||||
}
|
6
src/test/ui/parser/issues/issue-91461.rs
Normal file
6
src/test/ui/parser/issues/issue-91461.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
a(_:b:,)
|
||||
//~^ ERROR: expected identifier, found reserved identifier `_`
|
||||
//~| ERROR: expected type, found `,`
|
||||
//~| ERROR: expected type, found `,`
|
||||
}
|
31
src/test/ui/parser/issues/issue-91461.stderr
Normal file
31
src/test/ui/parser/issues/issue-91461.stderr
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user