Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 10a7aa1

Browse files
committedMar 27, 2024
Auto merge of #123128 - GuillaumeGomez:rollup-3l3zu6s, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - #121843 (Implement `-L KIND=`@RUSTC_BUILTIN/...`)` - #122860 (coverage: Re-enable `UnreachablePropagation` for coverage builds) - #123021 (Make `TyCtxt::coroutine_layout` take coroutine's kind parameter) - #123024 (CFI: Enable KCFI testing of run-pass tests) - #123083 (lib: fix some unnecessary_cast clippy lint) - #123116 (rustdoc: Swap fields and variant documentations) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0dcc130 + c0945f0 commit 10a7aa1

File tree

28 files changed

+265
-161
lines changed

28 files changed

+265
-161
lines changed
 

‎compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

Lines changed: 92 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ use crate::llvm;
66

77
use itertools::Itertools as _;
88
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
9-
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
10-
use rustc_hir::def::DefKind;
11-
use rustc_hir::def_id::DefId;
9+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
10+
use rustc_hir::def_id::{DefId, LocalDefId};
1211
use rustc_index::IndexVec;
1312
use rustc_middle::bug;
1413
use rustc_middle::mir;
@@ -335,16 +334,9 @@ fn save_function_record(
335334
);
336335
}
337336

338-
/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for
339-
/// the functions that went through codegen; such as public functions and "used" functions
340-
/// (functions referenced by other "used" or public items). Any other functions considered unused,
341-
/// or "Unreachable", were still parsed and processed through the MIR stage, but were not
342-
/// codegenned. (Note that `-Clink-dead-code` can force some unused code to be codegenned, but
343-
/// that flag is known to cause other errors, when combined with `-C instrument-coverage`; and
344-
/// `-Clink-dead-code` will not generate code for unused generic functions.)
345-
///
346-
/// We can find the unused functions (including generic functions) by the set difference of all MIR
347-
/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`codegenned_and_inlined_items`).
337+
/// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
338+
/// But since we don't want unused functions to disappear from coverage reports, we also scan for
339+
/// functions that were instrumented but are not participating in codegen.
348340
///
349341
/// These unused functions don't need to be codegenned, but we do need to add them to the function
350342
/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
@@ -354,75 +346,109 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
354346
assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
355347

356348
let tcx = cx.tcx;
349+
let usage = prepare_usage_sets(tcx);
350+
351+
let is_unused_fn = |def_id: LocalDefId| -> bool {
352+
let def_id = def_id.to_def_id();
353+
354+
// To be eligible for "unused function" mappings, a definition must:
355+
// - Be function-like
356+
// - Not participate directly in codegen (or have lost all its coverage statements)
357+
// - Not have any coverage statements inlined into codegenned functions
358+
tcx.def_kind(def_id).is_fn_like()
359+
&& (!usage.all_mono_items.contains(&def_id)
360+
|| usage.missing_own_coverage.contains(&def_id))
361+
&& !usage.used_via_inlining.contains(&def_id)
362+
};
357363

358-
let eligible_def_ids = tcx.mir_keys(()).iter().filter_map(|local_def_id| {
359-
let def_id = local_def_id.to_def_id();
360-
let kind = tcx.def_kind(def_id);
361-
// `mir_keys` will give us `DefId`s for all kinds of things, not
362-
// just "functions", like consts, statics, etc. Filter those out.
363-
if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) {
364-
return None;
365-
}
364+
// Scan for unused functions that were instrumented for coverage.
365+
for def_id in tcx.mir_keys(()).iter().copied().filter(|&def_id| is_unused_fn(def_id)) {
366+
// Get the coverage info from MIR, skipping functions that were never instrumented.
367+
let body = tcx.optimized_mir(def_id);
368+
let Some(function_coverage_info) = body.function_coverage_info.as_deref() else { continue };
366369

367370
// FIXME(79651): Consider trying to filter out dummy instantiations of
368371
// unused generic functions from library crates, because they can produce
369372
// "unused instantiation" in coverage reports even when they are actually
370373
// used by some downstream crate in the same binary.
371374

372-
Some(local_def_id.to_def_id())
373-
});
374-
375-
let codegenned_def_ids = codegenned_and_inlined_items(tcx);
376-
377-
// For each `DefId` that should have coverage instrumentation but wasn't
378-
// codegenned, add it to the function coverage map as an unused function.
379-
for def_id in eligible_def_ids.filter(|id| !codegenned_def_ids.contains(id)) {
380-
// Skip any function that didn't have coverage data added to it by the
381-
// coverage instrumentor.
382-
let body = tcx.instance_mir(ty::InstanceDef::Item(def_id));
383-
let Some(function_coverage_info) = body.function_coverage_info.as_deref() else {
384-
continue;
385-
};
386-
387375
debug!("generating unused fn: {def_id:?}");
388-
let instance = declare_unused_fn(tcx, def_id);
389-
add_unused_function_coverage(cx, instance, function_coverage_info);
376+
add_unused_function_coverage(cx, def_id, function_coverage_info);
390377
}
391378
}
392379

