authorbors <bors@rust-lang.org> 2025-11-14 05:29:52 UTC
committerbors <bors@rust-lang.org> 2025-11-14 05:29:52 UTC
logc880acdd3171dfafdb55be8cd9822a857e99348d
treea4dd60b38d0715db07918e08982d8326e4cfb853
parent6d41834e251a65a994bf0acf415ddafd4adbf71f
parentf589579a1df7e27fa4b6dead0c92f6a45f29c227

Auto merge of #148931 - Zalathar:rollup-yfyhpcw, r=Zalathar

Rollup of 15 pull requests Successful merges: - rust-lang/rust#148543 (Correctly link to associated trait items in reexports) - rust-lang/rust#148808 (Some resolve cleanups) - rust-lang/rust#148812 (coverage: Associate hole spans with expansion tree nodes ) - rust-lang/rust#148826 (CStr docs: Fix CStr vs &CStr confusion) - rust-lang/rust#148850 (Implement `Read::read_array`) - rust-lang/rust#148867 (Refactor `Box::take`) - rust-lang/rust#148870 (Remove unused LLVMModuleRef argument) - rust-lang/rust#148878 (error when ABI does not support guaranteed tail calls) - rust-lang/rust#148901 (Disable rustdoc-test-builder test partially for SGX target.) - rust-lang/rust#148902 (add missing s390x target feature to std detect test) - rust-lang/rust#148904 (waffle: stop watching codegen ssa) - rust-lang/rust#148906 (Expose fmt::Arguments::from_str as unstable.) - rust-lang/rust#148907 (add assembly test for infinite recursion with `become`) - rust-lang/rust#148928 (Move & adjust some `!`-adjacent tests) - rust-lang/rust#148929 (ignore `build-rust-analyzer` even if it's a symlink) r? `@ghost` `@rustbot` modify labels: rollup

40 files changed, 621 insertions(+), 342 deletions(-)

