diff --git a/.gitignore b/.gitignore index 0030f22363c24..91a2647ca98f4 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,7 @@ no_llvm_build /llvm/ /mingw-build/ /build -/build-rust-analyzer/ +/build-rust-analyzer /dist/ /unicode-downloads /target diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index e3b2b1eff72d4..0625759359ea3 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -276,6 +276,51 @@ impl ExternAbi { _ => CVariadicStatus::NotSupported, } } + + /// Returns whether the ABI supports guaranteed tail calls. + #[cfg(feature = "nightly")] + pub fn supports_guaranteed_tail_call(self) -> bool { + match self { + Self::CmseNonSecureCall | Self::CmseNonSecureEntry => { + // See https://godbolt.org/z/9jhdeqErv. The CMSE calling conventions clear registers + // before returning, and hence cannot guarantee a tail call. + false + } + Self::AvrInterrupt + | Self::AvrNonBlockingInterrupt + | Self::Msp430Interrupt + | Self::RiscvInterruptM + | Self::RiscvInterruptS + | Self::X86Interrupt => { + // See https://godbolt.org/z/Edfjnxxcq. Interrupts cannot be called directly. + false + } + Self::GpuKernel | Self::PtxKernel => { + // See https://godbolt.org/z/jq5TE5jK1. + false + } + Self::Custom => { + // This ABI does not support calls at all (except via assembly). + false + } + Self::C { .. } + | Self::System { .. } + | Self::Rust + | Self::RustCall + | Self::RustCold + | Self::RustInvalid + | Self::Unadjusted + | Self::EfiApi + | Self::Aapcs { .. } + | Self::Cdecl { .. } + | Self::Stdcall { .. } + | Self::Fastcall { .. } + | Self::Thiscall { .. } + | Self::Vectorcall { .. } + | Self::SysV64 { .. } + | Self::Win64 { .. } => true, + } + } } pub fn all_names() -> Vec<&'static str> { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c55fe3fad008a..fde7dd6ef7a85 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -683,7 +683,7 @@ pub(crate) unsafe fn llvm_optimize( // Here we map the old arguments to the new arguments, with an offset of 1 to make sure // that we don't use the newly added `%dyn_ptr`. unsafe { - llvm::LLVMRustOffloadMapper(cx.llmod(), old_fn, new_fn); + llvm::LLVMRustOffloadMapper(old_fn, new_fn); } llvm::set_linkage(new_fn, llvm::get_linkage(old_fn)); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 16549f9aab81a..ca64d96c2a33c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2025,7 +2025,7 @@ unsafe extern "C" { ) -> &Attribute; // Operations on functions - pub(crate) fn LLVMRustOffloadMapper<'a>(M: &'a Module, Fn: &'a Value, Fn: &'a Value); + pub(crate) fn LLVMRustOffloadMapper<'a>(Fn: &'a Value, Fn: &'a Value); pub(crate) fn LLVMRustGetOrInsertFunction<'a>( M: &'a Module, Name: *const c_char, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 810a5a21a055b..946f17943fe3d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1099,6 +1099,9 @@ pub struct Indeterminate; pub struct DeriveResolution { pub path: ast::Path, pub item: Annotatable, + // FIXME: currently this field is only used in `is_none`/`is_some` conditions. However, the + // `Arc` will be used if the FIXME in `MacroExpander::fully_expand_fragment` + // is completed. pub exts: Option>, pub is_const: bool, } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index eab65f92e2935..8823c83922822 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -144,9 +144,7 @@ extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) { llvm::PrintStatistics(OS); } -extern "C" void LLVMRustOffloadMapper(LLVMModuleRef M, LLVMValueRef OldFn, - LLVMValueRef NewFn) { - llvm::Module *module = llvm::unwrap(M); +extern "C" void LLVMRustOffloadMapper(LLVMValueRef OldFn, LLVMValueRef NewFn) { llvm::Function *oldFn = llvm::unwrap(OldFn); llvm::Function *newFn = llvm::unwrap(NewFn); diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index 9115c17f37525..b8547e288027a 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -135,6 +135,10 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi); } + if !callee_sig.abi.supports_guaranteed_tail_call() { + self.report_unsupported_abi(expr.span, callee_sig.abi); + } + // FIXME(explicit_tail_calls): this currently fails for cases where opaques are used. // e.g. // ``` @@ -358,6 +362,16 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { self.found_errors = Err(err); } + fn report_unsupported_abi(&mut self, sp: Span, callee_abi: ExternAbi) { + let err = self + .tcx + .dcx() + .struct_span_err(sp, "ABI does not support guaranteed tail calls") + .with_note(format!("`become` is not supported for `extern {callee_abi}` functions")) + .emit(); + self.found_errors = Err(err); + } + fn report_signature_mismatch( &mut self, sp: Span, diff --git a/compiler/rustc_mir_transform/src/coverage/expansion.rs b/compiler/rustc_mir_transform/src/coverage/expansion.rs index 851bbaeed48eb..827df27da52c7 100644 --- a/compiler/rustc_mir_transform/src/coverage/expansion.rs +++ b/compiler/rustc_mir_transform/src/coverage/expansion.rs @@ -1,7 +1,12 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; +use rustc_middle::mir; use rustc_middle::mir::coverage::BasicCoverageBlock; use rustc_span::{ExpnId, ExpnKind, Span}; +use crate::coverage::from_mir; +use crate::coverage::graph::CoverageGraph; +use crate::coverage::hir_info::ExtractedHirInfo; + #[derive(Clone, Copy, Debug)] pub(crate) struct SpanWithBcb { pub(crate) span: Span, @@ -70,6 +75,10 @@ pub(crate) struct ExpnNode { pub(crate) spans: Vec, /// Expansions whose call-site is in this expansion. pub(crate) child_expn_ids: FxIndexSet, + + /// Hole spans belonging to this expansion, to be carved out from the + /// code spans during span refinement. + pub(crate) hole_spans: Vec, } impl ExpnNode { @@ -88,17 +97,27 @@ impl ExpnNode { spans: vec![], child_expn_ids: FxIndexSet::default(), + + hole_spans: vec![], } } } -/// Given a collection of span/BCB pairs from potentially-different syntax contexts, +/// Extracts raw span/BCB pairs from potentially-different syntax contexts, and /// arranges them into an "expansion tree" based on their expansion call-sites. -pub(crate) fn build_expn_tree(spans: impl IntoIterator) -> ExpnTree { +pub(crate) fn build_expn_tree( + mir_body: &mir::Body<'_>, + hir_info: &ExtractedHirInfo, + graph: &CoverageGraph, +) -> ExpnTree { + let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph); + let mut nodes = FxIndexMap::default(); let new_node = |&expn_id: &ExpnId| ExpnNode::new(expn_id); - for span_with_bcb in spans { + for from_mir::RawSpanFromMir { raw_span, bcb } in raw_spans { + let span_with_bcb = SpanWithBcb { span: raw_span, bcb }; + // Create a node for this span's enclosing expansion, and add the span to it. let expn_id = span_with_bcb.span.ctxt().outer_expn(); let node = nodes.entry(expn_id).or_insert_with_key(new_node); @@ -123,5 +142,13 @@ pub(crate) fn build_expn_tree(spans: impl IntoIterator) -> E } } + // Associate each hole span (extracted from HIR) with its corresponding + // expansion tree node. + for &hole_span in &hir_info.hole_spans { + let expn_id = hole_span.ctxt().outer_expn(); + let Some(node) = nodes.get_mut(&expn_id) else { continue }; + node.hole_spans.push(hole_span); + } + ExpnTree { nodes } } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/from_mir.rs similarity index 94% rename from compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs rename to compiler/rustc_mir_transform/src/coverage/from_mir.rs index c096f1e2632ce..e1623f590a8eb 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/from_mir.rs @@ -142,19 +142,3 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span), } } - -#[derive(Debug)] -pub(crate) struct Hole { - pub(crate) span: Span, -} - -impl Hole { - pub(crate) fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool { - if !self.span.overlaps_or_adjacent(other.span) { - return false; - } - - self.span = self.span.to(other.span); - true - } -} diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 8dbe564f51749..5347e1150e5de 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -5,6 +5,7 @@ use rustc_middle::mir::coverage::{ use rustc_middle::mir::{self, BasicBlock, StatementKind}; use rustc_middle::ty::TyCtxt; +use crate::coverage::expansion; use crate::coverage::graph::CoverageGraph; use crate::coverage::hir_info::ExtractedHirInfo; use crate::coverage::spans::extract_refined_covspans; @@ -23,10 +24,12 @@ pub(crate) fn extract_mappings_from_mir<'tcx>( hir_info: &ExtractedHirInfo, graph: &CoverageGraph, ) -> ExtractedMappings { + let expn_tree = expansion::build_expn_tree(mir_body, hir_info, graph); + let mut mappings = vec![]; // Extract ordinary code mappings from MIR statement/terminator spans. - extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut mappings); + extract_refined_covspans(tcx, hir_info, graph, &expn_tree, &mut mappings); extract_branch_mappings(mir_body, hir_info, graph, &mut mappings); diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 08c7d346009c6..cc9d7c800a96b 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -9,6 +9,7 @@ use crate::coverage::mappings::ExtractedMappings; mod counters; mod expansion; +mod from_mir; mod graph; mod hir_info; mod mappings; diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 325935ee84682..2a06b409e8c2d 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,22 +1,18 @@ -use rustc_middle::mir; use rustc_middle::mir::coverage::{Mapping, MappingKind, START_BCB}; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, DesugaringKind, ExpnId, ExpnKind, MacroKind, Span}; use tracing::instrument; -use crate::coverage::expansion::{self, ExpnTree, SpanWithBcb}; +use crate::coverage::expansion::{ExpnTree, SpanWithBcb}; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; use crate::coverage::hir_info::ExtractedHirInfo; -use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir}; - -mod from_mir; pub(super) fn extract_refined_covspans<'tcx>( tcx: TyCtxt<'tcx>, - mir_body: &mir::Body<'tcx>, hir_info: &ExtractedHirInfo, graph: &CoverageGraph, + expn_tree: &ExpnTree, mappings: &mut Vec, ) { if hir_info.is_async_fn { @@ -32,22 +28,32 @@ pub(super) fn extract_refined_covspans<'tcx>( let &ExtractedHirInfo { body_span, .. } = hir_info; - let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph); - // Use the raw spans to build a tree of expansions for this function. - let expn_tree = expansion::build_expn_tree( - raw_spans - .into_iter() - .map(|RawSpanFromMir { raw_span, bcb }| SpanWithBcb { span: raw_span, bcb }), - ); + // If there somehow isn't an expansion tree node corresponding to the + // body span, return now and don't create any mappings. + let Some(node) = expn_tree.get(body_span.ctxt().outer_expn()) else { return }; let mut covspans = vec![]; - let mut push_covspan = |covspan: Covspan| { + + for &SpanWithBcb { span, bcb } in &node.spans { + covspans.push(Covspan { span, bcb }); + } + + // For each expansion with its call-site in the body span, try to + // distill a corresponding covspan. + for &child_expn_id in &node.child_expn_ids { + if let Some(covspan) = single_covspan_for_child_expn(tcx, graph, &expn_tree, child_expn_id) + { + covspans.push(covspan); + } + } + + covspans.retain(|covspan: &Covspan| { let covspan_span = covspan.span; // Discard any spans not contained within the function body span. // Also discard any spans that fill the entire body, because they tend // to represent compiler-inserted code, e.g. implicitly returning `()`. if !body_span.contains(covspan_span) || body_span.source_equal(covspan_span) { - return; + return false; } // Each pushed covspan should have the same context as the body span. @@ -57,27 +63,11 @@ pub(super) fn extract_refined_covspans<'tcx>( false, "span context mismatch: body_span={body_span:?}, covspan.span={covspan_span:?}" ); - return; + return false; } - covspans.push(covspan); - }; - - if let Some(node) = expn_tree.get(body_span.ctxt().outer_expn()) { - for &SpanWithBcb { span, bcb } in &node.spans { - push_covspan(Covspan { span, bcb }); - } - - // For each expansion with its call-site in the body span, try to - // distill a corresponding covspan. - for &child_expn_id in &node.child_expn_ids { - if let Some(covspan) = - single_covspan_for_child_expn(tcx, graph, &expn_tree, child_expn_id) - { - push_covspan(covspan); - } - } - } + true + }); // Only proceed if we found at least one usable span. if covspans.is_empty() { @@ -107,14 +97,8 @@ pub(super) fn extract_refined_covspans<'tcx>( covspans.dedup_by(|b, a| a.span.source_equal(b.span)); // Sort the holes, and merge overlapping/adjacent holes. - let mut holes = hir_info - .hole_spans - .iter() - .copied() - // Discard any holes that aren't directly visible within the body span. - .filter(|&hole_span| body_span.contains(hole_span) && body_span.eq_ctxt(hole_span)) - .map(|span| Hole { span }) - .collect::>(); + let mut holes = node.hole_spans.iter().copied().map(|span| Hole { span }).collect::>(); + holes.sort_by(|a, b| compare_spans(a.span, b.span)); holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b)); @@ -295,3 +279,19 @@ fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option { }) .ok()? } + +#[derive(Debug)] +struct Hole { + span: Span, +} + +impl Hole { + fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool { + if !self.span.overlaps_or_adjacent(other.span) { + return false; + } + + self.span = self.span.to(other.span); + true + } +} diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index f3f0a74d03bc0..8ecae07dea67d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -458,14 +458,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut result = Err(Determinacy::Determined); for derive in parent_scope.derives { let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; - match this.reborrow().resolve_macro_path( + match this.reborrow().resolve_derive_macro_path( derive, - MacroKind::Derive, parent_scope, - true, force, ignore_import, - None, ) { Ok((Some(ext), _)) => { if ext.helper_attrs.contains(&ident.name) { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 323b49e14a575..828759e2472f1 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -396,14 +396,11 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { for (i, resolution) in entry.resolutions.iter_mut().enumerate() { if resolution.exts.is_none() { resolution.exts = Some( - match self.cm().resolve_macro_path( + match self.cm().resolve_derive_macro_path( &resolution.path, - MacroKind::Derive, &parent_scope, - true, force, None, - None, ) { Ok((Some(ext), _)) => { if !ext.helper_attrs.is_empty() { @@ -571,7 +568,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { path, kind, parent_scope, - true, force, deleg_impl, invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)), @@ -713,26 +709,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok((ext, res)) } - pub(crate) fn resolve_macro_path<'r>( + pub(crate) fn resolve_derive_macro_path<'r>( self: CmResolver<'r, 'ra, 'tcx>, path: &ast::Path, - kind: MacroKind, parent_scope: &ParentScope<'ra>, - trace: bool, force: bool, ignore_import: Option>, - suggestion_span: Option, ) -> Result<(Option>, Res), Determinacy> { self.resolve_macro_or_delegation_path( path, - kind, + MacroKind::Derive, parent_scope, - trace, force, None, None, ignore_import, - suggestion_span, + None, ) } @@ -741,7 +733,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ast_path: &ast::Path, kind: MacroKind, parent_scope: &ParentScope<'ra>, - trace: bool, force: bool, deleg_impl: Option, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, @@ -780,16 +771,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PathResult::Module(..) => unreachable!(), }; - if trace { - self.multi_segment_macro_resolutions.borrow_mut(&self).push(( - path, - path_span, - kind, - *parent_scope, - res.ok(), - ns, - )); - } + self.multi_segment_macro_resolutions.borrow_mut(&self).push(( + path, + path_span, + kind, + *parent_scope, + res.ok(), + ns, + )); self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span); res @@ -807,15 +796,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Err(Determinacy::Undetermined); } - if trace { - self.single_segment_macro_resolutions.borrow_mut(&self).push(( - path[0].ident, - kind, - *parent_scope, - binding.ok(), - suggestion_span, - )); - } + self.single_segment_macro_resolutions.borrow_mut(&self).push(( + path[0].ident, + kind, + *parent_scope, + binding.ok(), + suggestion_span, + )); let res = binding.map(|binding| binding.res()); self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span); diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index fde6b80a62fe6..2b767ffe02bee 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -725,9 +725,9 @@ impl Box { #[unstable(feature = "box_take", issue = "147212")] pub fn take(boxed: Self) -> (T, Box, A>) { unsafe { - let (raw, alloc) = Box::into_raw_with_allocator(boxed); + let (raw, alloc) = Box::into_non_null_with_allocator(boxed); let value = raw.read(); - let uninit = Box::from_raw_in(raw.cast::>(), alloc); + let uninit = Box::from_non_null_in(raw.cast_uninit(), alloc); (value, uninit) } } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 666ae27fb8634..dc58b30afbce3 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -116,6 +116,7 @@ #![feature(exact_size_is_empty)] #![feature(extend_one)] #![feature(extend_one_unchecked)] +#![feature(fmt_arguments_from_str)] #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(formatting_options)] diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 09d9b160700ca..9a35ed07b89ac 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -15,18 +15,18 @@ use crate::{fmt, ops, slice, str}; // actually reference libstd or liballoc in intra-doc links. so, the best we can do is remove the // links to `CString` and `String` for now until a solution is developed -/// Representation of a borrowed C string. +/// A dynamically-sized view of a C string. /// -/// This type represents a borrowed reference to a nul-terminated +/// The type `&CStr` represents a reference to a borrowed nul-terminated /// array of bytes. It can be constructed safely from a &[[u8]] /// slice, or unsafely from a raw `*const c_char`. It can be expressed as a /// literal in the form `c"Hello world"`. /// -/// The `CStr` can then be converted to a Rust &[str] by performing +/// The `&CStr` can then be converted to a Rust &[str] by performing /// UTF-8 validation, or into an owned `CString`. /// /// `&CStr` is to `CString` as &[str] is to `String`: the former -/// in each pair are borrowed references; the latter are owned +/// in each pair are borrowing references; the latter are owned /// strings. /// /// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)` diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e00e48bcfeb70..7ca33d363cd8f 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -734,7 +734,21 @@ impl<'a> Arguments<'a> { unsafe { Arguments { template: mem::transmute(template), args: mem::transmute(args) } } } + // Same as `from_str`, but not const. + // Used by format_args!() expansion when arguments are inlined, + // e.g. format_args!("{}", 123), which is not allowed in const. #[inline] + pub fn from_str_nonconst(s: &'static str) -> Arguments<'a> { + Arguments::from_str(s) + } +} + +impl<'a> Arguments<'a> { + /// Create a `fmt::Arguments` object for a single static string. + /// + /// Formatting this `fmt::Arguments` will just produce the string as-is. + #[inline] + #[unstable(feature = "fmt_arguments_from_str", issue = "148905")] pub const fn from_str(s: &'static str) -> Arguments<'a> { // SAFETY: This is the "static str" representation of fmt::Arguments; see above. unsafe { @@ -744,14 +758,6 @@ impl<'a> Arguments<'a> { } } } - - // Same as `from_str`, but not const. - // Used by format_args!() expansion when arguments are inlined, - // e.g. format_args!("{}", 123), which is not allowed in const. - #[inline] - pub fn from_str_nonconst(s: &'static str) -> Arguments<'a> { - Arguments::from_str(s) - } } #[doc(hidden)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index df24dd43b82eb..6156525b2f599 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -991,7 +991,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "format_args_macro"] #[allow_internal_unsafe] - #[allow_internal_unstable(fmt_internals)] + #[allow_internal_unstable(fmt_internals, fmt_arguments_from_str)] #[rustc_builtin_macro] #[macro_export] macro_rules! format_args { @@ -1005,7 +1005,7 @@ pub(crate) mod builtin { /// /// This macro will be removed once `format_args` is allowed in const contexts. #[unstable(feature = "const_format_args", issue = "none")] - #[allow_internal_unstable(fmt_internals, const_fmt_arguments_new)] + #[allow_internal_unstable(fmt_internals, fmt_arguments_from_str)] #[rustc_builtin_macro] #[macro_export] macro_rules! const_format_args { @@ -1020,7 +1020,7 @@ pub(crate) mod builtin { reason = "`format_args_nl` is only for internal \ language use and is subject to change" )] - #[allow_internal_unstable(fmt_internals)] + #[allow_internal_unstable(fmt_internals, fmt_arguments_from_str)] #[rustc_builtin_macro] #[doc(hidden)] #[macro_export] diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 25a4661a0bc9c..b7756befa11e9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -330,7 +330,7 @@ pub use self::{ stdio::{Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout}, util::{Empty, Repeat, Sink, empty, repeat, sink}, }; -use crate::mem::take; +use crate::mem::{MaybeUninit, take}; use crate::ops::{Deref, DerefMut}; use crate::{cmp, fmt, slice, str, sys}; @@ -1242,6 +1242,46 @@ pub trait Read { { Take { inner: self, len: limit, limit } } + + /// Read and return a fixed array of bytes from this source. + /// + /// This function uses an array sized based on a const generic size known at compile time. You + /// can specify the size with turbofish (`reader.read_array::<8>()`), or let type inference + /// determine the number of bytes needed based on how the return value gets used. For instance, + /// this function works well with functions like [`u64::from_le_bytes`] to turn an array of + /// bytes into an integer of the same size. + /// + /// Like `read_exact`, if this function encounters an "end of file" before reading the desired + /// number of bytes, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// + /// ``` + /// #![feature(read_array)] + /// use std::io::Cursor; + /// use std::io::prelude::*; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buf = Cursor::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2]); + /// let x = u64::from_le_bytes(buf.read_array()?); + /// let y = u32::from_be_bytes(buf.read_array()?); + /// let z = u16::from_be_bytes(buf.read_array()?); + /// assert_eq!(x, 0x807060504030201); + /// assert_eq!(y, 0x9080706); + /// assert_eq!(z, 0x504); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "read_array", issue = "148848")] + fn read_array(&mut self) -> Result<[u8; N]> + where + Self: Sized, + { + let mut buf = [MaybeUninit::uninit(); N]; + let mut borrowed_buf = BorrowedBuf::from(buf.as_mut_slice()); + self.read_buf_exact(borrowed_buf.unfilled())?; + // Guard against incorrect `read_buf_exact` implementations. + assert_eq!(borrowed_buf.len(), N); + Ok(unsafe { MaybeUninit::array_assume_init(buf) }) + } } /// Reads all bytes from a [reader][Read] into a new [`String`]. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7b6cfbfe0f259..5374e9e61783f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -348,6 +348,7 @@ #![feature(int_from_ascii)] #![feature(ip)] #![feature(lazy_get)] +#![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] #![feature(panic_can_unwind)] diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index b2c3d0d3f9f8b..be2980f73268f 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -16,6 +16,7 @@ all(target_arch = "powerpc64", target_os = "linux"), feature(stdarch_powerpc_feature_detection) )] +#![cfg_attr(all(target_arch = "s390x", target_os = "linux"), feature(s390x_target_feature))] #[test] #[cfg(all(target_arch = "arm", any(target_os = "linux", target_os = "android")))] diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 4843c20c758e6..b7f6d84ea36c2 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -838,9 +838,23 @@ fn print_higher_ranked_params_with_space( pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display { fmt::from_fn(move |f| { if let Ok(HrefInfo { url, kind, rust_path }) = href(did, cx) { + let tcx = cx.tcx(); + let def_kind = tcx.def_kind(did); + let anchor = if matches!( + def_kind, + DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant + ) { + let parent_def_id = tcx.parent(did); + let item_type = + ItemType::from_def_kind(def_kind, Some(tcx.def_kind(parent_def_id))); + format!("#{}.{}", item_type.as_str(), tcx.item_name(did)) + } else { + String::new() + }; + write!( f, - r#"{text}"#, + r#"{text}"#, path = join_path_syms(rust_path), text = EscapeBodyText(text.as_str()), ) diff --git a/tests/assembly-llvm/tail-call-infinite-recursion.rs b/tests/assembly-llvm/tail-call-infinite-recursion.rs new file mode 100644 index 0000000000000..f788f0d590b6b --- /dev/null +++ b/tests/assembly-llvm/tail-call-infinite-recursion.rs @@ -0,0 +1,21 @@ +//@ add-minicore +//@ assembly-output: emit-asm +//@ compile-flags: --target x86_64-unknown-linux-gnu -Copt-level=0 -Cllvm-args=-x86-asm-syntax=intel +//@ needs-llvm-components: x86 +#![expect(incomplete_features)] +#![feature(no_core, explicit_tail_calls)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +// Test that an infinite loop via guaranteed tail calls does not blow the stack. + +// CHECK-LABEL: inf +// CHECK: mov rax, qword ptr [rip + inf@GOTPCREL] +// CHECK: jmp rax +#[unsafe(no_mangle)] +fn inf() -> ! { + become inf() +} diff --git a/tests/mir-opt/uninhabited_enum.rs b/tests/mir-opt/uninhabited_enum.rs index 90b5353f29143..124693c0fe2cc 100644 --- a/tests/mir-opt/uninhabited_enum.rs +++ b/tests/mir-opt/uninhabited_enum.rs @@ -1,4 +1,7 @@ // skip-filecheck +// +// check that we mark blocks with `!` locals as unreachable. +// (and currently don't do the same for other uninhabited types) #![feature(never_type)] #[derive(Copy, Clone)] diff --git a/tests/mir-opt/uninhabited_not_read.rs b/tests/mir-opt/uninhabited_not_read.rs index 15769cdd75b3f..4c80f5e55c684 100644 --- a/tests/mir-opt/uninhabited_not_read.rs +++ b/tests/mir-opt/uninhabited_not_read.rs @@ -1,7 +1,7 @@ // skip-filecheck //@ edition: 2021 -// In ed 2021 and below, we don't fallback `!` to `()`. +// In ed 2021 and below, we fallback `!` to `()`. // This would introduce a `! -> ()` coercion which would // be UB if we didn't disallow this explicitly. diff --git a/tests/run-make/rustdoc-test-builder/rmake.rs b/tests/run-make/rustdoc-test-builder/rmake.rs index d10a3c92cae42..17d40c68fd922 100644 --- a/tests/run-make/rustdoc-test-builder/rmake.rs +++ b/tests/run-make/rustdoc-test-builder/rmake.rs @@ -25,7 +25,10 @@ fn main() { // Some targets (for example wasm) cannot execute doctests directly even with a runner, // so only exercise the success path when the target can run on the host. - if target().contains("wasm") || std::env::var_os("REMOTE_TEST_CLIENT").is_some() { + if target().contains("wasm") + || target().contains("sgx") + || std::env::var_os("REMOTE_TEST_CLIENT").is_some() + { return; } diff --git a/tests/rustdoc/import_trait_associated_functions.rs b/tests/rustdoc/import_trait_associated_functions.rs new file mode 100644 index 0000000000000..84f6f8009701d --- /dev/null +++ b/tests/rustdoc/import_trait_associated_functions.rs @@ -0,0 +1,19 @@ +// This test ensures that reexports of associated items links to the associated items. +// Regression test for . + +#![feature(import_trait_associated_functions)] + +#![crate_name = "foo"] + +//@ has 'foo/index.html' + +pub trait Test { + fn method(); + const CONST: u8; + type Type; +} + +//@ has - '//*[@id="reexport.method"]//a[@href="trait.Test.html#tymethod.method"]' 'method' +//@ has - '//*[@id="reexport.CONST"]//a[@href="trait.Test.html#associatedconstant.CONST"]' 'CONST' +//@ has - '//*[@id="reexport.Type"]//a[@href="trait.Test.html#associatedtype.Type"]' 'Type' +pub use self::Test::{method, CONST, Type}; diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs index 50a2aacc91ad3..d79dfa28b0daf 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.rs +++ b/tests/ui/coercion/coerce-loop-issue-122561.rs @@ -1,4 +1,6 @@ -// Regression test for #122561 +// Regression test for . +// +// Tests suggestions for type mismatch of loop expressions. fn for_infinite() -> bool { for i in 0.. { diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr index 6415fd554cba9..3fd6671565f18 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.stderr +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -1,5 +1,5 @@ warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:47:5 + --> $DIR/coerce-loop-issue-122561.rs:49:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` @@ -7,13 +7,13 @@ LL | while true { = note: `#[warn(while_true)]` on by default warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:71:5 + --> $DIR/coerce-loop-issue-122561.rs:73:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:41:24 + --> $DIR/coerce-loop-issue-122561.rs:43:24 | LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` @@ -25,7 +25,7 @@ LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool { | +++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:4:5 + --> $DIR/coerce-loop-issue-122561.rs:6:5 | LL | fn for_infinite() -> bool { | ---- expected `bool` because of return type @@ -43,7 +43,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:11:5 + --> $DIR/coerce-loop-issue-122561.rs:13:5 | LL | fn for_finite() -> String { | ------ expected `String` because of return type @@ -61,7 +61,7 @@ LL + /* `String` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:18:5 + --> $DIR/coerce-loop-issue-122561.rs:20:5 | LL | fn for_zero_times() -> bool { | ---- expected `bool` because of return type @@ -79,7 +79,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:25:5 + --> $DIR/coerce-loop-issue-122561.rs:27:5 | LL | fn for_never_type() -> ! { | - expected `!` because of return type @@ -98,7 +98,7 @@ LL + /* `loop {}` or `panic!("...")` */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:33:32 + --> $DIR/coerce-loop-issue-122561.rs:35:32 | LL | fn for_single_line() -> bool { for i in 0.. { return false; } } | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` @@ -112,7 +112,7 @@ LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` val | ++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:47:5 + --> $DIR/coerce-loop-issue-122561.rs:49:5 | LL | fn while_inifinite() -> bool { | ---- expected `bool` because of return type @@ -131,7 +131,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:56:5 + --> $DIR/coerce-loop-issue-122561.rs:58:5 | LL | fn while_finite() -> bool { | ---- expected `bool` because of return type @@ -151,7 +151,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:64:5 + --> $DIR/coerce-loop-issue-122561.rs:66:5 | LL | fn while_zero_times() -> bool { | ---- expected `bool` because of return type @@ -169,7 +169,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:71:5 + --> $DIR/coerce-loop-issue-122561.rs:73:5 | LL | fn while_never_type() -> ! { | - expected `!` because of return type @@ -188,7 +188,7 @@ LL + /* `loop {}` or `panic!("...")` */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:85:5 + --> $DIR/coerce-loop-issue-122561.rs:87:5 | LL | / for i in 0.. { LL | | @@ -203,7 +203,7 @@ LL + /* `i32` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:92:9 + --> $DIR/coerce-loop-issue-122561.rs:94:9 | LL | / for i in 0..5 { LL | | @@ -218,7 +218,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:98:9 + --> $DIR/coerce-loop-issue-122561.rs:100:9 | LL | / while false { LL | | @@ -233,7 +233,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:104:23 + --> $DIR/coerce-loop-issue-122561.rs:106:23 | LL | let _ = |a: &[(); for x in 0..2 {}]| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs index 58ae763e017f0..199f4d1ea0e10 100644 --- a/tests/ui/consts/const-eval/raw-bytes.rs +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -34,7 +34,7 @@ const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; #[derive(Copy, Clone)] enum Never {} -// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do* +// An enum with 4 variants of which only some are uninhabited -- so the uninhabited variants *do* // have a discriminant. enum UninhDiscriminant { A, diff --git a/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs b/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs index e0d1d515deb02..24ff0a1f0719c 100644 --- a/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs +++ b/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs @@ -1,10 +1,18 @@ +// Regression test for . +// +// This checks that const eval doesn't cause an ICE when reading an uninhabited +// variant. (N.B. this is UB, but not currently detected by rustc) +// //@ check-pass #![feature(never_type)] + #[derive(Copy, Clone)] pub enum E { A(!), } + pub union U { u: (), e: E, } + pub const C: () = { - let E::A(ref a) = unsafe { &(&U { u: () }).e}; + let E::A(ref a) = unsafe { &(&U { u: () }).e }; }; fn main() {} diff --git a/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.rs b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.rs new file mode 100644 index 0000000000000..028716a14c7b4 --- /dev/null +++ b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.rs @@ -0,0 +1,38 @@ +//@ add-minicore +//@ ignore-backends: gcc +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![expect(incomplete_features)] +#![feature(no_core, explicit_tail_calls, abi_cmse_nonsecure_call)] +#![no_core] + +extern crate minicore; +use minicore::*; + +unsafe extern "C" { + safe fn magic() -> extern "cmse-nonsecure-call" fn(u32, u32) -> u32; +} + +// The `cmse-nonsecure-call` ABI can only occur on function pointers: +// +// - a `cmse-nonsecure-call` definition throws an error +// - a `cmse-nonsecure-call` become in a definition with any other ABI is an ABI mismatch +#[no_mangle] +extern "cmse-nonsecure-call" fn become_nonsecure_call_1(x: u32, y: u32) -> u32 { + //~^ ERROR the `"cmse-nonsecure-call"` ABI is only allowed on function pointers + unsafe { + let f = magic(); + become f(1, 2) + //~^ ERROR ABI does not support guaranteed tail calls + } +} + +#[no_mangle] +extern "C" fn become_nonsecure_call_2(x: u32, y: u32) -> u32 { + unsafe { + let f = magic(); + become f(1, 2) + //~^ ERROR mismatched function ABIs + //~| ERROR ABI does not support guaranteed tail calls + } +} diff --git a/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.stderr b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.stderr new file mode 100644 index 0000000000000..08f11a4bd4b71 --- /dev/null +++ b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.stderr @@ -0,0 +1,34 @@ +error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers + --> $DIR/cmse-nonsecure-call.rs:21:1 + | +LL | extern "cmse-nonsecure-call" fn become_nonsecure_call_1(x: u32, y: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: ABI does not support guaranteed tail calls + --> $DIR/cmse-nonsecure-call.rs:25:9 + | +LL | become f(1, 2) + | ^^^^^^^^^^^^^^ + | + = note: `become` is not supported for `extern "cmse-nonsecure-call"` functions + +error: mismatched function ABIs + --> $DIR/cmse-nonsecure-call.rs:34:9 + | +LL | become f(1, 2) + | ^^^^^^^^^^^^^^ + | + = note: `become` requires caller and callee to have the same ABI + = note: caller ABI is `"C"`, while callee ABI is `"cmse-nonsecure-call"` + +error: ABI does not support guaranteed tail calls + --> $DIR/cmse-nonsecure-call.rs:34:9 + | +LL | become f(1, 2) + | ^^^^^^^^^^^^^^ + | + = note: `become` is not supported for `extern "cmse-nonsecure-call"` functions + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0781`. diff --git a/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.rs b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.rs new file mode 100644 index 0000000000000..006fa538c4891 --- /dev/null +++ b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.rs @@ -0,0 +1,22 @@ +//@ add-minicore +//@ ignore-backends: gcc +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![expect(incomplete_features)] +#![feature(no_core, explicit_tail_calls, cmse_nonsecure_entry)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[inline(never)] +extern "cmse-nonsecure-entry" fn entry(c: bool, x: u32, y: u32) -> u32 { + if c { x } else { y } +} + +// A `cmse-nonsecure-entry` clears registers before returning, so a tail call cannot be guaranteed. +#[unsafe(no_mangle)] +extern "cmse-nonsecure-entry" fn become_nonsecure_entry(c: bool, x: u32, y: u32) -> u32 { + become entry(c, x, y) + //~^ ERROR ABI does not support guaranteed tail calls +} diff --git a/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.stderr b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.stderr new file mode 100644 index 0000000000000..3acbe8c5bfaa5 --- /dev/null +++ b/tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.stderr @@ -0,0 +1,10 @@ +error: ABI does not support guaranteed tail calls + --> $DIR/cmse-nonsecure-entry.rs:20:5 + | +LL | become entry(c, x, y) + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `become` is not supported for `extern "cmse-nonsecure-entry"` functions + +error: aborting due to 1 previous error + diff --git a/tests/ui/never_type/dispatch_from_dyn_zst.rs b/tests/ui/self/dispatch_from_dyn_zst.rs similarity index 100% rename from tests/ui/never_type/dispatch_from_dyn_zst.rs rename to tests/ui/self/dispatch_from_dyn_zst.rs diff --git a/triagebot.toml b/triagebot.toml index adc73c42c428c..0bf310e8fd7ef 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -922,9 +922,6 @@ cc = ["@davidtwco", "@wesleywiser"] [mentions."compiler/rustc_codegen_cranelift"] cc = ["@bjorn3"] -[mentions."compiler/rustc_codegen_ssa"] -cc = ["@WaffleLapkin"] - [mentions."compiler/rustc_codegen_gcc"] cc = ["@antoyo", "@GuillaumeGomez"]