393-
/// All items participating in code generation together with (instrumented)
394-
/// items inlined into them.
395-
fn codegenned_and_inlined_items(tcx: TyCtxt<'_>) -> DefIdSet {
396-
let (items, cgus) = tcx.collect_and_partition_mono_items(());
397-
let mut visited = DefIdSet::default();
398-
let mut result = items.clone();
399-
400-
for cgu in cgus {
401-
for item in cgu.items().keys() {
402-
if let mir::mono::MonoItem::Fn(ref instance) = item {
403-
let did = instance.def_id();
404-
if !visited.insert(did) {
405-
continue;
406-
}
407-
let body = tcx.instance_mir(instance.def);
408-
for block in body.basic_blocks.iter() {
409-
for statement in &block.statements {
410-
let mir::StatementKind::Coverage(_) = statement.kind else { continue };
411-
let scope = statement.source_info.scope;
412-
if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
413-
result.insert(inlined.def_id());
414-
}
415-
}
416-
}
380+
struct UsageSets<'tcx> {
381+
all_mono_items: &'tcx DefIdSet,
382+
used_via_inlining: FxHashSet<DefId>,
383+
missing_own_coverage: FxHashSet<DefId>,
384+
}
385+
386+
/// Prepare sets of definitions that are relevant to deciding whether something
387+
/// is an "unused function" for coverage purposes.
388+
fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
389+
let (all_mono_items, cgus) = tcx.collect_and_partition_mono_items(());
390+
391+
// Obtain a MIR body for each function participating in codegen, via an
392+
// arbitrary instance.
393+
let mut def_ids_seen = FxHashSet::default();
394+
let def_and_mir_for_all_mono_fns = cgus
395+
.iter()
396+
.flat_map(|cgu| cgu.items().keys())
397+
.filter_map(|item| match item {
398+
mir::mono::MonoItem::Fn(instance) => Some(instance),
399+
mir::mono::MonoItem::Static(_) | mir::mono::MonoItem::GlobalAsm(_) => None,
400+
})
401+
// We only need one arbitrary instance per definition.
402+
.filter(move |instance| def_ids_seen.insert(instance.def_id()))
403+
.map(|instance| {
404+
// We don't care about the instance, just its underlying MIR.
405+
let body = tcx.instance_mir(instance.def);
406+
(instance.def_id(), body)
407+
});
408+
409+
// Functions whose coverage statments were found inlined into other functions.
410+
let mut used_via_inlining = FxHashSet::default();
411+
// Functions that were instrumented, but had all of their coverage statements
412+
// removed by later MIR transforms (e.g. UnreachablePropagation).
413+
let mut missing_own_coverage = FxHashSet::default();
414+
415+
for (def_id, body) in def_and_mir_for_all_mono_fns {
416+
let mut saw_own_coverage = false;
417+
418+
// Inspect every coverage statement in the function's MIR.
419+
for stmt in body
420+
.basic_blocks
421+
.iter()
422+
.flat_map(|block| &block.statements)
423+
.filter(|stmt| matches!(stmt.kind, mir::StatementKind::Coverage(_)))
424+
{
425+
if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) {
426+
// This coverage statement was inlined from another function.
427+
used_via_inlining.insert(inlined.def_id());
428+
} else {
429+
// Non-inlined coverage statements belong to the enclosing function.
430+
saw_own_coverage = true;
417431
}
418432
}
433+
434+
if !saw_own_coverage && body.function_coverage_info.is_some() {
435+
missing_own_coverage.insert(def_id);
436+
}
419437
}
420438

421-
result
439+
UsageSets { all_mono_items, used_via_inlining, missing_own_coverage }
422440
}
423441

