Skip to content

Commit 96eaf55

Browse files
committed
Auto merge of #123455 - matthiaskrgr:rollup-b6nu296, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #121546 (Error out of layout calculation if a non-last struct field is unsized) - #122448 (Port hir-tree run-make test to ui test) - #123212 (CFI: Change type transformation to use TypeFolder) - #123218 (Add test for getting parent HIR for synthetic HIR node) - #123324 (match lowering: make false edges more precise) - #123389 (Avoid panicking unnecessarily on startup) - #123397 (Fix diagnostic for qualifier in extern block) - #123431 (Stabilize `proc_macro_byte_character` and `proc_macro_c_str_literals`) - #123439 (coverage: Remove useless constants) r? `@ghost` `@rustbot` modify labels: rollup
2 parents ca7d34e + 4ba3f46 commit 96eaf55

File tree

42 files changed

+893
-512
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+893
-512
lines changed

compiler/rustc_ast/src/ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2484,6 +2484,14 @@ pub enum CoroutineKind {
24842484
}
24852485

24862486
impl CoroutineKind {
2487+
pub fn span(self) -> Span {
2488+
match self {
2489+
CoroutineKind::Async { span, .. } => span,
2490+
CoroutineKind::Gen { span, .. } => span,
2491+
CoroutineKind::AsyncGen { span, .. } => span,
2492+
}
2493+
}
2494+
24872495
pub fn is_async(self) -> bool {
24882496
matches!(self, CoroutineKind::Async { .. })
24892497
}

compiler/rustc_ast_passes/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ ast_passes_extern_block_suggestion = if you meant to declare an externally defin
6868
6969
ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
7070
.label = in this `extern` block
71-
.suggestion = remove the qualifiers
71+
.suggestion = remove this qualifier
7272
7373
ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
7474
.label = in this `extern` block

compiler/rustc_ast_passes/src/ast_validation.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -514,13 +514,32 @@ impl<'a> AstValidator<'a> {
514514
}
515515

516516
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
517-
fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
518-
if header.has_qualifiers() {
517+
fn check_foreign_fn_headerless(
518+
&self,
519+
// Deconstruct to ensure exhaustiveness
520+
FnHeader { unsafety, coroutine_kind, constness, ext }: FnHeader,
521+
) {
522+
let report_err = |span| {
519523
self.dcx().emit_err(errors::FnQualifierInExtern {
520-
span: ident.span,
524+
span: span,
521525
block: self.current_extern_span(),
522-
sugg_span: span.until(ident.span.shrink_to_lo()),
523526
});
527+
};
528+
match unsafety {
529+
Unsafe::Yes(span) => report_err(span),
530+
Unsafe::No => (),
531+
}
532+
match coroutine_kind {
533+
Some(knd) => report_err(knd.span()),
534+
None => (),
535+
}
536+
match constness {
537+
Const::Yes(span) => report_err(span),
538+
Const::No => (),
539+
}
540+
match ext {
541+
Extern::None => (),
542+
Extern::Implicit(span) | Extern::Explicit(_, span) => report_err(span),
524543
}
525544
}
526545

@@ -1145,7 +1164,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11451164
ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
11461165
self.check_defaultness(fi.span, *defaultness);
11471166
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
1148-
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
1167+
self.check_foreign_fn_headerless(sig.header);
11491168
self.check_foreign_item_ascii_only(fi.ident);
11501169
}
11511170
ForeignItemKind::TyAlias(box TyAlias {

compiler/rustc_ast_passes/src/errors.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,10 @@ pub struct FnBodyInExtern {
270270
#[diag(ast_passes_extern_fn_qualifiers)]
271271
pub struct FnQualifierInExtern {
272272
#[primary_span]
273+
#[suggestion(code = "", applicability = "maybe-incorrect")]
273274
pub span: Span,
274275
#[label]
275276
pub block: Span,
276-
#[suggestion(code = "fn ", applicability = "maybe-incorrect", style = "verbose")]
277-
pub sugg_span: Span,
278277
}
279278

280279
#[derive(Diagnostic)]

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ pub(crate) mod ffi;
2424
pub(crate) mod map_data;
2525
pub mod mapgen;
2626

27-
const VAR_ALIGN: Align = Align::EIGHT;
28-
2927
/// A context object for maintaining all state needed by the coverageinfo module.
3028
pub struct CrateCoverageContext<'ll, 'tcx> {
3129
/// Coverage data for each instrumented function identified by DefId.
@@ -226,7 +224,8 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
226224
llvm::set_global_constant(llglobal, true);
227225
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
228226
llvm::set_section(llglobal, &covmap_section_name);
229-
llvm::set_alignment(llglobal, VAR_ALIGN);
227+
// LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
228+
llvm::set_alignment(llglobal, Align::EIGHT);
230229
cx.add_used_global(llglobal);
231230
}
232231

@@ -256,7 +255,8 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
256255
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
257256
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
258257
llvm::set_section(llglobal, covfun_section_name);
259-
llvm::set_alignment(llglobal, VAR_ALIGN);
258+
// LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
259+
llvm::set_alignment(llglobal, Align::EIGHT);
260260
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
261261
cx.add_used_global(llglobal);
262262
}

compiler/rustc_middle/src/mir/coverage.rs

-8
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ rustc_index::newtype_index! {
3333
pub struct CounterId {}
3434
}
3535

36-
impl CounterId {
37-
pub const START: Self = Self::ZERO;
38-
}
39-
4036
rustc_index::newtype_index! {
4137
/// ID of a coverage-counter expression. Values ascend from 0.
4238
///
@@ -55,10 +51,6 @@ rustc_index::newtype_index! {
5551
pub struct ExpressionId {}
5652
}
5753

58-
impl ExpressionId {
59-
pub const START: Self = Self::ZERO;
60-
}
61-
6254
/// Enum that can hold a constant zero value, the ID of an physical coverage
6355
/// counter, or the ID of a coverage-counter expression.
6456
///

compiler/rustc_mir_build/src/build/matches/mod.rs

+94-12
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,77 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
214214
///
215215
/// ## False edges
216216
///
217-
/// We don't want to have the exact structure of the decision tree be
218-
/// visible through borrow checking. False edges ensure that the CFG as
219-
/// seen by borrow checking doesn't encode this. False edges are added:
217+
/// We don't want to have the exact structure of the decision tree be visible through borrow
218+
/// checking. Specifically we want borrowck to think that:
219+
/// - at any point, any or none of the patterns and guards seen so far may have been tested;
220+
/// - after the match, any of the patterns may have matched.
220221
///
221-
/// * From each pre-binding block to the next pre-binding block.
222-
/// * From each otherwise block to the next pre-binding block.
222+
/// For example, all of these would fail to error if borrowck could see the real CFG (examples
223+
/// taken from `tests/ui/nll/match-cfg-fake-edges.rs`):
224+
/// ```ignore (too many errors, this is already in the test suite)
225+
/// let x = String::new();
226+
/// let _ = match true {
227+
/// _ => {},
228+
/// _ => drop(x),
229+
/// };
230+
/// // Borrowck must not know the second arm is never run.
231+
/// drop(x); //~ ERROR use of moved value
232+
///
233+
/// let x;
234+
/// # let y = true;
235+
/// match y {
236+
/// _ if { x = 2; true } => {},
237+
/// // Borrowck must not know the guard is always run.
238+
/// _ => drop(x), //~ ERROR used binding `x` is possibly-uninitialized
239+
/// };
240+
///
241+
/// let x = String::new();
242+
/// # let y = true;
243+
/// match y {
244+
/// false if { drop(x); true } => {},
245+
/// // Borrowck must not know the guard is not run in the `true` case.
246+
/// true => drop(x), //~ ERROR use of moved value: `x`
247+
/// false => {},
248+
/// };
249+
///
250+
/// # let mut y = (true, true);
251+
/// let r = &mut y.1;
252+
/// match y {
253+
/// //~^ ERROR cannot use `y.1` because it was mutably borrowed
254+
/// (false, true) => {}
255+
/// // Borrowck must not know we don't test `y.1` when `y.0` is `true`.
256+
/// (true, _) => drop(r),
257+
/// (false, _) => {}
258+
/// };
259+
/// ```
260+
///
261+
/// We add false edges to act as if we were naively matching each arm in order. What we need is
262+
/// a (fake) path from each candidate to the next, specifically from candidate C's pre-binding
263+
/// block to next candidate D's pre-binding block. For maximum precision (needed for deref
264+
/// patterns), we choose the earliest node on D's success path that doesn't also lead to C (to
265+
/// avoid loops).
266+
///
267+
/// This turns out to be easy to compute: that block is the `start_block` of the first call to
268+
/// `match_candidates` where D is the first candidate in the list.
269+
///
270+
/// For example:
271+
/// ```rust
272+
/// # let (x, y) = (true, true);
273+
/// match (x, y) {
274+
/// (true, true) => 1,
275+
/// (false, true) => 2,
276+
/// (true, false) => 3,
277+
/// _ => 4,
278+
/// }
279+
/// # ;
280+
/// ```
281+
/// In this example, the pre-binding block of arm 1 has a false edge to the block for result
282+
/// `false` of the first test on `x`. The other arms have false edges to the pre-binding blocks
283+
/// of the next arm.
284+
///
285+
/// On top of this, we also add a false edge from the otherwise_block of each guard to the
286+
/// aforementioned start block of the next candidate, to ensure borrock doesn't rely on which
287+
/// guards may have run.
223288
#[instrument(level = "debug", skip(self, arms))]
224289
pub(crate) fn match_expr(
225290
&mut self,
@@ -365,7 +430,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
365430
for candidate in candidates {
366431
candidate.visit_leaves(|leaf_candidate| {
367432
if let Some(ref mut prev) = previous_candidate {
368-
prev.next_candidate_pre_binding_block = leaf_candidate.pre_binding_block;
433+
assert!(leaf_candidate.false_edge_start_block.is_some());
434+
prev.next_candidate_start_block = leaf_candidate.false_edge_start_block;
369435
}
370436
previous_candidate = Some(leaf_candidate);
371437
});
@@ -1010,8 +1076,12 @@ struct Candidate<'pat, 'tcx> {
10101076

10111077
/// The block before the `bindings` have been established.
10121078
pre_binding_block: Option<BasicBlock>,
1013-
/// The pre-binding block of the next candidate.
1014-
next_candidate_pre_binding_block: Option<BasicBlock>,
1079+
1080+
/// The earliest block that has only candidates >= this one as descendents. Used for false
1081+
/// edges, see the doc for [`Builder::match_expr`].
1082+
false_edge_start_block: Option<BasicBlock>,
1083+
/// The `false_edge_start_block` of the next candidate.
1084+
next_candidate_start_block: Option<BasicBlock>,
10151085
}
10161086

10171087
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
@@ -1033,7 +1103,8 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
10331103
or_span: None,
10341104
otherwise_block: None,
10351105
pre_binding_block: None,
1036-
next_candidate_pre_binding_block: None,
1106+
false_edge_start_block: None,
1107+
next_candidate_start_block: None,
10371108
}
10381109
}
10391110

@@ -1325,6 +1396,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13251396
otherwise_block: BasicBlock,
13261397
candidates: &mut [&mut Candidate<'_, 'tcx>],
13271398
) {
1399+
if let [first, ..] = candidates {
1400+
if first.false_edge_start_block.is_none() {
1401+
first.false_edge_start_block = Some(start_block);
1402+
}
1403+
}
1404+
13281405
match candidates {
13291406
[] => {
13301407
// If there are no candidates that still need testing, we're done. Since all matches are
@@ -1545,6 +1622,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15451622
.into_iter()
15461623
.map(|flat_pat| Candidate::from_flat_pat(flat_pat, candidate.has_guard))
15471624
.collect();
1625+
candidate.subcandidates[0].false_edge_start_block = candidate.false_edge_start_block;
15481626
}
15491627

15501628
/// Try to merge all of the subcandidates of the given candidate into one. This avoids
@@ -1564,6 +1642,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15641642
let any_matches = self.cfg.start_new_block();
15651643
let or_span = candidate.or_span.take().unwrap();
15661644
let source_info = self.source_info(or_span);
1645+
if candidate.false_edge_start_block.is_none() {
1646+
candidate.false_edge_start_block =
1647+
candidate.subcandidates[0].false_edge_start_block;
1648+
}
15671649
for subcandidate in mem::take(&mut candidate.subcandidates) {
15681650
let or_block = subcandidate.pre_binding_block.unwrap();
15691651
self.cfg.goto(or_block, source_info, any_matches);
@@ -1979,12 +2061,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19792061

19802062
let mut block = candidate.pre_binding_block.unwrap();
19812063

1982-
if candidate.next_candidate_pre_binding_block.is_some() {
2064+
if candidate.next_candidate_start_block.is_some() {
19832065
let fresh_block = self.cfg.start_new_block();
19842066
self.false_edges(
19852067
block,
19862068
fresh_block,
1987-
candidate.next_candidate_pre_binding_block,
2069+
candidate.next_candidate_start_block,
19882070
candidate_source_info,
19892071
);
19902072
block = fresh_block;
@@ -2132,7 +2214,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21322214
self.false_edges(
21332215
otherwise_post_guard_block,
21342216
otherwise_block,
2135-
candidate.next_candidate_pre_binding_block,
2217+
candidate.next_candidate_start_block,
21362218
source_info,
21372219
);
21382220

compiler/rustc_mir_transform/src/coverage/query.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn coverage_ids_info<'tcx>(
5959
_ => None,
6060
})
6161
.max()
62-
.unwrap_or(CounterId::START);
62+
.unwrap_or(CounterId::ZERO);
6363

6464
CoverageIdsInfo { max_counter_id }
6565
}

0 commit comments

Comments
 (0)