diff --git a/Cargo.lock b/Cargo.lock index 7e798d6d26144..03663700e0033 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3282,6 +3282,7 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", + "rustc_attr_data_structures", "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", @@ -3316,6 +3317,7 @@ dependencies = [ "rustc_parse", "rustc_session", "rustc_span", + "rustc_target", "thin-vec", ] @@ -4116,6 +4118,7 @@ dependencies = [ "rustc_apfloat", "rustc_arena", "rustc_ast", + "rustc_attr_data_structures", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -5796,9 +5799,9 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter-provider" -version = "31.0.0" +version = "34.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fabda09a0d89ffd1615b297b4a5d4b4d99df9598aeb24685837e63019e927b" +checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae" [[package]] name = "wasm-bindgen" @@ -5860,9 +5863,9 @@ dependencies = [ [[package]] name = "wasm-component-ld" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60a07a994a3538b57d8c5f8caba19f4793fb4c7156276e5e90e90acbb829e20" +checksum = "b015ec93764aa5517bc8b839efa9941b90be8ce680b1134f8224644ba1e48e3f" dependencies = [ "anyhow", "clap", @@ -5870,7 +5873,7 @@ dependencies = [ "libc", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.229.0", + "wasmparser 0.234.0", "wat", "windows-sys 0.59.0", "winsplit", @@ -5897,12 +5900,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ba1d491ecacb085a2552025c10a675a6fddcbd03b1fc9b36c536010ce265d2" +checksum = "170a0157eef517a179f2d20ed7c68df9c3f7f6c1c047782d488bf5a464174684" dependencies = [ "leb128fmt", - "wasmparser 0.229.0", + "wasmparser 0.234.0", ] [[package]] @@ -5917,14 +5920,14 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78fdb7d29a79191ab363dc90c1ddd3a1e880ffd5348d92d48482393a9e6c5f4d" +checksum = "a42fe3f5cbfb56fc65311ef827930d06189160038e81db62188f66b4bf468e3a" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.229.0", - "wasmparser 0.229.0", + "wasm-encoder 0.234.0", + "wasmparser 0.234.0", ] [[package]] @@ -5939,9 +5942,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3b1f053f5d41aa55640a1fa9b6d1b8a9e4418d118ce308d20e24ff3575a8c" +checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5" dependencies = [ "bitflags", "hashbrown", @@ -5950,15 +5953,6 @@ dependencies = [ "serde", ] -[[package]] -name = "wasmparser" -version = "0.234.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5" -dependencies = [ - "bitflags", -] - [[package]] name = "wasmparser" version = "0.235.0" @@ -6411,9 +6405,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f550067740e223bfe6c4878998e81cdbe2529dd9a793dc49248dd6613394e8b" +checksum = "5a8888169acf4c6c4db535beb405b570eedac13215d6821ca9bd03190f7f8b8c" dependencies = [ "anyhow", "bitflags", @@ -6422,17 +6416,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.229.0", + "wasm-encoder 0.234.0", "wasm-metadata", - "wasmparser 0.229.0", + "wasmparser 0.234.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.229.0" +version = "0.234.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459c6ba62bf511d6b5f2a845a2a736822e38059c1cfa0b644b467bbbfae4efa6" +checksum = "465492df47d8dcc015a3b7f241aed8ea03688fee7c5e04162285c5b1a3539c8b" dependencies = [ "anyhow", "id-arena", @@ -6443,7 +6437,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.229.0", + "wasmparser 0.234.0", ] [[package]] diff --git a/compiler/rustc_abi/src/canon_abi.rs b/compiler/rustc_abi/src/canon_abi.rs index 7c020be676172..13f9a04b286f0 100644 --- a/compiler/rustc_abi/src/canon_abi.rs +++ b/compiler/rustc_abi/src/canon_abi.rs @@ -63,8 +63,8 @@ impl fmt::Display for CanonAbi { CanonAbi::Custom => ExternAbi::Custom, CanonAbi::Arm(arm_call) => match arm_call { ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false }, - ArmCall::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall, - ArmCall::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry, + ArmCall::CCmseNonSecureCall => ExternAbi::CmseNonSecureCall, + ArmCall::CCmseNonSecureEntry => ExternAbi::CmseNonSecureEntry, }, CanonAbi::GpuKernel => ExternAbi::GpuKernel, CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 7457ae1f03344..0dfe6ebe69d7f 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -55,9 +55,9 @@ pub enum ExternAbi { unwind: bool, }, /// extremely constrained barely-C ABI for TrustZone - CCmseNonSecureCall, + CmseNonSecureCall, /// extremely constrained barely-C ABI for TrustZone - CCmseNonSecureEntry, + CmseNonSecureEntry, /* gpu */ /// An entry-point function called by the GPU's host @@ -136,8 +136,6 @@ macro_rules! abi_impls { abi_impls! { ExternAbi = { C { unwind: false } =><= "C", - CCmseNonSecureCall =><= "C-cmse-nonsecure-call", - CCmseNonSecureEntry =><= "C-cmse-nonsecure-entry", C { unwind: true } =><= "C-unwind", Rust =><= "Rust", Aapcs { unwind: false } =><= "aapcs", @@ -146,6 +144,8 @@ abi_impls! { AvrNonBlockingInterrupt =><= "avr-non-blocking-interrupt", Cdecl { unwind: false } =><= "cdecl", Cdecl { unwind: true } =><= "cdecl-unwind", + CmseNonSecureCall =><= "cmse-nonsecure-call", + CmseNonSecureEntry =><= "cmse-nonsecure-entry", Custom =><= "custom", EfiApi =><= "efiapi", Fastcall { unwind: false } =><= "fastcall", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 11afd359e5ad3..ab8dac1602666 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -904,6 +904,10 @@ pub enum BorrowKind { /// The resulting type is either `*const T` or `*mut T` /// where `T = typeof($expr)`. Raw, + /// A pinned borrow, `&pin const $expr` or `&pin mut $expr`. + /// The resulting type is either `Pin<&'a T>` or `Pin<&'a mut T>` + /// where `T = typeof($expr)` and `'a` is some lifetime. + Pin, } #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6ac258155fe94..dc571f5c3671a 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -11,6 +11,7 @@ doctest = false rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f297bf9f4cfed..c2140514e3117 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::HirId; @@ -831,7 +832,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) { if self.tcx.features().async_fn_track_caller() && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id) - && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)) + && find_attr!(*attrs, AttributeKind::TrackCaller(_)) { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index b8fa2dd3dd626..9743d1e815e7e 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -124,12 +124,12 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { feature: sym::abi_riscv_interrupt, explain: GateReason::Experimental, }), - ExternAbi::CCmseNonSecureCall => Err(UnstableAbi { + ExternAbi::CmseNonSecureCall => Err(UnstableAbi { abi, - feature: sym::abi_c_cmse_nonsecure_call, + feature: sym::abi_cmse_nonsecure_call, explain: GateReason::Experimental, }), - ExternAbi::CCmseNonSecureEntry => Err(UnstableAbi { + ExternAbi::CmseNonSecureEntry => Err(UnstableAbi { abi, feature: sym::cmse_nonsecure_entry, explain: GateReason::Experimental, diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index c738cb2aa2fd4..1940628b44a53 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -18,5 +18,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 9a267501230fe..6eddce7b590ac 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -1,20 +1,25 @@ -ast_passes_abi_custom_coroutine = - functions with the `"custom"` ABI cannot be `{$coroutine_kind_str}` +ast_passes_abi_cannot_be_coroutine = + functions with the {$abi} ABI cannot be `{$coroutine_kind_str}` .suggestion = remove the `{$coroutine_kind_str}` keyword from this definiton -ast_passes_abi_custom_invalid_signature = - invalid signature for `extern "custom"` function - .note = functions with the `"custom"` ABI cannot have any parameters or return type - .suggestion = remove the parameters and return type - ast_passes_abi_custom_safe_foreign_function = - foreign functions with the `"custom"` ABI cannot be safe + foreign functions with the "custom" ABI cannot be safe .suggestion = remove the `safe` keyword from this definition ast_passes_abi_custom_safe_function = - functions with the `"custom"` ABI must be unsafe + functions with the "custom" ABI must be unsafe .suggestion = add the `unsafe` keyword to this definition +ast_passes_abi_must_not_have_parameters_or_return_type= + invalid signature for `extern {$abi}` function + .note = functions with the {$abi} ABI cannot have any parameters or return type + .suggestion = remove the parameters and return type + +ast_passes_abi_must_not_have_return_type= + invalid signature for `extern {$abi}` function + .note = functions with the "custom" ABI cannot have a return type + .help = remove the return type + ast_passes_assoc_const_without_body = associated constant in `impl` without body .suggestion = provide a definition for the constant diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b69a91e2f5f86..da24825120376 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -21,7 +21,7 @@ use std::ops::{Deref, DerefMut}; use std::str::FromStr; use itertools::{Either, Itertools}; -use rustc_abi::ExternAbi; +use rustc_abi::{CanonAbi, ExternAbi, InterruptKind}; use rustc_ast::ptr::P; use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list}; use rustc_ast::*; @@ -37,6 +37,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_span::{Ident, Span, kw, sym}; +use rustc_target::spec::{AbiMap, AbiMapping}; use thin_vec::thin_vec; use crate::errors::{self, TildeConstReason}; @@ -365,31 +366,77 @@ impl<'a> AstValidator<'a> { } } - /// An `extern "custom"` function must be unsafe, and must not have any parameters or return - /// type. - fn check_custom_abi(&self, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) { + /// Check that the signature of this function does not violate the constraints of its ABI. + fn check_extern_fn_signature(&self, abi: ExternAbi, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) { + match AbiMap::from_target(&self.sess.target).canonize_abi(abi, false) { + AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => { + match canon_abi { + CanonAbi::C + | CanonAbi::Rust + | CanonAbi::RustCold + | CanonAbi::Arm(_) + | CanonAbi::GpuKernel + | CanonAbi::X86(_) => { /* nothing to check */ } + + CanonAbi::Custom => { + // An `extern "custom"` function must be unsafe. + self.reject_safe_fn(abi, ctxt, sig); + + // An `extern "custom"` function cannot be `async` and/or `gen`. + self.reject_coroutine(abi, sig); + + // An `extern "custom"` function must have type `fn()`. + self.reject_params_or_return(abi, ident, sig); + } + + CanonAbi::Interrupt(interrupt_kind) => { + // An interrupt handler cannot be `async` and/or `gen`. + self.reject_coroutine(abi, sig); + + if let InterruptKind::X86 = interrupt_kind { + // "x86-interrupt" is special because it does have arguments. + // FIXME(workingjubilee): properly lint on acceptable input types. + if let FnRetTy::Ty(ref ret_ty) = sig.decl.output { + self.dcx().emit_err(errors::AbiMustNotHaveReturnType { + span: ret_ty.span, + abi, + }); + } + } else { + // An `extern "interrupt"` function must have type `fn()`. + self.reject_params_or_return(abi, ident, sig); + } + } + } + } + AbiMapping::Invalid => { /* ignore */ } + } + } + + fn reject_safe_fn(&self, abi: ExternAbi, ctxt: FnCtxt, sig: &FnSig) { let dcx = self.dcx(); - // An `extern "custom"` function must be unsafe. match sig.header.safety { Safety::Unsafe(_) => { /* all good */ } Safety::Safe(safe_span) => { - let safe_span = - self.sess.psess.source_map().span_until_non_whitespace(safe_span.to(sig.span)); + let source_map = self.sess.psess.source_map(); + let safe_span = source_map.span_until_non_whitespace(safe_span.to(sig.span)); dcx.emit_err(errors::AbiCustomSafeForeignFunction { span: sig.span, safe_span }); } Safety::Default => match ctxt { FnCtxt::Foreign => { /* all good */ } FnCtxt::Free | FnCtxt::Assoc(_) => { - self.dcx().emit_err(errors::AbiCustomSafeFunction { + dcx.emit_err(errors::AbiCustomSafeFunction { span: sig.span, + abi, unsafe_span: sig.span.shrink_to_lo(), }); } }, } + } - // An `extern "custom"` function cannot be `async` and/or `gen`. + fn reject_coroutine(&self, abi: ExternAbi, sig: &FnSig) { if let Some(coroutine_kind) = sig.header.coroutine_kind { let coroutine_kind_span = self .sess @@ -397,14 +444,16 @@ impl<'a> AstValidator<'a> { .source_map() .span_until_non_whitespace(coroutine_kind.span().to(sig.span)); - self.dcx().emit_err(errors::AbiCustomCoroutine { + self.dcx().emit_err(errors::AbiCannotBeCoroutine { span: sig.span, + abi, coroutine_kind_span, coroutine_kind_str: coroutine_kind.as_str(), }); } + } - // An `extern "custom"` function must not have any parameters or return type. + fn reject_params_or_return(&self, abi: ExternAbi, ident: &Ident, sig: &FnSig) { let mut spans: Vec<_> = sig.decl.inputs.iter().map(|p| p.span).collect(); if let FnRetTy::Ty(ref ret_ty) = sig.decl.output { spans.push(ret_ty.span); @@ -415,11 +464,12 @@ impl<'a> AstValidator<'a> { let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span()); let padding = if header_span.is_empty() { "" } else { " " }; - self.dcx().emit_err(errors::AbiCustomInvalidSignature { + self.dcx().emit_err(errors::AbiMustNotHaveParametersOrReturnType { spans, symbol: ident.name, suggestion_span, padding, + abi, }); } } @@ -1199,9 +1249,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_fn_bodyless(*ident, body.as_deref()); self.check_foreign_fn_headerless(sig.header); self.check_foreign_item_ascii_only(*ident); - if self.extern_mod_abi == Some(ExternAbi::Custom) { - self.check_custom_abi(FnCtxt::Foreign, ident, sig); - } + self.check_extern_fn_signature( + self.extern_mod_abi.unwrap_or(ExternAbi::FALLBACK), + FnCtxt::Foreign, + ident, + sig, + ); } ForeignItemKind::TyAlias(box TyAlias { defaultness, @@ -1411,9 +1464,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let FnKind::Fn(ctxt, _, fun) = fk && let Extern::Explicit(str_lit, _) = fun.sig.header.ext - && let Ok(ExternAbi::Custom) = ExternAbi::from_str(str_lit.symbol.as_str()) + && let Ok(abi) = ExternAbi::from_str(str_lit.symbol.as_str()) { - self.check_custom_abi(ctxt, &fun.ident, &fun.sig); + self.check_extern_fn_signature(abi, ctxt, &fun.ident, &fun.sig); } self.check_c_variadic_type(fk); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index c437e62f4d373..d387a4a310ea0 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,5 +1,6 @@ //! Errors emitted by ast_passes. +use rustc_abi::ExternAbi; use rustc_ast::ParamKindOrd; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; @@ -845,6 +846,7 @@ pub(crate) struct AbiCustomSafeForeignFunction { pub(crate) struct AbiCustomSafeFunction { #[primary_span] pub span: Span, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -856,10 +858,11 @@ pub(crate) struct AbiCustomSafeFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_coroutine)] -pub(crate) struct AbiCustomCoroutine { +#[diag(ast_passes_abi_cannot_be_coroutine)] +pub(crate) struct AbiCannotBeCoroutine { #[primary_span] pub span: Span, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -872,11 +875,12 @@ pub(crate) struct AbiCustomCoroutine { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_invalid_signature)] +#[diag(ast_passes_abi_must_not_have_parameters_or_return_type)] #[note] -pub(crate) struct AbiCustomInvalidSignature { +pub(crate) struct AbiMustNotHaveParametersOrReturnType { #[primary_span] pub spans: Vec, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -888,3 +892,13 @@ pub(crate) struct AbiCustomInvalidSignature { pub symbol: Symbol, pub padding: &'static str, } + +#[derive(Diagnostic)] +#[diag(ast_passes_abi_must_not_have_return_type)] +#[note] +pub(crate) struct AbiMustNotHaveReturnType { + #[primary_span] + #[help] + pub span: Span, + pub abi: ExternAbi, +} diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index f6b5ff404db65..7651e8365a293 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -357,6 +357,10 @@ impl<'a> State<'a> { self.word_nbsp("raw"); self.print_mutability(mutability, true); } + ast::BorrowKind::Pin => { + self.word_nbsp("pin"); + self.print_mutability(mutability, true); + } } self.print_expr_cond_paren( expr, diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index ae3a1a4138716..dc3598bcc361e 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -212,6 +212,9 @@ pub enum AttributeKind { first_span: Span, }, + /// Represents `#[const_continue]`. + ConstContinue(Span), + /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. ConstStability { stability: PartialConstStability, @@ -231,6 +234,9 @@ pub enum AttributeKind { /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), + /// Represents `#[loop_match]`. + LoopMatch(Span), + /// Represents `#[rustc_macro_transparency]`. MacroTransparency(Transparency), @@ -268,5 +274,8 @@ pub enum AttributeKind { /// Span of the attribute. span: Span, }, + + /// Represents `#[track_caller]` + TrackCaller(Span), // tidy-alphabetical-end } diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 0fa69c401546f..eadf8657a0fd6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,7 +1,7 @@ use rustc_attr_data_structures::{AttributeKind, OptimizeAttr}; use rustc_feature::{AttributeTemplate, template}; use rustc_session::parse::feature_err; -use rustc_span::{Span, sym}; +use rustc_span::{Span, Symbol, sym}; use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; use crate::context::{AcceptContext, FinalizeContext, Stage}; @@ -11,7 +11,7 @@ use crate::session_diagnostics::NakedFunctionIncompatibleAttribute; pub(crate) struct OptimizeParser; impl SingleAttributeParser for OptimizeParser { - const PATH: &[rustc_span::Symbol] = &[sym::optimize]; + const PATH: &[Symbol] = &[sym::optimize]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none"); @@ -44,7 +44,7 @@ impl SingleAttributeParser for OptimizeParser { pub(crate) struct ColdParser; impl SingleAttributeParser for ColdParser { - const PATH: &[rustc_span::Symbol] = &[sym::cold]; + const PATH: &[Symbol] = &[sym::cold]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; const TEMPLATE: AttributeTemplate = template!(Word); @@ -166,6 +166,24 @@ impl AttributeParser for NakedParser { } } +pub(crate) struct TrackCallerParser; + +impl SingleAttributeParser for TrackCallerParser { + const PATH: &[Symbol] = &[sym::track_caller]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + + Some(AttributeKind::TrackCaller(cx.attr_span)) + } +} + pub(crate) struct NoMangleParser; impl SingleAttributeParser for NoMangleParser { diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs new file mode 100644 index 0000000000000..f6c7ac5e3a39c --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -0,0 +1,31 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct LoopMatchParser; +impl SingleAttributeParser for LoopMatchParser { + const PATH: &[Symbol] = &[sym::loop_match]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { + Some(AttributeKind::LoopMatch(cx.attr_span)) + } +} + +pub(crate) struct ConstContinueParser; +impl SingleAttributeParser for ConstContinueParser { + const PATH: &[Symbol] = &[sym::const_continue]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { + Some(AttributeKind::ConstContinue(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index ac7e90fd90256..d407669cb410c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -32,6 +32,7 @@ pub(crate) mod confusables; pub(crate) mod deprecation; pub(crate) mod inline; pub(crate) mod lint_helpers; +pub(crate) mod loop_match; pub(crate) mod must_use; pub(crate) mod repr; pub(crate) mod semantics; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 43b2d07dbe100..6ca5c64e0bc5d 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,11 +15,14 @@ use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; -use crate::attributes::codegen_attrs::{ColdParser, NakedParser, NoMangleParser, OptimizeParser}; +use crate::attributes::codegen_attrs::{ + ColdParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, +}; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser}; +use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; use crate::attributes::must_use::MustUseParser; use crate::attributes::repr::{AlignParser, ReprParser}; use crate::attributes::semantics::MayDangleParser; @@ -111,9 +114,11 @@ attribute_parsers!( // tidy-alphabetical-start Single, Single, + Single, Single, Single, Single, + Single, Single, Single, Single, @@ -121,6 +126,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 32c71f433b0ff..7e356b4b462b2 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -151,20 +151,6 @@ rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist cat <, did: LocalDefId) -> CodegenFnAttrs { // In these cases, we bail from performing further checks that are only meaningful for // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. - let fn_sig = || { + let fn_sig = |attr_span| { use DefKind::*; let def_kind = tcx.def_kind(did); if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { - tcx.dcx().span_delayed_bug( - attr.span(), - "this attribute can only be applied to functions", - ); + tcx.dcx() + .span_delayed_bug(attr_span, "this attribute can only be applied to functions"); None } }; @@ -142,6 +140,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { }); } } + AttributeKind::TrackCaller(attr_span) => { + let is_closure = tcx.is_closure_like(did.to_def_id()); + + if !is_closure + && let Some(fn_sig) = fn_sig(*attr_span) + && fn_sig.skip_binder().abi() != ExternAbi::Rust + { + tcx.dcx().emit_err(errors::RequiresRustAbi { span: *attr_span }); + } + if is_closure + && !tcx.features().closure_track_caller() + && !attr_span.allows_unstable(sym::closure_track_caller) + { + feature_err( + &tcx.sess, + sym::closure_track_caller, + *attr_span, + "`#[track_caller]` on closures is currently unstable", + ) + .emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER + } _ => {} } } @@ -202,29 +223,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::track_caller => { - let is_closure = tcx.is_closure_like(did.to_def_id()); - - if !is_closure - && let Some(fn_sig) = fn_sig() - && fn_sig.skip_binder().abi() != ExternAbi::Rust - { - tcx.dcx().emit_err(errors::RequiresRustAbi { span: attr.span() }); - } - if is_closure - && !tcx.features().closure_track_caller() - && !attr.span().allows_unstable(sym::closure_track_caller) - { - feature_err( - &tcx.sess, - sym::closure_track_caller, - attr.span(), - "`#[track_caller]` on closures is currently unstable", - ) - .emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER - } sym::export_name => { if let Some(s) = attr.value_str() { if s.as_str().contains('\0') { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index e1d8b7546cf42..db5ac6a514fb4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1123,7 +1123,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // While optimizations will remove no-op transmutes, they might still be // there in debug or things that aren't no-op in MIR because they change // the Rust type but not the underlying layout/niche. - if from_scalar == to_scalar && from_backend_ty == to_backend_ty { + if from_scalar == to_scalar { return imm; } @@ -1142,7 +1142,13 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { - (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), + (Int(..) | Float(_), Int(..) | Float(_)) => { + if from_backend_ty == to_backend_ty { + imm + } else { + bx.bitcast(imm, to_backend_ty) + } + } (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), (Pointer(..), Int(..)) => { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 887275e7294d2..f5b7a6066c8b7 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -600,11 +600,13 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(E0764), }), - hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping { - span, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0764), - }), + hir::BorrowKind::Ref | hir::BorrowKind::Pin => { + ccx.dcx().create_err(errors::MutableRefEscaping { + span, + kind: ccx.const_kind(), + teach: ccx.tcx.sess.teach(E0764), + }) + } } } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0775.md b/compiler/rustc_error_codes/src/error_codes/E0775.md index efbd51e89ea3a..9fcd3a6eef741 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0775.md +++ b/compiler/rustc_error_codes/src/error_codes/E0775.md @@ -8,7 +8,7 @@ Erroneous code example: ```ignore (no longer emitted) #![feature(cmse_nonsecure_entry)] -pub extern "C-cmse-nonsecure-entry" fn entry_function() {} +pub extern "cmse-nonsecure-entry" fn entry_function() {} ``` To fix this error, compile your code for a Rust target that supports the diff --git a/compiler/rustc_error_codes/src/error_codes/E0781.md b/compiler/rustc_error_codes/src/error_codes/E0781.md index 7641acfb5249e..22abe0e3cb158 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0781.md +++ b/compiler/rustc_error_codes/src/error_codes/E0781.md @@ -1,12 +1,12 @@ -The `C-cmse-nonsecure-call` ABI can only be used with function pointers. +The `cmse-nonsecure-call` ABI can only be used with function pointers. Erroneous code example: ```compile_fail,E0781 -#![feature(abi_c_cmse_nonsecure_call)] +#![feature(abi_cmse_nonsecure_call)] -pub extern "C-cmse-nonsecure-call" fn test() {} +pub extern "cmse-nonsecure-call" fn test() {} ``` -The `C-cmse-nonsecure-call` ABI should be used by casting function pointers to +The `cmse-nonsecure-call` ABI should be used by casting function pointers to specific addresses. diff --git a/compiler/rustc_error_codes/src/error_codes/E0798.md b/compiler/rustc_error_codes/src/error_codes/E0798.md index da08cde301000..e5f356ef4d50a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0798.md +++ b/compiler/rustc_error_codes/src/error_codes/E0798.md @@ -1,4 +1,4 @@ -Functions marked as `C-cmse-nonsecure-call` place restrictions on their +Functions marked as `cmse-nonsecure-call` place restrictions on their inputs and outputs. - inputs must fit in the 4 available 32-bit argument registers. Alignment @@ -12,12 +12,12 @@ see [arm's aapcs32](https://github.com/ARM-software/abi-aa/releases). Erroneous code example: -```ignore (only fails on supported targets) -#![feature(abi_c_cmse_nonsecure_call)] +```ignore (host errors will not match for target) +#![feature(abi_cmse_nonsecure_call)] #[no_mangle] pub fn test( - f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32, + f: extern "cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32, ) -> u32 { f(1, 2, 3, 4, 5) } @@ -27,12 +27,12 @@ Arguments' alignment is respected. In the example below, padding is inserted so that the `u64` argument is passed in registers r2 and r3. There is then no room left for the final `f32` argument -```ignore (only fails on supported targets) -#![feature(abi_c_cmse_nonsecure_call)] +```ignore (host errors will not match for target) +#![feature(abi_cmse_nonsecure_call)] #[no_mangle] pub fn test( - f: extern "C-cmse-nonsecure-call" fn(u32, u64, f32) -> u32, + f: extern "cmse-nonsecure-call" fn(u32, u64, f32) -> u32, ) -> u32 { f(1, 2, 3.0) } diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 22cc1e894da90..0aff1c06e0a8c 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -690,5 +690,5 @@ E0805: 0805, // E0723, // unstable feature in `const` context // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. // E0744, // merged into E0728 -// E0776, // Removed; cmse_nonsecure_entry is now `C-cmse-nonsecure-entry` +// E0776, // Removed; `#[cmse_nonsecure_entry]` is now `extern "cmse-nonsecure-entry"` // E0796, // unused error code. We use `static_mut_refs` lint instead. diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs index 6b2ad30dffd06..b4c4eac028fe5 100644 --- a/compiler/rustc_expand/src/stats.rs +++ b/compiler/rustc_expand/src/stats.rs @@ -15,15 +15,11 @@ pub struct MacroStat { /// Number of uses of the macro. pub uses: usize, - /// Net increase in number of lines of code (when pretty-printed), i.e. - /// `lines(output) - lines(invocation)`. Can be negative because a macro - /// output may be smaller than the invocation. - pub lines: isize, - - /// Net increase in number of lines of code (when pretty-printed), i.e. - /// `bytes(output) - bytes(invocation)`. Can be negative because a macro - /// output may be smaller than the invocation. - pub bytes: isize, + /// Number of lines of code (when pretty-printed). + pub lines: usize, + + /// Number of bytes of code (when pretty-printed). + pub bytes: usize, } pub(crate) fn elems_to_string(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> String) -> String { @@ -131,16 +127,12 @@ pub(crate) fn update_macro_stats( input: &str, fragment: &AstFragment, ) { - fn lines_and_bytes(s: &str) -> (usize, usize) { - (s.trim_end().split('\n').count(), s.len()) - } - // Measure the size of the output by pretty-printing it and counting // the lines and bytes. let name = Symbol::intern(&pprust::path_to_string(path)); let output = fragment.to_string(); - let (in_l, in_b) = lines_and_bytes(input); - let (out_l, out_b) = lines_and_bytes(&output); + let num_lines = output.trim_end().split('\n').count(); + let num_bytes = output.len(); // This code is useful for debugging `-Zmacro-stats`. For every // invocation it prints the full input and output. @@ -157,7 +149,7 @@ pub(crate) fn update_macro_stats( {name}: [{crate_name}] ({fragment_kind:?}) {span}\n\ -------------------------------\n\ {input}\n\ - -- ({in_l} lines, {in_b} bytes) --> ({out_l} lines, {out_b} bytes) --\n\ + -- {num_lines} lines, {num_bytes} bytes --\n\ {output}\n\ " ); @@ -166,6 +158,6 @@ pub(crate) fn update_macro_stats( // The recorded size is the difference between the input and the output. let entry = ecx.macro_stats.entry((name, macro_kind)).or_insert(MacroStat::default()); entry.uses += 1; - entry.lines += out_l as isize - in_l as isize; - entry.bytes += out_b as isize - in_b as isize; + entry.lines += num_lines; + entry.bytes += num_bytes; } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3540c9b4bf0bd..8c0f279e343b7 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -657,6 +657,19 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const), ), + // The `#[loop_match]` and `#[const_continue]` attributes are part of the + // lang experiment for RFC 3720 tracked in: + // + // - https://github.com/rust-lang/rust/issues/132306 + gated!( + const_continue, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::No, loop_match, experimental!(const_continue) + ), + gated!( + loop_match, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::No, loop_match, experimental!(loop_match) + ), + // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index c54b831e24448..ddb99585bc243 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -54,6 +54,7 @@ declare_features! ( /// Allows using the `amdgpu-kernel` ABI. (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None, 120495), + (removed, abi_c_cmse_nonsecure_call, "CURRENT_RUSTC_VERSION", Some(81391), Some("renamed to abi_cmse_nonsecure_call"), 142146), (removed, advanced_slice_patterns, "1.42.0", Some(62254), Some("merged into `#![feature(slice_patterns)]`"), 67712), (removed, allocator, "1.0.0", None, None), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 91715851226bb..e73a4e1766ce5 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -353,8 +353,8 @@ declare_features! ( /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. (unstable, abi_avr_interrupt, "1.45.0", Some(69664)), - /// Allows `extern "C-cmse-nonsecure-call" fn()`. - (unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391)), + /// Allows `extern "cmse-nonsecure-call" fn()`. + (unstable, abi_cmse_nonsecure_call, "CURRENT_RUSTC_VERSION", Some(81391)), /// Allows `extern "custom" fn()`. (unstable, abi_custom, "CURRENT_RUSTC_VERSION", Some(140829)), /// Allows `extern "gpu-kernel" fn()`. @@ -431,7 +431,7 @@ declare_features! ( (unstable, closure_lifetime_binder, "1.64.0", Some(97362)), /// Allows `#[track_caller]` on closures and coroutines. (unstable, closure_track_caller, "1.57.0", Some(87417)), - /// Allows `extern "C-cmse-nonsecure-entry" fn()`. + /// Allows `extern "cmse-nonsecure-entry" fn()`. (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)), /// Allows `async {}` expressions in const contexts. (unstable, const_async_blocks, "1.53.0", Some(85368)), @@ -557,6 +557,8 @@ declare_features! ( /// Allows using `#[link(kind = "link-arg", name = "...")]` /// to pass custom arguments to the linker. (unstable, link_arg_attribute, "1.76.0", Some(99427)), + /// Allows fused `loop`/`match` for direct intraprocedural jumps. + (incomplete, loop_match, "CURRENT_RUSTC_VERSION", Some(132306)), /// Give access to additional metadata about declarative macro meta-variables. (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Provides a way to concatenate identifiers using metavariable expressions. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index bd2252c1bf8fd..4ec2bbfc5abe1 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -1,5 +1,5 @@ hir_analysis_abi_custom_clothed_function = - items with the `"custom"` ABI can only be declared externally or defined via naked functions + items with the "custom" ABI can only be declared externally or defined via naked functions .suggestion = convert this to an `#[unsafe(naked)]` function hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}` @@ -73,10 +73,10 @@ hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are fo .label = `for<...>` is here hir_analysis_cmse_call_generic = - function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type + function pointers with the `"cmse-nonsecure-call"` ABI cannot contain generics in their type hir_analysis_cmse_entry_generic = - functions with the `"C-cmse-nonsecure-entry"` ABI cannot contain generics in their type + functions with the `"cmse-nonsecure-entry"` ABI cannot contain generics in their type hir_analysis_cmse_inputs_stack_spill = arguments for `{$abi}` function too large to pass via registers diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 3bad36da99909..b556683e80a54 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -1,14 +1,15 @@ use std::ops::Not; use rustc_abi::ExternAbi; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_hir as hir; use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_session::config::EntryFnType; +use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; @@ -98,8 +99,10 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { error = true; } - for attr in tcx.get_attrs(main_def_id, sym::track_caller) { - tcx.dcx().emit_err(errors::TrackCallerOnMain { span: attr.span(), annotated: main_span }); + if let Some(attr_span) = + find_attr!(tcx.get_all_attrs(main_def_id), AttributeKind::TrackCaller(span) => *span) + { + tcx.dcx().emit_err(errors::TrackCallerOnMain { span: attr_span, annotated: main_span }); error = true; } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index ebeb3b58208eb..82e5f65476ff9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -18,7 +18,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( fn_sig: ty::PolyFnSig<'tcx>, ) { match abi { - ExternAbi::CCmseNonSecureCall => { + ExternAbi::CmseNonSecureCall => { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { span: bare_fn_span, @@ -38,7 +38,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( dcx, span, E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + "the `\"cmse-nonsecure-call\"` ABI is only allowed on function pointers" ) .emit(); return; @@ -78,7 +78,7 @@ pub(crate) fn validate_cmse_abi<'tcx>( } }; } - ExternAbi::CCmseNonSecureEntry => { + ExternAbi::CmseNonSecureEntry => { let hir_node = tcx.hir_node(hir_id); let Some(hir::FnSig { decl, span: fn_sig_span, .. }) = hir_node.fn_sig() else { // might happen when this ABI is used incorrectly. That will be handled elsewhere @@ -203,11 +203,11 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError match layout_err { TooGeneric(ty) => { match abi { - ExternAbi::CCmseNonSecureCall => { + ExternAbi::CmseNonSecureCall => { // prevent double reporting of this error !ty.is_impl_trait() } - ExternAbi::CCmseNonSecureEntry => true, + ExternAbi::CmseNonSecureEntry => true, _ => bug!("invalid ABI: {abi}"), } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d3289e4cc6d0f..ff87d3dec6e96 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1335,6 +1335,10 @@ impl<'a> State<'a> { self.word_nbsp("raw"); self.print_mutability(mutability, true); } + hir::BorrowKind::Pin => { + self.word_nbsp("pin"); + self.print_mutability(mutability, true); + } } self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix); } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 258535f3742d4..c21b16c9f9f04 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -79,6 +79,9 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to -> .note = the type information given here is insufficient to check whether the pointer cast is valid .label_from = the type information given here is insufficient to check whether the pointer cast is valid +hir_typeck_const_continue_bad_label = + `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` + hir_typeck_const_select_must_be_const = this argument must be a `const fn` .help = consult the documentation on `const_eval_select` for more information diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 5fea0c6284334..3606c778fc407 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -1167,3 +1167,10 @@ pub(crate) struct AbiCannotBeCalled { pub span: Span, pub abi: ExternAbi, } + +#[derive(Diagnostic)] +#[diag(hir_typeck_const_continue_bad_label)] +pub(crate) struct ConstContinueBadLabel { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 672f3bc67cef8..2bc9dadb6653b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -690,7 +690,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_named_place_expr(oprnd); Ty::new_ptr(self.tcx, ty, mutbl) } - hir::BorrowKind::Ref => { + hir::BorrowKind::Ref | hir::BorrowKind::Pin => { // Note: at this point, we cannot say what the best lifetime // is to use for resulting pointer. We want to use the // shortest lifetime possible so as to avoid spurious borrowck @@ -706,7 +706,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // whose address was taken can actually be made to live as long // as it needs to live. let region = self.next_region_var(infer::BorrowRegion(expr.span)); - Ty::new_ref(self.tcx, region, ty, mutbl) + match kind { + hir::BorrowKind::Ref => Ty::new_ref(self.tcx, region, ty, mutbl), + hir::BorrowKind::Pin => Ty::new_pinned_ref(self.tcx, region, ty, mutbl), + _ => unreachable!(), + } } } } diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index b06e0704b6ff5..80eab578f1342 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -2,6 +2,8 @@ use std::collections::BTreeMap; use std::fmt; use Context::*; +use rustc_ast::Label; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -14,8 +16,9 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::{BytePos, Span}; use crate::errors::{ - BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, - OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, + BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ConstContinueBadLabel, + ContinueLabeledBlock, OutsideLoop, OutsideLoopSuggestion, UnlabeledCfInWhileCondition, + UnlabeledInLabeledBlock, }; /// The context in which a block is encountered. @@ -37,6 +40,11 @@ enum Context { AnonConst, /// E.g. `const { ... }`. ConstBlock, + /// E.g. `#[loop_match] loop { state = 'label: { /* ... */ } }`. + LoopMatch { + /// The label of the labeled block (not of the loop itself). + labeled_block: Label, + }, } #[derive(Clone)] @@ -141,7 +149,12 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { } } hir::ExprKind::Loop(ref b, _, source, _) => { - self.with_context(Loop(source), |v| v.visit_block(b)); + let cx = match self.is_loop_match(e, b) { + Some(labeled_block) => LoopMatch { labeled_block }, + None => Loop(source), + }; + + self.with_context(cx, |v| v.visit_block(b)); } hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, fn_decl_span, kind, .. @@ -197,6 +210,23 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> { Err(hir::LoopIdError::UnresolvedLabel) => None, }; + // A `#[const_continue]` must break to a block in a `#[loop_match]`. + if find_attr!(self.tcx.hir_attrs(e.hir_id), AttributeKind::ConstContinue(_)) { + if let Some(break_label) = break_label.label { + let is_target_label = |cx: &Context| match cx { + Context::LoopMatch { labeled_block } => { + break_label.ident.name == labeled_block.ident.name + } + _ => false, + }; + + if !self.cx_stack.iter().rev().any(is_target_label) { + let span = break_label.ident.span; + self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span }); + } + } + } + if let Some(Node::Block(_)) = loop_id.map(|id| self.tcx.hir_node(id)) { return; } @@ -299,7 +329,7 @@ impl<'hir> CheckLoopVisitor<'hir> { cx_pos: usize, ) { match self.cx_stack[cx_pos] { - LabeledBlock | Loop(_) => {} + LabeledBlock | Loop(_) | LoopMatch { .. } => {} Closure(closure_span) => { self.tcx.dcx().emit_err(BreakInsideClosure { span, @@ -380,4 +410,36 @@ impl<'hir> CheckLoopVisitor<'hir> { }); } } + + /// Is this a loop annotated with `#[loop_match]` that looks syntactically sound? + fn is_loop_match( + &self, + e: &'hir hir::Expr<'hir>, + body: &'hir hir::Block<'hir>, + ) -> Option