424-
fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tcx> {
425-
ty::Instance::new(
442+
fn add_unused_function_coverage<'tcx>(
443+
cx: &CodegenCx<'_, 'tcx>,
444+
def_id: LocalDefId,
445+
function_coverage_info: &'tcx mir::coverage::FunctionCoverageInfo,
446+
) {
447+
let tcx = cx.tcx;
448+
let def_id = def_id.to_def_id();
449+
450+
// Make a dummy instance that fills in all generics with placeholders.
451+
let instance = ty::Instance::new(
426452
def_id,
427453
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
428454
if let ty::GenericParamDefKind::Lifetime = param.kind {
@@ -431,14 +457,8 @@ fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tc
431457
tcx.mk_param_from_def(param)
432458
}
433459
}),
434-
)
435-
}
460+
);
436461

437-
fn add_unused_function_coverage<'tcx>(
438-
cx: &CodegenCx<'_, 'tcx>,
439-
instance: ty::Instance<'tcx>,
440-
function_coverage_info: &'tcx mir::coverage::FunctionCoverageInfo,
441-
) {
442462
// An unused function's mappings will automatically be rewritten to map to
443463
// zero, because none of its counters/expressions are marked as seen.
444464
let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info);

‎compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,8 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
683683
_ => unreachable!(),
684684
};
685685

686-
let coroutine_layout = cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
686+
let coroutine_layout =
687+
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
687688

688689
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
689690
let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);