.gitignore+1-1
......@@ -48,7 +48,7 @@ no_llvm_build
4848/llvm/
4949/mingw-build/
5050/build
51/build-rust-analyzer/
51/build-rust-analyzer
5252/dist/
5353/unicode-downloads
5454/target
compiler/rustc_abi/src/extern_abi.rs+45
......@@ -276,6 +276,51 @@ impl ExternAbi {
276276 _ => CVariadicStatus::NotSupported,
277277 }
278278 }
279
280 /// Returns whether the ABI supports guaranteed tail calls.
281 #[cfg(feature = "nightly")]
282 pub fn supports_guaranteed_tail_call(self) -> bool {
283 match self {
284 Self::CmseNonSecureCall | Self::CmseNonSecureEntry => {
285 // See https://godbolt.org/z/9jhdeqErv. The CMSE calling conventions clear registers
286 // before returning, and hence cannot guarantee a tail call.
287 false
288 }
289 Self::AvrInterrupt
290 | Self::AvrNonBlockingInterrupt
291 | Self::Msp430Interrupt
292 | Self::RiscvInterruptM
293 | Self::RiscvInterruptS
294 | Self::X86Interrupt => {
295 // See https://godbolt.org/z/Edfjnxxcq. Interrupts cannot be called directly.
296 false
297 }
298 Self::GpuKernel | Self::PtxKernel => {
299 // See https://godbolt.org/z/jq5TE5jK1.
300 false
301 }
302 Self::Custom => {
303 // This ABI does not support calls at all (except via assembly).
304 false
305 }
306 Self::C { .. }
307 | Self::System { .. }
308 | Self::Rust
309 | Self::RustCall
310 | Self::RustCold
311 | Self::RustInvalid
312 | Self::Unadjusted
313 | Self::EfiApi
314 | Self::Aapcs { .. }
315 | Self::Cdecl { .. }
316 | Self::Stdcall { .. }
317 | Self::Fastcall { .. }
318 | Self::Thiscall { .. }
319 | Self::Vectorcall { .. }
320 | Self::SysV64 { .. }
321 | Self::Win64 { .. } => true,
322 }
323 }
279324}
280325
281326pub fn all_names() -> Vec<&'static str> {
compiler/rustc_codegen_llvm/src/back/write.rs+1-1
......@@ -683,7 +683,7 @@ pub(crate) unsafe fn llvm_optimize(
683683 // Here we map the old arguments to the new arguments, with an offset of 1 to make sure
684684 // that we don't use the newly added `%dyn_ptr`.
685685 unsafe {
686 llvm::LLVMRustOffloadMapper(cx.llmod(), old_fn, new_fn);
686 llvm::LLVMRustOffloadMapper(old_fn, new_fn);
687687 }
688688
689689 llvm::set_linkage(new_fn, llvm::get_linkage(old_fn));
compiler/rustc_codegen_llvm/src/llvm/ffi.rs+1-1
......@@ -2025,7 +2025,7 @@ unsafe extern "C" {
20252025 ) -> &Attribute;
20262026
20272027 // Operations on functions
2028 pub(crate) fn LLVMRustOffloadMapper<'a>(M: &'a Module, Fn: &'a Value, Fn: &'a Value);
2028 pub(crate) fn LLVMRustOffloadMapper<'a>(Fn: &'a Value, Fn: &'a Value);
20292029 pub(crate) fn LLVMRustGetOrInsertFunction<'a>(
20302030 M: &'a Module,
20312031 Name: *const c_char,
compiler/rustc_expand/src/base.rs+3
......@@ -1099,6 +1099,9 @@ pub struct Indeterminate;
10991099pub struct DeriveResolution {
11001100 pub path: ast::Path,
11011101 pub item: Annotatable,
1102 // FIXME: currently this field is only used in `is_none`/`is_some` conditions. However, the
1103 // `Arc<SyntaxExtension>` will be used if the FIXME in `MacroExpander::fully_expand_fragment`
1104 // is completed.
11021105 pub exts: Option<Arc<SyntaxExtension>>,
11031106 pub is_const: bool,
11041107}
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp+1-3
......@@ -144,9 +144,7 @@ extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) {
144144 llvm::PrintStatistics(OS);
145145}
146146
147extern "C" void LLVMRustOffloadMapper(LLVMModuleRef M, LLVMValueRef OldFn,
148 LLVMValueRef NewFn) {
149 llvm::Module *module = llvm::unwrap(M);
147extern "C" void LLVMRustOffloadMapper(LLVMValueRef OldFn, LLVMValueRef NewFn) {
150148 llvm::Function *oldFn = llvm::unwrap<llvm::Function>(OldFn);
151149 llvm::Function *newFn = llvm::unwrap<llvm::Function>(NewFn);
152150
compiler/rustc_mir_build/src/check_tail_calls.rs+14
......@@ -135,6 +135,10 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
135135 self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi);
136136 }
137137
138 if !callee_sig.abi.supports_guaranteed_tail_call() {
139 self.report_unsupported_abi(expr.span, callee_sig.abi);
140 }
141
138142 // FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
139143 // e.g.
140144 // ```
......@@ -358,6 +362,16 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
358362 self.found_errors = Err(err);
359363 }
360364
365 fn report_unsupported_abi(&mut self, sp: Span, callee_abi: ExternAbi) {
366 let err = self
367 .tcx
368 .dcx()
369 .struct_span_err(sp, "ABI does not support guaranteed tail calls")
370 .with_note(format!("`become` is not supported for `extern {callee_abi}` functions"))
371 .emit();
372 self.found_errors = Err(err);
373 }
374
361375 fn report_signature_mismatch(
362376 &mut self,
363377 sp: Span,
compiler/rustc_mir_transform/src/coverage/expansion.rs+30-3
......@@ -1,7 +1,12 @@
11use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
2use rustc_middle::mir;
23use rustc_middle::mir::coverage::BasicCoverageBlock;
34use rustc_span::{ExpnId, ExpnKind, Span};
45
6use crate::coverage::from_mir;
7use crate::coverage::graph::CoverageGraph;
8use crate::coverage::hir_info::ExtractedHirInfo;
9
510#[derive(Clone, Copy, Debug)]
611pub(crate) struct SpanWithBcb {
712 pub(crate) span: Span,
......@@ -70,6 +75,10 @@ pub(crate) struct ExpnNode {
7075 pub(crate) spans: Vec<SpanWithBcb>,
7176 /// Expansions whose call-site is in this expansion.
7277 pub(crate) child_expn_ids: FxIndexSet<ExpnId>,
78
79 /// Hole spans belonging to this expansion, to be carved out from the
80 /// code spans during span refinement.
81 pub(crate) hole_spans: Vec<Span>,
7382}
7483
7584impl ExpnNode {
......@@ -88,17 +97,27 @@ impl ExpnNode {
8897
8998 spans: vec![],
9099 child_expn_ids: FxIndexSet::default(),
100
101 hole_spans: vec![],
91102 }
92103 }
93104}
94105
95/// Given a collection of span/BCB pairs from potentially-different syntax contexts,
106/// Extracts raw span/BCB pairs from potentially-different syntax contexts, and
96107/// arranges them into an "expansion tree" based on their expansion call-sites.
97pub(crate) fn build_expn_tree(spans: impl IntoIterator<Item = SpanWithBcb>) -> ExpnTree {
108pub(crate) fn build_expn_tree(
109 mir_body: &mir::Body<'_>,
110 hir_info: &ExtractedHirInfo,
111 graph: &CoverageGraph,
112) -> ExpnTree {
113 let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph);
114
98115 let mut nodes = FxIndexMap::default();
99116 let new_node = |&expn_id: &ExpnId| ExpnNode::new(expn_id);
100117
101 for span_with_bcb in spans {
118 for from_mir::RawSpanFromMir { raw_span, bcb } in raw_spans {
119 let span_with_bcb = SpanWithBcb { span: raw_span, bcb };
120
102121 // Create a node for this span's enclosing expansion, and add the span to it.
103122 let expn_id = span_with_bcb.span.ctxt().outer_expn();
104123 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<Item = SpanWithBcb>) -> E
123142 }
124143 }
125144
145 // Associate each hole span (extracted from HIR) with its corresponding
146 // expansion tree node.
147 for &hole_span in &hir_info.hole_spans {
148 let expn_id = hole_span.ctxt().outer_expn();
149 let Some(node) = nodes.get_mut(&expn_id) else { continue };
150 node.hole_spans.push(hole_span);
151 }
152
126153 ExpnTree { nodes }
127154}
compiler/rustc_mir_transform/src/coverage/from_mir.rs created+144
......@@ -0,0 +1,144 @@
1use std::iter;
2
3use rustc_middle::bug;
4use rustc_middle::mir::coverage::CoverageKind;
5use rustc_middle::mir::{
6 self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind,
7};
8use rustc_span::Span;
9
10use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
11
12#[derive(Debug)]
13pub(crate) struct RawSpanFromMir {
14 /// A span that has been extracted from a MIR statement/terminator, but
15 /// hasn't been "unexpanded", so it might not lie within the function body
16 /// span and might be part of an expansion with a different context.
17 pub(crate) raw_span: Span,
18 pub(crate) bcb: BasicCoverageBlock,
19}
20
21/// Generates an initial set of coverage spans from the statements and
22/// terminators in the function's MIR body, each associated with its
23/// corresponding node in the coverage graph.
24///
25/// This is necessarily an inexact process, because MIR isn't designed to
26/// capture source spans at the level of detail we would want for coverage,
27/// but it's good enough to be better than nothing.
28pub(crate) fn extract_raw_spans_from_mir<'tcx>(
29 mir_body: &mir::Body<'tcx>,
30 graph: &CoverageGraph,
31) -> Vec<RawSpanFromMir> {
32 let mut raw_spans = vec![];
33
34 // We only care about blocks that are part of the coverage graph.
35 for (bcb, bcb_data) in graph.iter_enumerated() {
36 let make_raw_span = |raw_span: Span| RawSpanFromMir { raw_span, bcb };
37
38 // A coverage graph node can consist of multiple basic blocks.
39 for &bb in &bcb_data.basic_blocks {
40 let bb_data = &mir_body[bb];
41
42 let statements = bb_data.statements.iter();
43 raw_spans.extend(statements.filter_map(filtered_statement_span).map(make_raw_span));
44
45 // There's only one terminator, but wrap it in an iterator to
46 // mirror the handling of statements.
47 let terminator = iter::once(bb_data.terminator());
48 raw_spans.extend(terminator.filter_map(filtered_terminator_span).map(make_raw_span));
49 }
50 }
51
52 raw_spans
53}
54
55/// If the MIR `Statement` has a span contributive to computing coverage spans,
56/// return it; otherwise return `None`.
57fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
58 match statement.kind {
59 // These statements have spans that are often outside the scope of the executed source code
60 // for their parent `BasicBlock`.
61 StatementKind::StorageLive(_)
62 | StatementKind::StorageDead(_)
63 | StatementKind::ConstEvalCounter
64 | StatementKind::BackwardIncompatibleDropHint { .. }
65 | StatementKind::Nop => None,
66
67 // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead`
68 // statements be more consistent?
69 //
70 // FakeReadCause::ForGuardBinding, in this example:
71 // match somenum {
72 // x if x < 1 => { ... }
73 // }...
74 // The BasicBlock within the match arm code included one of these statements, but the span
75 // for it covered the `1` in this source. The actual statements have nothing to do with that
76 // source span:
77 // FakeRead(ForGuardBinding, _4);
78 // where `_4` is:
79 // _4 = &_1; (at the span for the first `x`)
80 // and `_1` is the `Place` for `somenum`.
81 //
82 // If and when the Issue is resolved, remove this special case match pattern:
83 StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None,
84
85 // Retain spans from most other statements.
86 StatementKind::FakeRead(_)
87 | StatementKind::Intrinsic(..)
88 | StatementKind::Coverage(
89 // The purpose of `SpanMarker` is to be matched and accepted here.
90 CoverageKind::SpanMarker,
91 )
92 | StatementKind::Assign(_)
93 | StatementKind::SetDiscriminant { .. }
94 | StatementKind::Retag(_, _)
95 | StatementKind::PlaceMention(..)
96 | StatementKind::AscribeUserType(_, _) => Some(statement.source_info.span),
97
98 // Block markers are used for branch coverage, so ignore them here.
99 StatementKind::Coverage(CoverageKind::BlockMarker { .. }) => None,
100
101 // These coverage statements should not exist prior to coverage instrumentation.
102 StatementKind::Coverage(CoverageKind::VirtualCounter { .. }) => bug!(
103 "Unexpected coverage statement found during coverage instrumentation: {statement:?}"
104 ),
105 }
106}
107
108/// If the MIR `Terminator` has a span contributive to computing coverage spans,
109/// return it; otherwise return `None`.
110fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
111 match terminator.kind {
112 // These terminators have spans that don't positively contribute to computing a reasonable
113 // span of actually executed source code. (For example, SwitchInt terminators extracted from
114 // an `if condition { block }` has a span that includes the executed block, if true,
115 // but for coverage, the code region executed, up to *and* through the SwitchInt,
116 // actually stops before the if's block.)
117 TerminatorKind::Unreachable
118 | TerminatorKind::Assert { .. }
119 | TerminatorKind::Drop { .. }
120 | TerminatorKind::SwitchInt { .. }
121 | TerminatorKind::FalseEdge { .. }
122 | TerminatorKind::Goto { .. } => None,
123
124 // Call `func` operand can have a more specific span when part of a chain of calls
125 TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => {
126 let mut span = terminator.source_info.span;
127 if let mir::Operand::Constant(constant) = func
128 && span.contains(constant.span)
129 {
130 span = constant.span;
131 }
132 Some(span)
133 }
134
135 // Retain spans from all other terminators
136 TerminatorKind::UnwindResume
137 | TerminatorKind::UnwindTerminate(_)
138 | TerminatorKind::Return
139 | TerminatorKind::Yield { .. }
140 | TerminatorKind::CoroutineDrop
141 | TerminatorKind::FalseUnwind { .. }
142 | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span),
143 }
144}
compiler/rustc_mir_transform/src/coverage/mappings.rs+4-1
......@@ -5,6 +5,7 @@ use rustc_middle::mir::coverage::{
55use rustc_middle::mir::{self, BasicBlock, StatementKind};
66use rustc_middle::ty::TyCtxt;
77
8use crate::coverage::expansion;
89use crate::coverage::graph::CoverageGraph;
910use crate::coverage::hir_info::ExtractedHirInfo;
1011use crate::coverage::spans::extract_refined_covspans;
......@@ -23,10 +24,12 @@ pub(crate) fn extract_mappings_from_mir<'tcx>(
2324 hir_info: &ExtractedHirInfo,
2425 graph: &CoverageGraph,
2526) -> ExtractedMappings {
27 let expn_tree = expansion::build_expn_tree(mir_body, hir_info, graph);
28
2629 let mut mappings = vec![];
2730
2831 // Extract ordinary code mappings from MIR statement/terminator spans.
29 extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut mappings);
32 extract_refined_covspans(tcx, hir_info, graph, &expn_tree, &mut mappings);
3033
3134 extract_branch_mappings(mir_body, hir_info, graph, &mut mappings);
3235
compiler/rustc_mir_transform/src/coverage/mod.rs+1
......@@ -9,6 +9,7 @@ use crate::coverage::mappings::ExtractedMappings;
99
1010mod counters;
1111mod expansion;
12mod from_mir;
1213mod graph;
1314mod hir_info;
1415mod mappings;
compiler/rustc_mir_transform/src/coverage/spans.rs+42-42
......@@ -1,22 +1,18 @@
1use rustc_middle::mir;
21use rustc_middle::mir::coverage::{Mapping, MappingKind, START_BCB};
32use rustc_middle::ty::TyCtxt;
43use rustc_span::source_map::SourceMap;
54use rustc_span::{BytePos, DesugaringKind, ExpnId, ExpnKind, MacroKind, Span};
65use tracing::instrument;
76
8use crate::coverage::expansion::{self, ExpnTree, SpanWithBcb};
7use crate::coverage::expansion::{ExpnTree, SpanWithBcb};
98use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
109use crate::coverage::hir_info::ExtractedHirInfo;
11use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir};
12
13mod from_mir;
1410
1511pub(super) fn extract_refined_covspans<'tcx>(
1612 tcx: TyCtxt<'tcx>,
17 mir_body: &mir::Body<'tcx>,
1813 hir_info: &ExtractedHirInfo,
1914 graph: &CoverageGraph,
15 expn_tree: &ExpnTree,
2016 mappings: &mut Vec<Mapping>,
2117) {
2218 if hir_info.is_async_fn {
......@@ -32,22 +28,32 @@ pub(super) fn extract_refined_covspans<'tcx>(
3228
3329 let &ExtractedHirInfo { body_span, .. } = hir_info;
3430
35 let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph);
36 // Use the raw spans to build a tree of expansions for this function.
37 let expn_tree = expansion::build_expn_tree(
38 raw_spans
39 .into_iter()
40 .map(|RawSpanFromMir { raw_span, bcb }| SpanWithBcb { span: raw_span, bcb }),
41 );
31 // If there somehow isn't an expansion tree node corresponding to the
32 // body span, return now and don't create any mappings.
33 let Some(node) = expn_tree.get(body_span.ctxt().outer_expn()) else { return };
4234
4335 let mut covspans = vec![];
44 let mut push_covspan = |covspan: Covspan| {
36
37 for &SpanWithBcb { span, bcb } in &node.spans {
38 covspans.push(Covspan { span, bcb });
39 }
40
41 // For each expansion with its call-site in the body span, try to
42 // distill a corresponding covspan.
43 for &child_expn_id in &node.child_expn_ids {
44 if let Some(covspan) = single_covspan_for_child_expn(tcx, graph, &expn_tree, child_expn_id)
45 {
46 covspans.push(covspan);
47 }
48 }
49
50 covspans.retain(|covspan: &Covspan| {
4551 let covspan_span = covspan.span;
4652 // Discard any spans not contained within the function body span.
4753 // Also discard any spans that fill the entire body, because they tend
4854 // to represent compiler-inserted code, e.g. implicitly returning `()`.
4955 if !body_span.contains(covspan_span) || body_span.source_equal(covspan_span) {
50 return;
56 return false;
5157 }
5258
5359 // Each pushed covspan should have the same context as the body span.
......@@ -57,27 +63,11 @@ pub(super) fn extract_refined_covspans<'tcx>(
5763 false,
5864 "span context mismatch: body_span={body_span:?}, covspan.span={covspan_span:?}"
5965 );
60 return;
66 return false;
6167 }
6268
63 covspans.push(covspan);
64 };
65
66 if let Some(node) = expn_tree.get(body_span.ctxt().outer_expn()) {
67 for &SpanWithBcb { span, bcb } in &node.spans {
68 push_covspan(Covspan { span, bcb });
69 }
70
71 // For each expansion with its call-site in the body span, try to
72 // distill a corresponding covspan.
73 for &child_expn_id in &node.child_expn_ids {
74 if let Some(covspan) =
75 single_covspan_for_child_expn(tcx, graph, &expn_tree, child_expn_id)
76 {
77 push_covspan(covspan);
78 }
79 }
80 }
69 true
70 });
8171
8272 // Only proceed if we found at least one usable span.
8373 if covspans.is_empty() {
......@@ -107,14 +97,8 @@ pub(super) fn extract_refined_covspans<'tcx>(
10797 covspans.dedup_by(|b, a| a.span.source_equal(b.span));
10898
10999 // Sort the holes, and merge overlapping/adjacent holes.
110 let mut holes = hir_info
111 .hole_spans
112 .iter()
113 .copied()
114 // Discard any holes that aren't directly visible within the body span.
115 .filter(|&hole_span| body_span.contains(hole_span) && body_span.eq_ctxt(hole_span))
116 .map(|span| Hole { span })
117 .collect::<Vec<_>>();
100 let mut holes = node.hole_spans.iter().copied().map(|span| Hole { span }).collect::<Vec<_>>();
101
118102 holes.sort_by(|a, b| compare_spans(a.span, b.span));
119103 holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
120104
......@@ -295,3 +279,19 @@ fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
295279 })
296280 .ok()?
297281}
282
283#[derive(Debug)]
284struct Hole {
285 span: Span,
286}
287
288impl Hole {
289 fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
290 if !self.span.overlaps_or_adjacent(other.span) {
291 return false;
292 }
293
294 self.span = self.span.to(other.span);
295 true
296 }
297}
compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs deleted-160
......@@ -1,160 +0,0 @@
1use std::iter;
2
3use rustc_middle::bug;
4use rustc_middle::mir::coverage::CoverageKind;
5use rustc_middle::mir::{
6 self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind,
7};
8use rustc_span::Span;
9
10use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
11
12#[derive(Debug)]
13pub(crate) struct RawSpanFromMir {
14 /// A span that has been extracted from a MIR statement/terminator, but
15 /// hasn't been "unexpanded", so it might not lie within the function body
16 /// span and might be part of an expansion with a different context.
17 pub(crate) raw_span: Span,
18 pub(crate) bcb: BasicCoverageBlock,
19}
20
21/// Generates an initial set of coverage spans from the statements and
22/// terminators in the function's MIR body, each associated with its
23/// corresponding node in the coverage graph.
24///
25/// This is necessarily an inexact process, because MIR isn't designed to
26/// capture source spans at the level of detail we would want for coverage,
27/// but it's good enough to be better than nothing.
28pub(crate) fn extract_raw_spans_from_mir<'tcx>(
29 mir_body: &mir::Body<'tcx>,
30 graph: &CoverageGraph,
31) -> Vec<RawSpanFromMir> {
32 let mut raw_spans = vec![];
33
34 // We only care about blocks that are part of the coverage graph.
35 for (bcb, bcb_data) in graph.iter_enumerated() {
36 let make_raw_span = |raw_span: Span| RawSpanFromMir { raw_span, bcb };
37
38 // A coverage graph node can consist of multiple basic blocks.
39 for &bb in &bcb_data.basic_blocks {
40 let bb_data = &mir_body[bb];
41
42 let statements = bb_data.statements.iter();
43 raw_spans.extend(statements.filter_map(filtered_statement_span).map(make_raw_span));
44
45 // There's only one terminator, but wrap it in an iterator to
46 // mirror the handling of statements.
47 let terminator = iter::once(bb_data.terminator());
48 raw_spans.extend(terminator.filter_map(filtered_terminator_span).map(make_raw_span));
49 }
50 }
51
52 raw_spans
53}
54
55/// If the MIR `Statement` has a span contributive to computing coverage spans,
56/// return it; otherwise return `None`.
57fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
58 match statement.kind {
59 // These statements have spans that are often outside the scope of the executed source code
60 // for their parent `BasicBlock`.
61 StatementKind::StorageLive(_)
62 | StatementKind::StorageDead(_)
63 | StatementKind::ConstEvalCounter
64 | StatementKind::BackwardIncompatibleDropHint { .. }
65 | StatementKind::Nop => None,
66
67 // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead`
68 // statements be more consistent?
69 //
70 // FakeReadCause::ForGuardBinding, in this example:
71 // match somenum {
72 // x if x < 1 => { ... }
73 // }...
74 // The BasicBlock within the match arm code included one of these statements, but the span
75 // for it covered the `1` in this source. The actual statements have nothing to do with that
76 // source span:
77 // FakeRead(ForGuardBinding, _4);
78 // where `_4` is:
79 // _4 = &_1; (at the span for the first `x`)
80 // and `_1` is the `Place` for `somenum`.
81 //
82 // If and when the Issue is resolved, remove this special case match pattern:
83 StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None,
84
85 // Retain spans from most other statements.
86 StatementKind::FakeRead(_)
87 | StatementKind::Intrinsic(..)
88 | StatementKind::Coverage(
89 // The purpose of `SpanMarker` is to be matched and accepted here.
90 CoverageKind::SpanMarker,
91 )
92 | StatementKind::Assign(_)
93 | StatementKind::SetDiscriminant { .. }
94 | StatementKind::Retag(_, _)
95 | StatementKind::PlaceMention(..)
96 | StatementKind::AscribeUserType(_, _) => Some(statement.source_info.span),
97
98 // Block markers are used for branch coverage, so ignore them here.
99 StatementKind::Coverage(CoverageKind::BlockMarker { .. }) => None,
100
101 // These coverage statements should not exist prior to coverage instrumentation.
102 StatementKind::Coverage(CoverageKind::VirtualCounter { .. }) => bug!(
103 "Unexpected coverage statement found during coverage instrumentation: {statement:?}"
104 ),
105 }
106}
107
108/// If the MIR `Terminator` has a span contributive to computing coverage spans,
109/// return it; otherwise return `None`.
110fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
111 match terminator.kind {
112 // These terminators have spans that don't positively contribute to computing a reasonable
113 // span of actually executed source code. (For example, SwitchInt terminators extracted from
114 // an `if condition { block }` has a span that includes the executed block, if true,
115 // but for coverage, the code region executed, up to *and* through the SwitchInt,
116 // actually stops before the if's block.)
117 TerminatorKind::Unreachable
118 | TerminatorKind::Assert { .. }
119 | TerminatorKind::Drop { .. }
120 | TerminatorKind::SwitchInt { .. }
121 | TerminatorKind::FalseEdge { .. }
122 | TerminatorKind::Goto { .. } => None,
123
124 // Call `func` operand can have a more specific span when part of a chain of calls
125 TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => {
126 let mut span = terminator.source_info.span;
127 if let mir::Operand::Constant(constant) = func
128 && span.contains(constant.span)
129 {
130 span = constant.span;
131 }
132 Some(span)
133 }
134
135 // Retain spans from all other terminators
136 TerminatorKind::UnwindResume
137 | TerminatorKind::UnwindTerminate(_)
138 | TerminatorKind::Return
139 | TerminatorKind::Yield { .. }
140 | TerminatorKind::CoroutineDrop
141 | TerminatorKind::FalseUnwind { .. }
142 | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span),
143 }
144}
145
146#[derive(Debug)]
147pub(crate) struct Hole {
148 pub(crate) span: Span,
149}
150
151impl Hole {
152 pub(crate) fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
153 if !self.span.overlaps_or_adjacent(other.span) {
154 return false;
155 }
156
157 self.span = self.span.to(other.span);
158 true
159 }
160}
compiler/rustc_resolve/src/ident.rs+1-4
......@@ -458,14 +458,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
458458 let mut result = Err(Determinacy::Determined);
459459 for derive in parent_scope.derives {
460460 let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
461 match this.reborrow().resolve_macro_path(
461 match this.reborrow().resolve_derive_macro_path(
462462 derive,
463 MacroKind::Derive,
464463 parent_scope,
465 true,
466464 force,
467465 ignore_import,
468 None,
469466 ) {
470467 Ok((Some(ext), _)) => {
471468 if ext.helper_attrs.contains(&ident.name) {
compiler/rustc_resolve/src/macros.rs+19-32
......@@ -396,14 +396,11 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
396396 for (i, resolution) in entry.resolutions.iter_mut().enumerate() {
397397 if resolution.exts.is_none() {
398398 resolution.exts = Some(
399 match self.cm().resolve_macro_path(
399 match self.cm().resolve_derive_macro_path(
400400 &resolution.path,
401 MacroKind::Derive,
402401 &parent_scope,
403 true,
404402 force,
405403 None,
406 None,
407404 ) {
408405 Ok((Some(ext), _)) => {
409406 if !ext.helper_attrs.is_empty() {
......@@ -571,7 +568,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
571568 path,
572569 kind,
573570 parent_scope,
574 true,
575571 force,
576572 deleg_impl,
577573 invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
......@@ -713,26 +709,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
713709 Ok((ext, res))
714710 }
715711
716 pub(crate) fn resolve_macro_path<'r>(
712 pub(crate) fn resolve_derive_macro_path<'r>(
717713 self: CmResolver<'r, 'ra, 'tcx>,
718714 path: &ast::Path,
719 kind: MacroKind,
720715 parent_scope: &ParentScope<'ra>,
721 trace: bool,
722716 force: bool,
723717 ignore_import: Option<Import<'ra>>,
724 suggestion_span: Option<Span>,
725718 ) -> Result<(Option<Arc<SyntaxExtension>>, Res), Determinacy> {
726719 self.resolve_macro_or_delegation_path(
727720 path,
728 kind,
721 MacroKind::Derive,
729722 parent_scope,
730 trace,
731723 force,
732724 None,
733725 None,
734726 ignore_import,
735 suggestion_span,
727 None,
736728 )
737729 }
738730
......@@ -741,7 +733,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
741733 ast_path: &ast::Path,
742734 kind: MacroKind,
743735 parent_scope: &ParentScope<'ra>,
744 trace: bool,
745736 force: bool,
746737 deleg_impl: Option<LocalDefId>,
747738 invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
......@@ -780,16 +771,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
780771 PathResult::Module(..) => unreachable!(),
781772 };
782773
783 if trace {
784 self.multi_segment_macro_resolutions.borrow_mut(&self).push((
785 path,
786 path_span,
787 kind,
788 *parent_scope,
789 res.ok(),
790 ns,
791 ));
792 }
774 self.multi_segment_macro_resolutions.borrow_mut(&self).push((
775 path,
776 path_span,
777 kind,
778 *parent_scope,
779 res.ok(),
780 ns,
781 ));
793782
794783 self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
795784 res
......@@ -807,15 +796,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
807796 return Err(Determinacy::Undetermined);
808797 }
809798
810 if trace {
811 self.single_segment_macro_resolutions.borrow_mut(&self).push((
812 path[0].ident,
813 kind,
814 *parent_scope,
815 binding.ok(),
816 suggestion_span,
817 ));
818 }
799 self.single_segment_macro_resolutions.borrow_mut(&self).push((
800 path[0].ident,
801 kind,
802 *parent_scope,
803 binding.ok(),
804 suggestion_span,
805 ));
819806
820807 let res = binding.map(|binding| binding.res());
821808 self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
library/alloc/src/boxed.rs+2-2
......@@ -725,9 +725,9 @@ impl<T, A: Allocator> Box<T, A> {
725725 #[unstable(feature = "box_take", issue = "147212")]
726726 pub fn take(boxed: Self) -> (T, Box<mem::MaybeUninit<T>, A>) {
727727 unsafe {
728 let (raw, alloc) = Box::into_raw_with_allocator(boxed);
728 let (raw, alloc) = Box::into_non_null_with_allocator(boxed);
729729 let value = raw.read();
730 let uninit = Box::from_raw_in(raw.cast::<mem::MaybeUninit<T>>(), alloc);
730 let uninit = Box::from_non_null_in(raw.cast_uninit(), alloc);
731731 (value, uninit)
732732 }
733733 }
library/alloc/src/lib.rs+1
......@@ -116,6 +116,7 @@
116116#![feature(exact_size_is_empty)]
117117#![feature(extend_one)]
118118#![feature(extend_one_unchecked)]
119#![feature(fmt_arguments_from_str)]
119120#![feature(fmt_internals)]
120121#![feature(fn_traits)]
121122#![feature(formatting_options)]
library/core/src/ffi/c_str.rs+4-4
......@@ -15,18 +15,18 @@ use crate::{fmt, ops, slice, str};
1515// actually reference libstd or liballoc in intra-doc links. so, the best we can do is remove the
1616// links to `CString` and `String` for now until a solution is developed
1717
18/// Representation of a borrowed C string.
18/// A dynamically-sized view of a C string.
1919///
20/// This type represents a borrowed reference to a nul-terminated
20/// The type `&CStr` represents a reference to a borrowed nul-terminated
2121/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
2222/// slice, or unsafely from a raw `*const c_char`. It can be expressed as a
2323/// literal in the form `c"Hello world"`.
2424///
25/// The `CStr` can then be converted to a Rust <code>&[str]</code> by performing
25/// The `&CStr` can then be converted to a Rust <code>&[str]</code> by performing
2626/// UTF-8 validation, or into an owned `CString`.
2727///
2828/// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former
29/// in each pair are borrowed references; the latter are owned
29/// in each pair are borrowing references; the latter are owned
3030/// strings.
3131///
3232/// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)`
library/core/src/fmt/mod.rs+14-8
......@@ -734,7 +734,21 @@ impl<'a> Arguments<'a> {
734734 unsafe { Arguments { template: mem::transmute(template), args: mem::transmute(args) } }
735735 }
736736
737 // Same as `from_str`, but not const.
738 // Used by format_args!() expansion when arguments are inlined,
739 // e.g. format_args!("{}", 123), which is not allowed in const.
737740 #[inline]
741 pub fn from_str_nonconst(s: &'static str) -> Arguments<'a> {
742 Arguments::from_str(s)
743 }
744}
745
746impl<'a> Arguments<'a> {
747 /// Create a `fmt::Arguments` object for a single static string.
748 ///
749 /// Formatting this `fmt::Arguments` will just produce the string as-is.
750 #[inline]
751 #[unstable(feature = "fmt_arguments_from_str", issue = "148905")]
738752 pub const fn from_str(s: &'static str) -> Arguments<'a> {
739753 // SAFETY: This is the "static str" representation of fmt::Arguments; see above.
740754 unsafe {
......@@ -744,14 +758,6 @@ impl<'a> Arguments<'a> {
744758 }
745759 }
746760 }
747
748 // Same as `from_str`, but not const.
749 // Used by format_args!() expansion when arguments are inlined,
750 // e.g. format_args!("{}", 123), which is not allowed in const.
751 #[inline]
752 pub fn from_str_nonconst(s: &'static str) -> Arguments<'a> {
753 Arguments::from_str(s)
754 }
755761}
756762
757763#[doc(hidden)]
library/core/src/macros/mod.rs+3-3
......@@ -991,7 +991,7 @@ pub(crate) mod builtin {
991991 #[stable(feature = "rust1", since = "1.0.0")]
992992 #[rustc_diagnostic_item = "format_args_macro"]
993993 #[allow_internal_unsafe]
994 #[allow_internal_unstable(fmt_internals)]
994 #[allow_internal_unstable(fmt_internals, fmt_arguments_from_str)]
995995 #[rustc_builtin_macro]
996996 #[macro_export]
997997 macro_rules! format_args {
......@@ -1005,7 +1005,7 @@ pub(crate) mod builtin {
10051005 ///
10061006 /// This macro will be removed once `format_args` is allowed in const contexts.
10071007 #[unstable(feature = "const_format_args", issue = "none")]
1008 #[allow_internal_unstable(fmt_internals, const_fmt_arguments_new)]
1008 #[allow_internal_unstable(fmt_internals, fmt_arguments_from_str)]
10091009 #[rustc_builtin_macro]
10101010 #[macro_export]
10111011 macro_rules! const_format_args {
......@@ -1020,7 +1020,7 @@ pub(crate) mod builtin {
10201020 reason = "`format_args_nl` is only for internal \
10211021 language use and is subject to change"
10221022 )]
1023 #[allow_internal_unstable(fmt_internals)]
1023 #[allow_internal_unstable(fmt_internals, fmt_arguments_from_str)]
10241024 #[rustc_builtin_macro]
10251025 #[doc(hidden)]
10261026 #[macro_export]
library/std/src/io/mod.rs+41-1
......@@ -330,7 +330,7 @@ pub use self::{
330330 stdio::{Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout},
331331 util::{Empty, Repeat, Sink, empty, repeat, sink},
332332};
333use crate::mem::take;
333use crate::mem::{MaybeUninit, take};
334334use crate::ops::{Deref, DerefMut};
335335use crate::{cmp, fmt, slice, str, sys};
336336
......@@ -1242,6 +1242,46 @@ pub trait Read {
12421242 {
12431243 Take { inner: self, len: limit, limit }
12441244 }
1245
1246 /// Read and return a fixed array of bytes from this source.
1247 ///
1248 /// This function uses an array sized based on a const generic size known at compile time. You
1249 /// can specify the size with turbofish (`reader.read_array::<8>()`), or let type inference
1250 /// determine the number of bytes needed based on how the return value gets used. For instance,
1251 /// this function works well with functions like [`u64::from_le_bytes`] to turn an array of
1252 /// bytes into an integer of the same size.
1253 ///
1254 /// Like `read_exact`, if this function encounters an "end of file" before reading the desired
1255 /// number of bytes, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
1256 ///
1257 /// ```
1258 /// #![feature(read_array)]
1259 /// use std::io::Cursor;
1260 /// use std::io::prelude::*;
1261 ///
1262 /// fn main() -> std::io::Result<()> {
1263 /// let mut buf = Cursor::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2]);
1264 /// let x = u64::from_le_bytes(buf.read_array()?);
1265 /// let y = u32::from_be_bytes(buf.read_array()?);
1266 /// let z = u16::from_be_bytes(buf.read_array()?);
1267 /// assert_eq!(x, 0x807060504030201);
1268 /// assert_eq!(y, 0x9080706);
1269 /// assert_eq!(z, 0x504);
1270 /// Ok(())
1271 /// }
1272 /// ```
1273 #[unstable(feature = "read_array", issue = "148848")]
1274 fn read_array<const N: usize>(&mut self) -> Result<[u8; N]>
1275 where
1276 Self: Sized,
1277 {
1278 let mut buf = [MaybeUninit::uninit(); N];
1279 let mut borrowed_buf = BorrowedBuf::from(buf.as_mut_slice());
1280 self.read_buf_exact(borrowed_buf.unfilled())?;
1281 // Guard against incorrect `read_buf_exact` implementations.
1282 assert_eq!(borrowed_buf.len(), N);
1283 Ok(unsafe { MaybeUninit::array_assume_init(buf) })
1284 }
12451285}
12461286
12471287/// Reads all bytes from a [reader][Read] into a new [`String`].
library/std/src/lib.rs+1
......@@ -348,6 +348,7 @@
348348#![feature(int_from_ascii)]
349349#![feature(ip)]
350350#![feature(lazy_get)]
351#![feature(maybe_uninit_array_assume_init)]
351352#![feature(maybe_uninit_slice)]
352353#![feature(maybe_uninit_write_slice)]
353354#![feature(panic_can_unwind)]
library/std/tests/run-time-detect.rs+1
......@@ -16,6 +16,7 @@
1616 all(target_arch = "powerpc64", target_os = "linux"),
1717 feature(stdarch_powerpc_feature_detection)
1818)]
19#![cfg_attr(all(target_arch = "s390x", target_os = "linux"), feature(s390x_target_feature))]
1920
2021#[test]
2122#[cfg(all(target_arch = "arm", any(target_os = "linux", target_os = "android")))]
src/librustdoc/html/format.rs+15-1
......@@ -838,9 +838,23 @@ fn print_higher_ranked_params_with_space(
838838pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
839839 fmt::from_fn(move |f| {
840840 if let Ok(HrefInfo { url, kind, rust_path }) = href(did, cx) {
841 let tcx = cx.tcx();
842 let def_kind = tcx.def_kind(did);
843 let anchor = if matches!(
844 def_kind,
845 DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant
846 ) {
847 let parent_def_id = tcx.parent(did);
848 let item_type =
849 ItemType::from_def_kind(def_kind, Some(tcx.def_kind(parent_def_id)));
850 format!("#{}.{}", item_type.as_str(), tcx.item_name(did))
851 } else {
852 String::new()
853 };
854
841855 write!(
842856 f,
843 r#"<a class="{kind}" href="{url}" title="{kind} {path}">{text}</a>"#,
857 r#"<a class="{kind}" href="{url}{anchor}" title="{kind} {path}">{text}</a>"#,
844858 path = join_path_syms(rust_path),
845859 text = EscapeBodyText(text.as_str()),
846860 )
tests/assembly-llvm/tail-call-infinite-recursion.rs created+21
......@@ -0,0 +1,21 @@
1//@ add-minicore
2//@ assembly-output: emit-asm
3//@ compile-flags: --target x86_64-unknown-linux-gnu -Copt-level=0 -Cllvm-args=-x86-asm-syntax=intel
4//@ needs-llvm-components: x86
5#![expect(incomplete_features)]
6#![feature(no_core, explicit_tail_calls)]
7#![crate_type = "lib"]
8#![no_core]
9
10extern crate minicore;
11use minicore::*;
12
13// Test that an infinite loop via guaranteed tail calls does not blow the stack.
14
15// CHECK-LABEL: inf
16// CHECK: mov rax, qword ptr [rip + inf@GOTPCREL]
17// CHECK: jmp rax
18#[unsafe(no_mangle)]
19fn inf() -> ! {
20 become inf()
21}
tests/mir-opt/uninhabited_enum.rs+3
......@@ -1,4 +1,7 @@
11// skip-filecheck
2//
3// check that we mark blocks with `!` locals as unreachable.
4// (and currently don't do the same for other uninhabited types)
25#![feature(never_type)]
36
47#[derive(Copy, Clone)]
tests/mir-opt/uninhabited_not_read.rs+1-1
......@@ -1,7 +1,7 @@
11// skip-filecheck
22
33//@ edition: 2021
4// In ed 2021 and below, we don't fallback `!` to `()`.
4// In ed 2021 and below, we fallback `!` to `()`.
55// This would introduce a `! -> ()` coercion which would
66// be UB if we didn't disallow this explicitly.
77
tests/run-make/rustdoc-test-builder/rmake.rs+4-1
......@@ -25,7 +25,10 @@ fn main() {
2525
2626 // Some targets (for example wasm) cannot execute doctests directly even with a runner,
2727 // so only exercise the success path when the target can run on the host.
28 if target().contains("wasm") || std::env::var_os("REMOTE_TEST_CLIENT").is_some() {
28 if target().contains("wasm")
29 || target().contains("sgx")
30 || std::env::var_os("REMOTE_TEST_CLIENT").is_some()
31 {
2932 return;
3033 }
3134
tests/rustdoc/import_trait_associated_functions.rs created+19
......@@ -0,0 +1,19 @@
1// This test ensures that reexports of associated items links to the associated items.
2// Regression test for <https://github.com/rust-lang/rust/issues/148008>.
3
4#![feature(import_trait_associated_functions)]
5
6#![crate_name = "foo"]
7
8//@ has 'foo/index.html'
9
10pub trait Test {
11 fn method();
12 const CONST: u8;
13 type Type;
14}
15
16//@ has - '//*[@id="reexport.method"]//a[@href="trait.Test.html#tymethod.method"]' 'method'
17//@ has - '//*[@id="reexport.CONST"]//a[@href="trait.Test.html#associatedconstant.CONST"]' 'CONST'
18//@ has - '//*[@id="reexport.Type"]//a[@href="trait.Test.html#associatedtype.Type"]' 'Type'
19pub use self::Test::{method, CONST, Type};
tests/ui/coercion/coerce-loop-issue-122561.rs+3-1
......@@ -1,4 +1,6 @@
1// Regression test for #122561
1// Regression test for <https://github.com/rust-lang/rust/issues/122561>.
2//
3// Tests suggestions for type mismatch of loop expressions.
24
35fn for_infinite() -> bool {
46 for i in 0.. {
tests/ui/coercion/coerce-loop-issue-122561.stderr+16-16
......@@ -1,5 +1,5 @@
11warning: denote infinite loops with `loop { ... }`
2 --> $DIR/coerce-loop-issue-122561.rs:47:5
2 --> $DIR/coerce-loop-issue-122561.rs:49:5
33 |
44LL | while true {
55 | ^^^^^^^^^^ help: use `loop`
......@@ -7,13 +7,13 @@ LL | while true {
77 = note: `#[warn(while_true)]` on by default
88
99warning: denote infinite loops with `loop { ... }`
10 --> $DIR/coerce-loop-issue-122561.rs:71:5
10 --> $DIR/coerce-loop-issue-122561.rs:73:5
1111 |
1212LL | while true {
1313 | ^^^^^^^^^^ help: use `loop`
1414
1515error[E0308]: mismatched types
16 --> $DIR/coerce-loop-issue-122561.rs:41:24
16 --> $DIR/coerce-loop-issue-122561.rs:43:24
1717 |
1818LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
1919 | ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
......@@ -25,7 +25,7 @@ LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool {
2525 | +++++++++++++++++++
2626
2727error[E0308]: mismatched types
28 --> $DIR/coerce-loop-issue-122561.rs:4:5
28 --> $DIR/coerce-loop-issue-122561.rs:6:5
2929 |
3030LL | fn for_infinite() -> bool {
3131 | ---- expected `bool` because of return type
......@@ -43,7 +43,7 @@ LL + /* `bool` value */
4343 |
4444
4545error[E0308]: mismatched types
46 --> $DIR/coerce-loop-issue-122561.rs:11:5
46 --> $DIR/coerce-loop-issue-122561.rs:13:5
4747 |
4848LL | fn for_finite() -> String {
4949 | ------ expected `String` because of return type
......@@ -61,7 +61,7 @@ LL + /* `String` value */
6161 |
6262
6363error[E0308]: mismatched types
64 --> $DIR/coerce-loop-issue-122561.rs:18:5
64 --> $DIR/coerce-loop-issue-122561.rs:20:5
6565 |
6666LL | fn for_zero_times() -> bool {
6767 | ---- expected `bool` because of return type
......@@ -79,7 +79,7 @@ LL + /* `bool` value */
7979 |
8080
8181error[E0308]: mismatched types
82 --> $DIR/coerce-loop-issue-122561.rs:25:5
82 --> $DIR/coerce-loop-issue-122561.rs:27:5
8383 |
8484LL | fn for_never_type() -> ! {
8585 | - expected `!` because of return type
......@@ -98,7 +98,7 @@ LL + /* `loop {}` or `panic!("...")` */
9898 |
9999
100100error[E0308]: mismatched types
101 --> $DIR/coerce-loop-issue-122561.rs:33:32
101 --> $DIR/coerce-loop-issue-122561.rs:35:32
102102 |
103103LL | fn for_single_line() -> bool { for i in 0.. { return false; } }
104104 | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
......@@ -112,7 +112,7 @@ LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` val
112112 | ++++++++++++++++++
113113
114114error[E0308]: mismatched types
115 --> $DIR/coerce-loop-issue-122561.rs:47:5
115 --> $DIR/coerce-loop-issue-122561.rs:49:5
116116 |
117117LL | fn while_inifinite() -> bool {
118118 | ---- expected `bool` because of return type
......@@ -131,7 +131,7 @@ LL + /* `bool` value */
131131 |
132132
133133error[E0308]: mismatched types
134 --> $DIR/coerce-loop-issue-122561.rs:56:5
134 --> $DIR/coerce-loop-issue-122561.rs:58:5
135135 |
136136LL | fn while_finite() -> bool {
137137 | ---- expected `bool` because of return type
......@@ -151,7 +151,7 @@ LL + /* `bool` value */
151151 |
152152
153153error[E0308]: mismatched types
154 --> $DIR/coerce-loop-issue-122561.rs:64:5
154 --> $DIR/coerce-loop-issue-122561.rs:66:5
155155 |
156156LL | fn while_zero_times() -> bool {
157157 | ---- expected `bool` because of return type
......@@ -169,7 +169,7 @@ LL + /* `bool` value */
169169 |
170170
171171error[E0308]: mismatched types
172 --> $DIR/coerce-loop-issue-122561.rs:71:5
172 --> $DIR/coerce-loop-issue-122561.rs:73:5
173173 |
174174LL | fn while_never_type() -> ! {
175175 | - expected `!` because of return type
......@@ -188,7 +188,7 @@ LL + /* `loop {}` or `panic!("...")` */
188188 |
189189
190190error[E0308]: mismatched types
191 --> $DIR/coerce-loop-issue-122561.rs:85:5
191 --> $DIR/coerce-loop-issue-122561.rs:87:5
192192 |
193193LL | / for i in 0.. {
194194LL | |
......@@ -203,7 +203,7 @@ LL + /* `i32` value */
203203 |
204204
205205error[E0308]: mismatched types
206 --> $DIR/coerce-loop-issue-122561.rs:92:9
206 --> $DIR/coerce-loop-issue-122561.rs:94:9
207207 |
208208LL | / for i in 0..5 {
209209LL | |
......@@ -218,7 +218,7 @@ LL + /* `usize` value */
218218 |
219219
220220error[E0308]: mismatched types
221 --> $DIR/coerce-loop-issue-122561.rs:98:9
221 --> $DIR/coerce-loop-issue-122561.rs:100:9
222222 |
223223LL | / while false {
224224LL | |
......@@ -233,7 +233,7 @@ LL + /* `usize` value */
233233 |
234234
235235error[E0308]: mismatched types
236 --> $DIR/coerce-loop-issue-122561.rs:104:23
236 --> $DIR/coerce-loop-issue-122561.rs:106:23
237237 |
238238LL | let _ = |a: &[(); for x in 0..2 {}]| {};
239239 | ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
tests/ui/consts/const-eval/raw-bytes.rs+1-1
......@@ -34,7 +34,7 @@ const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
3434#[derive(Copy, Clone)]
3535enum Never {}
3636
37// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do*
37// An enum with 4 variants of which only some are uninhabited -- so the uninhabited variants *do*
3838// have a discriminant.
3939enum UninhDiscriminant {
4040 A,
tests/ui/consts/let-irrefutable-pattern-ice-120337.rs+9-1
......@@ -1,10 +1,18 @@
1// Regression test for <https://github.com/rust-lang/rust/issues/120337>.
2//
3// This checks that const eval doesn't cause an ICE when reading an uninhabited
4// variant. (N.B. this is UB, but not currently detected by rustc)
5//
16//@ check-pass
27#![feature(never_type)]
8
39#[derive(Copy, Clone)]
410pub enum E { A(!), }
11
512pub union U { u: (), e: E, }
13
614pub const C: () = {
7 let E::A(ref a) = unsafe { &(&U { u: () }).e};
15 let E::A(ref a) = unsafe { &(&U { u: () }).e };
816};
917
1018fn main() {}
tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.rs created+38
......@@ -0,0 +1,38 @@
1//@ add-minicore
2//@ ignore-backends: gcc
3//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
4//@ needs-llvm-components: arm
5#![expect(incomplete_features)]
6#![feature(no_core, explicit_tail_calls, abi_cmse_nonsecure_call)]
7#![no_core]
8
9extern crate minicore;
10use minicore::*;
11
12unsafe extern "C" {
13 safe fn magic() -> extern "cmse-nonsecure-call" fn(u32, u32) -> u32;
14}
15
16// The `cmse-nonsecure-call` ABI can only occur on function pointers:
17//
18// - a `cmse-nonsecure-call` definition throws an error
19// - a `cmse-nonsecure-call` become in a definition with any other ABI is an ABI mismatch
20#[no_mangle]
21extern "cmse-nonsecure-call" fn become_nonsecure_call_1(x: u32, y: u32) -> u32 {
22 //~^ ERROR the `"cmse-nonsecure-call"` ABI is only allowed on function pointers
23 unsafe {
24 let f = magic();
25 become f(1, 2)
26 //~^ ERROR ABI does not support guaranteed tail calls
27 }
28}
29
30#[no_mangle]
31extern "C" fn become_nonsecure_call_2(x: u32, y: u32) -> u32 {
32 unsafe {
33 let f = magic();
34 become f(1, 2)
35 //~^ ERROR mismatched function ABIs
36 //~| ERROR ABI does not support guaranteed tail calls
37 }
38}
tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-call.stderr created+34
......@@ -0,0 +1,34 @@
1error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers
2 --> $DIR/cmse-nonsecure-call.rs:21:1
3 |
4LL | extern "cmse-nonsecure-call" fn become_nonsecure_call_1(x: u32, y: u32) -> u32 {
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6
7error: ABI does not support guaranteed tail calls
8 --> $DIR/cmse-nonsecure-call.rs:25:9
9 |
10LL | become f(1, 2)
11 | ^^^^^^^^^^^^^^
12 |
13 = note: `become` is not supported for `extern "cmse-nonsecure-call"` functions
14
15error: mismatched function ABIs
16 --> $DIR/cmse-nonsecure-call.rs:34:9
17 |
18LL | become f(1, 2)
19 | ^^^^^^^^^^^^^^
20 |
21 = note: `become` requires caller and callee to have the same ABI
22 = note: caller ABI is `"C"`, while callee ABI is `"cmse-nonsecure-call"`
23
24error: ABI does not support guaranteed tail calls
25 --> $DIR/cmse-nonsecure-call.rs:34:9
26 |
27LL | become f(1, 2)
28 | ^^^^^^^^^^^^^^
29 |
30 = note: `become` is not supported for `extern "cmse-nonsecure-call"` functions
31
32error: aborting due to 4 previous errors
33
34For more information about this error, try `rustc --explain E0781`.
tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.rs created+22
......@@ -0,0 +1,22 @@
1//@ add-minicore
2//@ ignore-backends: gcc
3//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
4//@ needs-llvm-components: arm
5#![expect(incomplete_features)]
6#![feature(no_core, explicit_tail_calls, cmse_nonsecure_entry)]
7#![no_core]
8
9extern crate minicore;
10use minicore::*;
11
12#[inline(never)]
13extern "cmse-nonsecure-entry" fn entry(c: bool, x: u32, y: u32) -> u32 {
14 if c { x } else { y }
15}
16
17// A `cmse-nonsecure-entry` clears registers before returning, so a tail call cannot be guaranteed.
18#[unsafe(no_mangle)]
19extern "cmse-nonsecure-entry" fn become_nonsecure_entry(c: bool, x: u32, y: u32) -> u32 {
20 become entry(c, x, y)
21 //~^ ERROR ABI does not support guaranteed tail calls
22}
tests/ui/explicit-tail-calls/unsupported-abi/cmse-nonsecure-entry.stderr created+10
......@@ -0,0 +1,10 @@
1error: ABI does not support guaranteed tail calls
2 --> $DIR/cmse-nonsecure-entry.rs:20:5
3 |
4LL | become entry(c, x, y)
5 | ^^^^^^^^^^^^^^^^^^^^^
6 |
7 = note: `become` is not supported for `extern "cmse-nonsecure-entry"` functions
8
9error: aborting due to 1 previous error
10
tests/ui/never_type/dispatch_from_dyn_zst.rs deleted-51
......@@ -1,51 +0,0 @@
1//@ run-pass
2
3#![feature(unsize, dispatch_from_dyn, never_type)]
4
5#![allow(dead_code)]
6
7use std::{
8 ops::DispatchFromDyn,
9 marker::{Unsize, PhantomData},
10};
11
12struct Zst;
13struct NestedZst(PhantomData<()>, Zst);
14
15
16struct WithUnit<T: ?Sized>(Box<T>, ());
17impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithUnit<U>> for WithUnit<T>
18 where T: Unsize<U> {}
19
20struct WithPhantom<T: ?Sized>(Box<T>, PhantomData<()>);
21impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithPhantom<U>> for WithPhantom<T>
22 where T: Unsize<U> {}
23
24struct WithNever<T: ?Sized>(Box<T>, !);
25impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNever<U>> for WithNever<T>
26 where T: Unsize<U> {}
27
28struct WithZst<T: ?Sized>(Box<T>, Zst);
29impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithZst<U>> for WithZst<T>
30 where T: Unsize<U> {}
31
32struct WithNestedZst<T: ?Sized>(Box<T>, NestedZst);
33impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNestedZst<U>> for WithNestedZst<T>
34 where T: Unsize<U> {}
35
36
37struct Generic<T: ?Sized, A>(Box<T>, A);
38impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, ()>> for Generic<T, ()>
39 where T: Unsize<U> {}
40impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, PhantomData<()>>>
41 for Generic<T, PhantomData<()>>
42 where T: Unsize<U> {}
43impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, !>> for Generic<T, !>
44 where T: Unsize<U> {}
45impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, Zst>> for Generic<T, Zst>
46 where T: Unsize<U> {}
47impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, NestedZst>> for Generic<T, NestedZst>
48 where T: Unsize<U> {}
49
50
51fn main() {}
tests/ui/self/dispatch_from_dyn_zst.rs created+51
......@@ -0,0 +1,51 @@
1//@ run-pass
2
3#![feature(unsize, dispatch_from_dyn, never_type)]
4
5#![allow(dead_code)]
6
7use std::{
8 ops::DispatchFromDyn,
9 marker::{Unsize, PhantomData},
10};
11
12struct Zst;
13struct NestedZst(PhantomData<()>, Zst);
14
15
16struct WithUnit<T: ?Sized>(Box<T>, ());
17impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithUnit<U>> for WithUnit<T>
18 where T: Unsize<U> {}
19
20struct WithPhantom<T: ?Sized>(Box<T>, PhantomData<()>);
21impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithPhantom<U>> for WithPhantom<T>
22 where T: Unsize<U> {}
23
24struct WithNever<T: ?Sized>(Box<T>, !);
25impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNever<U>> for WithNever<T>
26 where T: Unsize<U> {}
27
28struct WithZst<T: ?Sized>(Box<T>, Zst);
29impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithZst<U>> for WithZst<T>
30 where T: Unsize<U> {}
31
32struct WithNestedZst<T: ?Sized>(Box<T>, NestedZst);
33impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNestedZst<U>> for WithNestedZst<T>
34 where T: Unsize<U> {}
35
36
37struct Generic<T: ?Sized, A>(Box<T>, A);
38impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, ()>> for Generic<T, ()>
39 where T: Unsize<U> {}
40impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, PhantomData<()>>>
41 for Generic<T, PhantomData<()>>
42 where T: Unsize<U> {}
43impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, !>> for Generic<T, !>
44 where T: Unsize<U> {}
45impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, Zst>> for Generic<T, Zst>
46 where T: Unsize<U> {}
47impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, NestedZst>> for Generic<T, NestedZst>
48 where T: Unsize<U> {}
49
50
51fn main() {}
triagebot.toml-3
......@@ -922,9 +922,6 @@ cc = ["@davidtwco", "@wesleywiser"]
922922[mentions."compiler/rustc_codegen_cranelift"]
923923cc = ["@bjorn3"]
924924
925[mentions."compiler/rustc_codegen_ssa"]
926cc = ["@WaffleLapkin"]
927
928925[mentions."compiler/rustc_codegen_gcc"]
929926cc = ["@antoyo", "@GuillaumeGomez"]
930927