‎compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
135135
unique_type_id: UniqueTypeId<'tcx>,
136136
) -> DINodeCreationResult<'ll> {
137137
let coroutine_type = unique_type_id.expect_ty();
138-
let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else {
138+
let &ty::Coroutine(coroutine_def_id, coroutine_args) = coroutine_type.kind() else {
139139
bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
140140
};
141141

@@ -158,8 +158,10 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
158158
DIFlags::FlagZero,
159159
),
160160
|cx, coroutine_type_di_node| {
161-
let coroutine_layout =
162-
cx.tcx.optimized_mir(coroutine_def_id).coroutine_layout().unwrap();
161+
let coroutine_layout = cx
162+
.tcx
163+
.coroutine_layout(coroutine_def_id, coroutine_args.as_coroutine().kind_ty())
164+
.unwrap();
163165

164166
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
165167
coroutine_type_and_layout.variants

‎compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,17 @@ impl<'tcx> MirPass<'tcx> for Validator {
101101
}
102102

103103
// Enforce that coroutine-closure layouts are identical.
104-
if let Some(layout) = body.coroutine_layout()
104+
if let Some(layout) = body.coroutine_layout_raw()
105105
&& let Some(by_move_body) = body.coroutine_by_move_body()
106-
&& let Some(by_move_layout) = by_move_body.coroutine_layout()
106+
&& let Some(by_move_layout) = by_move_body.coroutine_layout_raw()
107107
{
108-
if layout != by_move_layout {
109-
// If this turns out not to be true, please let compiler-errors know.
110-
// It is possible to support, but requires some changes to the layout
111-
// computation code.
108+
// FIXME(async_closures): We could do other validation here?
109+
if layout.variant_fields.len() != by_move_layout.variant_fields.len() {
112110
cfg_checker.fail(
113111
Location::START,
114112
format!(
115-
"Coroutine layout differs from by-move coroutine layout:\n\
113+
"Coroutine layout has different number of variant fields from \
114+
by-move coroutine layout:\n\
116115
layout: {layout:#?}\n\
117116
by_move_layout: {by_move_layout:#?}",
118117
),
@@ -715,13 +714,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
715714
// args of the coroutine. Otherwise, we prefer to use this body
716715
// since we may be in the process of computing this MIR in the
717716
// first place.
718-
let gen_body = if def_id == self.caller_body.source.def_id() {
719-
self.caller_body
717+
let layout = if def_id == self.caller_body.source.def_id() {
718+
// FIXME: This is not right for async closures.
719+
self.caller_body.coroutine_layout_raw()
720720
} else {
721-
self.tcx.optimized_mir(def_id)
721+
self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty())
722722
};
723723

724-
let Some(layout) = gen_body.coroutine_layout() else {
724+
let Some(layout) = layout else {
725725
self.fail(
726726
location,
727727
format!("No coroutine layout for {parent_ty:?}"),

‎compiler/rustc_interface/src/tests.rs

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -315,30 +315,39 @@ fn test_search_paths_tracking_hash_different_order() {
315315
json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
316316
};
317317

318+
let push = |opts: &mut Options, search_path| {
319+
opts.search_paths.push(SearchPath::from_cli_opt(
320+
"not-a-sysroot".as_ref(),
321+
&opts.target_triple,
322+
&early_dcx,
323+
search_path,
324+
));
325+
};
326+
318327
// Reference
319-
v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
320-
v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
321-
v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
322-
v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
323-
v1.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
324-
325-
v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
326-
v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
327-
v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
328-
v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
329-
v2.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
330-
331-
v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
332-
v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
333-
v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
334-
v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
335-
v3.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
336-
337-
v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "all=mno"));
338-
v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "native=abc"));
339-
v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "crate=def"));
340-
v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "dependency=ghi"));
341-
v4.search_paths.push(SearchPath::from_cli_opt(&early_dcx, "framework=jkl"));
328+
push(&mut v1, "native=abc");
329+
push(&mut v1, "crate=def");
330+
push(&mut v1, "dependency=ghi");
331+
push(&mut v1, "framework=jkl");
332+
push(&mut v1, "all=mno");
333+
334+
push(&mut v2, "native=abc");
335+
push(&mut v2, "dependency=ghi");
336+
push(&mut v2, "crate=def");
337+
push(&mut v2, "framework=jkl");
338+
push(&mut v2, "all=mno");
339+
340+
push(&mut v3, "crate=def");
341+
push(&mut v3, "framework=jkl");
342+
push(&mut v3, "native=abc");
343+
push(&mut v3, "dependency=ghi");
344+
push(&mut v3, "all=mno");
345+
346+
push(&mut v4, "all=mno");
347+
push(&mut v4, "native=abc");
348+
push(&mut v4, "crate=def");
349+
push(&mut v4, "dependency=ghi");
350+
push(&mut v4, "framework=jkl");
342351

343352
assert_same_hash(&v1, &v2);
344353
assert_same_hash(&v1, &v3);

‎compiler/rustc_middle/src/mir/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,9 @@ impl<'tcx> Body<'tcx> {
652652
self.coroutine.as_ref().and_then(|coroutine| coroutine.resume_ty)
653653
}
654654

655+
/// Prefer going through [`TyCtxt::coroutine_layout`] rather than using this directly.
655656
#[inline]
656-
pub fn coroutine_layout(&self) -> Option<&CoroutineLayout<'tcx>> {
657+
pub fn coroutine_layout_raw(&self) -> Option<&CoroutineLayout<'tcx>> {
657658
self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_layout.as_ref())
658659
}
659660

‎compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ fn dump_matched_mir_node<'tcx, F>(
126126
Some(promoted) => write!(file, "::{promoted:?}`")?,
127127
}
128128
writeln!(file, " {disambiguator} {pass_name}")?;
129-
if let Some(ref layout) = body.coroutine_layout() {
129+
if let Some(ref layout) = body.coroutine_layout_raw() {
130130
writeln!(file, "/* coroutine_layout = {layout:#?} */")?;
131131
}
132132
writeln!(file)?;

‎compiler/rustc_middle/src/ty/mod.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub use rustc_target::abi::{ReprFlags, ReprOptions};
6060
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
6161
pub use vtable::*;
6262

63+
use std::assert_matches::assert_matches;
6364
use std::fmt::Debug;
6465
use std::hash::{Hash, Hasher};
6566
use std::marker::PhantomData;
@@ -1826,8 +1827,40 @@ impl<'tcx> TyCtxt<'tcx> {
18261827

18271828
/// Returns layout of a coroutine. Layout might be unavailable if the
18281829
/// coroutine is tainted by errors.
1829-
pub fn coroutine_layout(self, def_id: DefId) -> Option<&'tcx CoroutineLayout<'tcx>> {
1830-
self.optimized_mir(def_id).coroutine_layout()
1830+
///
1831+
/// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
1832+
/// e.g. `args.as_coroutine().kind_ty()`.
1833+
pub fn coroutine_layout(
1834+
self,
1835+
def_id: DefId,
1836+
coroutine_kind_ty: Ty<'tcx>,
1837+
) -> Option<&'tcx CoroutineLayout<'tcx>> {
1838+
let mir = self.optimized_mir(def_id);
1839+
// Regular coroutine
1840+
if coroutine_kind_ty.is_unit() {
1841+
mir.coroutine_layout_raw()
1842+
} else {
1843+
// If we have a `Coroutine` that comes from an coroutine-closure,
1844+
// then it may be a by-move or by-ref body.
1845+
let ty::Coroutine(_, identity_args) =
1846+
*self.type_of(def_id).instantiate_identity().kind()
1847+
else {
1848+
unreachable!();
1849+
};
1850+
let identity_kind_ty = identity_args.as_coroutine().kind_ty();
1851+
// If the types differ, then we must be getting the by-move body of
1852+
// a by-ref coroutine.
1853+
if identity_kind_ty == coroutine_kind_ty {
1854+
mir.coroutine_layout_raw()
1855+
} else {
1856+
assert_matches!(coroutine_kind_ty.to_opt_closure_kind(), Some(ClosureKind::FnOnce));
1857+
assert_matches!(
1858+
identity_kind_ty.to_opt_closure_kind(),
1859+
Some(ClosureKind::Fn | ClosureKind::FnMut)
1860+
);
1861+
mir.coroutine_by_move_body().unwrap().coroutine_layout_raw()
1862+
}
1863+
}
18311864
}
18321865

18331866
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.

‎compiler/rustc_middle/src/ty/sty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,8 @@ impl<'tcx> CoroutineArgs<'tcx> {
694694
#[inline]
695695
pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
696696
// FIXME requires optimized MIR
697-
FIRST_VARIANT..tcx.coroutine_layout(def_id).unwrap().variant_fields.next_index()
697+
FIRST_VARIANT
698+
..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index()
698699
}
699700

700701
/// The discriminant for the given variant. Panics if the `variant_index` is
@@ -754,7 +755,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
754755
def_id: DefId,
755756
tcx: TyCtxt<'tcx>,
756757
) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
757-
let layout = tcx.coroutine_layout(def_id).unwrap();
758+
let layout = tcx.coroutine_layout(def_id, self.kind_ty()).unwrap();
758759
layout.variant_fields.iter().map(move |variant| {
759760
variant.iter().map(move |field| {
760761
ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)

‎compiler/rustc_mir_transform/src/unreachable_prop.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ pub struct UnreachablePropagation;
1414
impl MirPass<'_> for UnreachablePropagation {
1515
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
1616
// Enable only under -Zmir-opt-level=2 as this can make programs less debuggable.
17-
18-
// FIXME(#116171) Coverage gets confused by MIR passes that can remove all
19-
// coverage statements from an instrumented function. This pass can be
20-
// re-enabled when coverage codegen is robust against that happening.
21-
sess.mir_opt_level() >= 2 && !sess.instrument_coverage()
17+
sess.mir_opt_level() >= 2
2218
}
2319

2420
fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {

‎compiler/rustc_session/src/config.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,11 +2795,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27952795
let debuginfo = select_debuginfo(matches, &cg);
27962796
let debuginfo_compression = unstable_opts.debuginfo_compression;
27972797

2798-
let mut search_paths = vec![];
2799-
for s in &matches.opt_strs("L") {
2800-
search_paths.push(SearchPath::from_cli_opt(early_dcx, s));
2801-
}
2802-
28032798
let libs = parse_libs(early_dcx, matches);
28042799

28052800
let test = matches.opt_present("test");
@@ -2848,6 +2843,11 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
28482843
candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
28492844
};
28502845

2846+
let mut search_paths = vec![];
2847+
for s in &matches.opt_strs("L") {
2848+
search_paths.push(SearchPath::from_cli_opt(&sysroot, &target_triple, early_dcx, s));
2849+
}
2850+
28512851
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
28522852
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
28532853
});

‎compiler/rustc_session/src/search_paths.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::filesearch::make_target_lib_path;
22
use crate::EarlyDiagCtxt;
3+
use rustc_target::spec::TargetTriple;
34
use std::path::{Path, PathBuf};
45

56
#[derive(Clone, Debug)]
@@ -46,7 +47,12 @@ impl PathKind {
4647
}
4748

4849
impl SearchPath {
49-
pub fn from_cli_opt(early_dcx: &EarlyDiagCtxt, path: &str) -> Self {
50+
pub fn from_cli_opt(
51+
sysroot: &Path,
52+
triple: &TargetTriple,
53+
early_dcx: &EarlyDiagCtxt,
54+
path: &str,
55+
) -> Self {
5056
let (kind, path) = if let Some(stripped) = path.strip_prefix("native=") {
5157
(PathKind::Native, stripped)
5258
} else if let Some(stripped) = path.strip_prefix("crate=") {
@@ -60,12 +66,17 @@ impl SearchPath {
6066
} else {
6167
(PathKind::All, path)
6268
};
63-
if path.is_empty() {
69+
let dir = match path.strip_prefix("@RUSTC_BUILTIN") {
70+
Some(stripped) => {
71+
make_target_lib_path(sysroot, triple.triple()).join("builtin").join(stripped)
72+
}
73+
None => PathBuf::from(path),
74+
};
75+
if dir.as_os_str().is_empty() {
6476
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
6577
early_dcx.early_fatal("empty search path given via `-L`");
6678
}
6779

68-
let dir = PathBuf::from(path);
6980
Self::new(kind, dir)
7081
}
7182

‎compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn target() -> Target {
1919
stack_probes: StackProbeType::Inline,
2020
supported_sanitizers: SanitizerSet::ADDRESS
2121
| SanitizerSet::CFI
22+
| SanitizerSet::KCFI
2223
| SanitizerSet::LEAK
2324
| SanitizerSet::MEMORY
2425
| SanitizerSet::MEMTAG

‎compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub fn target() -> Target {
1010
base.static_position_independent_executables = true;
1111
base.supported_sanitizers = SanitizerSet::ADDRESS
1212
| SanitizerSet::CFI
13+
| SanitizerSet::KCFI
1314
| SanitizerSet::DATAFLOW
1415
| SanitizerSet::LEAK
1516
| SanitizerSet::MEMORY

‎compiler/rustc_ty_utils/src/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ fn coroutine_layout<'tcx>(
745745
let tcx = cx.tcx;
746746
let instantiate_field = |ty: Ty<'tcx>| EarlyBinder::bind(ty).instantiate(tcx, args);
747747

748-
let Some(info) = tcx.coroutine_layout(def_id) else {
748+
let Some(info) = tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()) else {
749749
return Err(error(cx, LayoutError::Unknown(ty)));
750750
};
751751
let (ineligible_locals, assignments) = coroutine_saved_local_eligibility(info);
@@ -1072,7 +1072,7 @@ fn variant_info_for_coroutine<'tcx>(
10721072
return (vec![], None);
10731073
};
10741074

1075-
let coroutine = cx.tcx.optimized_mir(def_id).coroutine_layout().unwrap();
1075+
let coroutine = cx.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()).unwrap();
10761076
let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
10771077

10781078
let mut upvars_size = Size::ZERO;

‎library/alloc/src/collections/btree/map/entry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
354354
// SAFETY: There is no tree yet so no reference to it exists.
355355
let map = unsafe { self.dormant_map.awaken() };
356356
let mut root = NodeRef::new_leaf(self.alloc.clone());
357-
let val_ptr = root.borrow_mut().push(self.key, value) as *mut V;
357+
let val_ptr = root.borrow_mut().push(self.key, value);
358358
map.root = Some(root.forget_type());
359359
map.length = 1;
360360
val_ptr

‎library/alloc/src/ffi/c_str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl CString {
408408
fn strlen(s: *const c_char) -> usize;
409409
}
410410
let len = strlen(ptr) + 1; // Including the NUL byte
411-
let slice = slice::from_raw_parts_mut(ptr, len as usize);
411+
let slice = slice::from_raw_parts_mut(ptr, len);
412412
CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
413413
}
414414
}

‎library/alloc/src/slice.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,9 @@ impl<T> [T] {
511511
while m > 0 {
512512
// `buf.extend(buf)`:
513513
unsafe {
514-
ptr::copy_nonoverlapping(
514+
ptr::copy_nonoverlapping::<T>(
515515
buf.as_ptr(),
516-
(buf.as_mut_ptr() as *mut T).add(buf.len()),
516+
(buf.as_mut_ptr()).add(buf.len()),
517517
buf.len(),
518518
);
519519
// `buf` has capacity of `self.len() * n`.
@@ -532,9 +532,9 @@ impl<T> [T] {
532532
// `buf.extend(buf[0 .. rem_len])`:
533533
unsafe {
534534
// This is non-overlapping since `2^expn > rem`.
535-
ptr::copy_nonoverlapping(
535+
ptr::copy_nonoverlapping::<T>(
536536
buf.as_ptr(),
537-
(buf.as_mut_ptr() as *mut T).add(buf.len()),
537+
(buf.as_mut_ptr()).add(buf.len()),
538538
rem_len,
539539
);
540540
// `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).

‎library/alloc/src/task.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
148148
unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
149149
unsafe { Arc::increment_strong_count(waker as *const W) };
150150
RawWaker::new(
151-
waker as *const (),
151+
waker,
152152
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
153153
)
154154
}
@@ -320,7 +320,7 @@ fn local_raw_waker<W: LocalWake + 'static>(waker: Rc<W>) -> RawWaker {
320320
unsafe fn clone_waker<W: LocalWake + 'static>(waker: *const ()) -> RawWaker {
321321
unsafe { Rc::increment_strong_count(waker as *const W) };
322322
RawWaker::new(
323-
waker as *const (),
323+
waker,
324324
&RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
325325
)
326326
}

‎library/std/src/sys_common/net.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ where
107107
pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
108108
match storage.ss_family as c_int {
109109
c::AF_INET => {
110-
assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
110+
assert!(len >= mem::size_of::<c::sockaddr_in>());
111111
Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
112112
*(storage as *const _ as *const c::sockaddr_in)
113113
})))
114114
}
115115
c::AF_INET6 => {
116-
assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
116+
assert!(len >= mem::size_of::<c::sockaddr_in6>());
117117
Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
118118
*(storage as *const _ as *const c::sockaddr_in6)
119119
})))

‎src/librustdoc/config.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,6 @@ impl Options {
460460
&matches.free[0]
461461
});
462462

463-
let libs =
464-
matches.opt_strs("L").iter().map(|s| SearchPath::from_cli_opt(early_dcx, s)).collect();
465463
let externs = parse_externs(early_dcx, matches, &unstable_opts);
466464
let extern_html_root_urls = match parse_extern_html_roots(matches) {
467465
Ok(ex) => ex,
@@ -625,6 +623,20 @@ impl Options {
625623
}
626624

627625
let target = parse_target_triple(early_dcx, matches);
626+
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
627+
628+
let sysroot = match &maybe_sysroot {
629+
Some(s) => s.clone(),
630+
None => {
631+
rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot")
632+
}
633+
};
634+
635+
let libs = matches
636+
.opt_strs("L")
637+
.iter()
638+
.map(|s| SearchPath::from_cli_opt(&sysroot, &target, early_dcx, s))
639+
.collect();
628640

629641
let show_coverage = matches.opt_present("show-coverage");
630642

@@ -653,7 +665,6 @@ impl Options {
653665
let bin_crate = crate_types.contains(&CrateType::Executable);
654666
let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
655667
let playground_url = matches.opt_str("playground-url");
656-
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
657668
let module_sorting = if matches.opt_present("sort-modules-by-appearance") {
658669
ModuleSorting::DeclarationOrder
659670
} else {

‎src/librustdoc/html/render/print_item.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,6 +1728,8 @@ fn item_variants(
17281728
}
17291729
w.write_str("</h3></section>");
17301730

1731+
write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4));
1732+
17311733
let heading_and_fields = match &variant_data.kind {
17321734
clean::VariantKind::Struct(s) => {
17331735
// If there is no field to display, no need to add the heading.
@@ -1789,8 +1791,6 @@ fn item_variants(
17891791
}
17901792
w.write_str("</div>");
17911793
}
1792-
1793-
write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4));
17941794
}
17951795
write!(w, "</div>");
17961796
}

‎src/tools/compiletest/src/header.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
827827
"needs-sanitizer-cfi",
828828
"needs-sanitizer-dataflow",
829829
"needs-sanitizer-hwaddress",
830+
"needs-sanitizer-kcfi",
830831
"needs-sanitizer-leak",
831832
"needs-sanitizer-memory",
832833
"needs-sanitizer-memtag",

‎tests/coverage/unreachable.cov-map

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ Number of expressions: 0
1414
Number of file 0 mappings: 1
1515
- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 37)
1616

17-
Function name: unreachable::unreachable_intrinsic
18-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 01, 2c]
17+
Function name: unreachable::unreachable_intrinsic (unused)
18+
Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 2c]
1919
Number of files: 1
2020
- file 0 => global file 1
2121
Number of expressions: 0
2222
Number of file 0 mappings: 1
23-
- Code(Counter(0)) at (prev + 22, 1) to (start + 1, 44)
23+
- Code(Zero) at (prev + 22, 1) to (start + 1, 44)
2424

‎tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
//
66
// This checks that the reified function pointer will have the expected alias set at its call-site.
77

8-
//@ needs-sanitizer-cfi
8+
//@ revisions: cfi kcfi
99
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
1010
//@ only-linux
11-
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
12-
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
11+
//@ [cfi] needs-sanitizer-cfi
12+
//@ [kcfi] needs-sanitizer-kcfi
13+
//@ compile-flags: -C target-feature=-crt-static
14+
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
15+
//@ [cfi] compile-flags: -Z sanitizer=cfi
16+
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
1317
//@ run-pass
1418

1519
pub fn main() {

‎tests/ui/sanitizer/cfi-complex-receiver.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22
// * Arc<dyn Foo> as for custom receivers
33
// * &dyn Bar<T=Baz> for type constraints
44

5-
//@ needs-sanitizer-cfi
5+
//@ revisions: cfi kcfi
66
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
77
//@ only-linux
8-
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
9-
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
8+
//@ [cfi] needs-sanitizer-cfi
9+
//@ [kcfi] needs-sanitizer-kcfi
10+
//@ compile-flags: -C target-feature=-crt-static
11+
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
12+
//@ [cfi] compile-flags: -Z sanitizer=cfi
13+
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
1014
//@ run-pass
1115

1216
use std::sync::Arc;

‎tests/ui/sanitizer/cfi-self-ref.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
// Check that encoding self-referential types works with #[repr(transparent)]
22

3-
//@ needs-sanitizer-cfi
3+
//@ revisions: cfi kcfi
44
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
55
//@ only-linux
6-
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
7-
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
6+
//@ [cfi] needs-sanitizer-cfi
7+
//@ [kcfi] needs-sanitizer-kcfi
8+
//@ compile-flags: -C target-feature=-crt-static
9+
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
10+
//@ [cfi] compile-flags: -Z sanitizer=cfi
11+
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
812
//@ run-pass
913

1014
use std::marker::PhantomData;

‎tests/ui/sanitizer/cfi-virtual-auto.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
// Tests that calling a trait object method on a trait object with additional auto traits works.
22

3-
//@ needs-sanitizer-cfi
3+
//@ revisions: cfi kcfi
44
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
55
//@ only-linux
6-
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
7-
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
6+
//@ [cfi] needs-sanitizer-cfi
7+
//@ [kcfi] needs-sanitizer-kcfi
8+
//@ compile-flags: -C target-feature=-crt-static
9+
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
10+
//@ [cfi] compile-flags: -Z sanitizer=cfi
11+
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
812
//@ run-pass
913

1014
trait Foo {

0 commit comments

Comments
 (0)
Please sign in to comment.