Skip to content

Commit 7ffc697

Browse files
committed
Auto merge of rust-lang#120309 - fmease:rollup-kr7wqy6, r=fmease
Rollup of 9 pull requests Successful merges: - rust-lang#114764 ([style edition 2024] Combine all delimited exprs as last argument) - rust-lang#118326 (Add `NonZero*::count_ones`) - rust-lang#119460 (coverage: Never emit improperly-ordered coverage regions) - rust-lang#119616 (Add a new `wasm32-wasi-preview2` target) - rust-lang#120185 (coverage: Don't instrument `#[automatically_derived]` functions) - rust-lang#120265 (Remove no-system-llvm) - rust-lang#120284 (privacy: Refactor top-level visiting in `TypePrivacyVisitor`) - rust-lang#120285 (Remove extra # from url in suggestion) - rust-lang#120299 (Add mw to review rotation and add some owner assignments) r? `@ghost` `@rustbot` modify labels: rollup
2 parents cd6d8f2 + 8325f3d commit 7ffc697

File tree

64 files changed

+614
-408
lines changed

Some content is hidden

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

64 files changed

+614
-408
lines changed

compiler/rustc_mir_transform/src/coverage/mod.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ fn make_code_region(
329329
start_line = source_map.doctest_offset_line(&file.name, start_line);
330330
end_line = source_map.doctest_offset_line(&file.name, end_line);
331331

332-
Some(CodeRegion {
332+
check_code_region(CodeRegion {
333333
file_name,
334334
start_line: start_line as u32,
335335
start_col: start_col as u32,
@@ -338,6 +338,39 @@ fn make_code_region(
338338
})
339339
}
340340

341+
/// If `llvm-cov` sees a code region that is improperly ordered (end < start),
342+
/// it will immediately exit with a fatal error. To prevent that from happening,
343+
/// discard regions that are improperly ordered, or might be interpreted in a
344+
/// way that makes them improperly ordered.
345+
fn check_code_region(code_region: CodeRegion) -> Option<CodeRegion> {
346+
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
347+
348+
// Line/column coordinates are supposed to be 1-based. If we ever emit
349+
// coordinates of 0, `llvm-cov` might misinterpret them.
350+
let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0);
351+
// Coverage mappings use the high bit of `end_col` to indicate that a
352+
// region is actually a "gap" region, so make sure it's unset.
353+
let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0;
354+
// If a region is improperly ordered (end < start), `llvm-cov` will exit
355+
// with a fatal error, which is inconvenient for users and hard to debug.
356+
let is_ordered = (start_line, start_col) <= (end_line, end_col);
357+
358+
if all_nonzero && end_col_has_high_bit_unset && is_ordered {
359+
Some(code_region)
360+
} else {
361+
debug!(
362+
?code_region,
363+
?all_nonzero,
364+
?end_col_has_high_bit_unset,
365+
?is_ordered,
366+
"Skipping code region that would be misinterpreted or rejected by LLVM"
367+
);
368+
// If this happens in a debug build, ICE to make it easier to notice.
369+
debug_assert!(false, "Improper code region: {code_region:?}");
370+
None
371+
}
372+
}
373+
341374
fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
342375
// Only instrument functions, methods, and closures (not constants since they are evaluated
343376
// at compile time by Miri).
@@ -351,7 +384,18 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
351384
return false;
352385
}
353386

387+
// Don't instrument functions with `#[automatically_derived]` on their
388+
// enclosing impl block, on the assumption that most users won't care about
389+
// coverage for derived impls.
390+
if let Some(impl_of) = tcx.impl_of_method(def_id.to_def_id())
391+
&& tcx.is_automatically_derived(impl_of)
392+
{
393+
trace!("InstrumentCoverage skipped for {def_id:?} (automatically derived)");
394+
return false;
395+
}
396+
354397
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
398+
trace!("InstrumentCoverage skipped for {def_id:?} (`#[coverage(off)]`)");
355399
return false;
356400
}
357401

compiler/rustc_privacy/src/lib.rs

+27-63
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ use rustc_hir::def::{DefKind, Res};
2424
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
2525
use rustc_hir::intravisit::{self, Visitor};
2626
use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind};
27-
use rustc_middle::bug;
2827
use rustc_middle::hir::nested_filter;
2928
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
3029
use rustc_middle::query::Providers;
3130
use rustc_middle::ty::GenericArgs;
3231
use rustc_middle::ty::{self, Const, GenericParamDefKind};
3332
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
33+
use rustc_middle::{bug, span_bug};
3434
use rustc_session::lint;
3535
use rustc_span::hygiene::Transparency;
3636
use rustc_span::symbol::{kw, sym, Ident};
@@ -1064,29 +1064,22 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
10641064

10651065
struct TypePrivacyVisitor<'tcx> {
10661066
tcx: TyCtxt<'tcx>,
1067+
module_def_id: LocalModDefId,
10671068
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
1068-
current_item: LocalDefId,
10691069
span: Span,
10701070
}
10711071

10721072
impl<'tcx> TypePrivacyVisitor<'tcx> {
1073-
/// Gets the type-checking results for the current body.
1074-
/// As this will ICE if called outside bodies, only call when working with
1075-
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
1076-
#[track_caller]
1077-
fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
1078-
self.maybe_typeck_results
1079-
.expect("`TypePrivacyVisitor::typeck_results` called outside of body")
1080-
}
1081-
10821073
fn item_is_accessible(&self, did: DefId) -> bool {
1083-
self.tcx.visibility(did).is_accessible_from(self.current_item, self.tcx)
1074+
self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
10841075
}
10851076

10861077
// Take node-id of an expression or pattern and check its type for privacy.
10871078
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
10881079
self.span = span;
1089-
let typeck_results = self.typeck_results();
1080+
let typeck_results = self
1081+
.maybe_typeck_results
1082+
.unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body"));
10901083
let result: ControlFlow<()> = try {
10911084
self.visit(typeck_results.node_type(id))?;
10921085
self.visit(typeck_results.node_args(id))?;
@@ -1107,35 +1100,13 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
11071100
}
11081101

11091102
impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
1110-
type NestedFilter = nested_filter::All;
1111-
1112-
/// We want to visit items in the context of their containing
1113-
/// module and so forth, so supply a crate for doing a deep walk.
1114-
fn nested_visit_map(&mut self) -> Self::Map {
1115-
self.tcx.hir()
1116-
}
1117-
1118-
fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
1119-
// Don't visit nested modules, since we run a separate visitor walk
1120-
// for each module in `effective_visibilities`
1121-
}
1122-
1123-
fn visit_nested_body(&mut self, body: hir::BodyId) {
1103+
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
11241104
let old_maybe_typeck_results =
1125-
self.maybe_typeck_results.replace(self.tcx.typeck_body(body));
1126-
let body = self.tcx.hir().body(body);
1127-
self.visit_body(body);
1105+
self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
1106+
self.visit_body(self.tcx.hir().body(body_id));
11281107
self.maybe_typeck_results = old_maybe_typeck_results;
11291108
}
11301109

1131-
fn visit_generic_arg(&mut self, generic_arg: &'tcx hir::GenericArg<'tcx>) {
1132-
match generic_arg {
1133-
hir::GenericArg::Type(t) => self.visit_ty(t),
1134-
hir::GenericArg::Infer(inf) => self.visit_infer(inf),
1135-
hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {}
1136-
}
1137-
}
1138-
11391110
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {
11401111
self.span = hir_ty.span;
11411112
if let Some(typeck_results) = self.maybe_typeck_results {
@@ -1163,19 +1134,19 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
11631134
return;
11641135
}
11651136
} else {
1166-
// We don't do anything for const infers here.
1137+
// FIXME: check types of const infers here.
11671138
}
11681139
} else {
1169-
bug!("visit_infer without typeck_results");
1140+
span_bug!(self.span, "`hir::InferArg` outside of a body");
11701141
}
11711142
intravisit::walk_inf(self, inf);
11721143
}
11731144

11741145
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) {
11751146
self.span = trait_ref.path.span;
1176-
if self.maybe_typeck_results.is_none() {
1177-
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
1178-
// The traits' privacy in bodies is already checked as a part of trait object types.
1147+
if self.maybe_typeck_results.is_some() {
1148+
// Privacy of traits in bodies is checked as a part of trait object types.
1149+
} else {
11791150
let bounds = rustc_hir_analysis::hir_trait_to_predicates(
11801151
self.tcx,
11811152
trait_ref,
@@ -1223,7 +1194,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
12231194
hir::ExprKind::MethodCall(segment, ..) => {
12241195
// Method calls have to be checked specially.
12251196
self.span = segment.ident.span;
1226-
if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) {
1197+
let typeck_results = self
1198+
.maybe_typeck_results
1199+
.unwrap_or_else(|| span_bug!(self.span, "`hir::Expr` outside of a body"));
1200+
if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
12271201
if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
12281202
return;
12291203
}
@@ -1251,9 +1225,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
12511225
Res::Def(kind, def_id) => Some((kind, def_id)),
12521226
_ => None,
12531227
},
1254-
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
1255-
.maybe_typeck_results
1256-
.and_then(|typeck_results| typeck_results.type_dependent_def(id)),
1228+
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
1229+
match self.maybe_typeck_results {
1230+
Some(typeck_results) => typeck_results.type_dependent_def(id),
1231+
// FIXME: Check type-relative associated types in signatures.
1232+
None => None,
1233+
}
1234+
}
12571235
};
12581236
let def = def.filter(|(kind, _)| {
12591237
matches!(
@@ -1307,15 +1285,6 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
13071285

13081286
intravisit::walk_local(self, local);
13091287
}
1310-
1311-
// Check types in item interfaces.
1312-
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
1313-
let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
1314-
let old_maybe_typeck_results = self.maybe_typeck_results.take();
1315-
intravisit::walk_item(self, item);
1316-
self.maybe_typeck_results = old_maybe_typeck_results;
1317-
self.current_item = orig_current_item;
1318-
}
13191288
}
13201289

13211290
impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
@@ -1785,13 +1754,8 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
17851754

17861755
// Check privacy of explicitly written types and traits as well as
17871756
// inferred types of expressions and patterns.
1788-
let mut visitor = TypePrivacyVisitor {
1789-
tcx,
1790-
maybe_typeck_results: None,
1791-
current_item: module_def_id.to_local_def_id(),
1792-
span,
1793-
};
1794-
intravisit::walk_mod(&mut visitor, module, hir_id);
1757+
let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
1758+
tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor);
17951759
}
17961760

17971761
fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1793,6 +1793,7 @@ symbols! {
17931793
warn,
17941794
wasm_abi,
17951795
wasm_import_module,
1796+
wasm_preview2,
17961797
wasm_target_feature,
17971798
while_let,
17981799
windows,

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,7 @@ supported_targets! {
15741574
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
15751575
("wasm32-unknown-unknown", wasm32_unknown_unknown),
15761576
("wasm32-wasi", wasm32_wasi),
1577+
("wasm32-wasi-preview2", wasm32_wasi_preview2),
15771578
("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads),
15781579
("wasm64-unknown-unknown", wasm64_unknown_unknown),
15791580

compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@
7272
//! best we can with this target. Don't start relying on too much here unless
7373
//! you know what you're getting in to!
7474
75-
use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target};
75+
use crate::spec::{base, crt_objects, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, Target};
7676

7777
pub fn target() -> Target {
7878
let mut options = base::wasm::options();
7979

80+
options.families = cvs!["wasm", "wasi"];
8081
options.os = "wasi".into();
8182

8283
options.add_pre_link_args(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//! The `wasm32-wasi-preview2` target is the next evolution of the
2+
//! wasm32-wasi target. While the wasi specification is still under
3+
//! active development, the {review 2 iteration is considered an "island
4+
//! of stability" that should allow users to rely on it indefinitely.
5+
//!
6+
//! The `wasi` target is a proposal to define a standardized set of WebAssembly
7+
//! component imports that allow it to interoperate with the host system in a
8+
//! standardized way. This set of imports is intended to empower WebAssembly
9+
//! binaries with host capabilities such as filesystem access, network access, etc.
10+
//!
11+
//! Wasi Preview 2 relies on the WebAssembly component model which is an extension of
12+
//! the core WebAssembly specification which allows interoperability between WebAssembly
13+
//! modules (known as "components") through high-level, shared-nothing APIs instead of the
14+
//! low-level, shared-everything linear memory model of the core WebAssembly specification.
15+
//!
16+
//! You can see more about wasi at <https://wasi.dev> and the component model at
17+
//! <https://github.com/WebAssembly/component-model>.
18+
19+
use crate::spec::crt_objects;
20+
use crate::spec::LinkSelfContainedDefault;
21+
use crate::spec::{base, Target};
22+
23+
pub fn target() -> Target {
24+
let mut options = base::wasm::options();
25+
26+
options.os = "wasi".into();
27+
options.env = "preview2".into();
28+
options.linker = Some("wasm-component-ld".into());
29+
30+
options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
31+
options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
32+
33+
// FIXME: Figure out cases in which WASM needs to link with a native toolchain.
34+
options.link_self_contained = LinkSelfContainedDefault::True;
35+
36+
// Right now this is a bit of a workaround but we're currently saying that
37+
// the target by default has a static crt which we're taking as a signal
38+
// for "use the bundled crt". If that's turned off then the system's crt
39+
// will be used, but this means that default usage of this target doesn't
40+
// need an external compiler but it's still interoperable with an external
41+
// compiler if configured correctly.
42+
options.crt_static_default = true;
43+
options.crt_static_respected = true;
44+
45+
// Allow `+crt-static` to create a "cdylib" output which is just a wasm file
46+
// without a main function.
47+
options.crt_static_allows_dylibs = true;
48+
49+
// WASI's `sys::args::init` function ignores its arguments; instead,
50+
// `args::args()` makes the WASI API calls itself.
51+
options.main_needs_argc_argv = false;
52+
53+
// And, WASI mangles the name of "main" to distinguish between different
54+
// signatures.
55+
options.entry_name = "__main_void".into();
56+
57+
Target {
58+
llvm_target: "wasm32-unknown-unknown".into(),
59+
pointer_width: 32,
60+
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
61+
arch: "wasm32".into(),
62+
options,
63+
}
64+
}

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3155,7 +3155,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
31553155
} else {
31563156
// FIXME: we may suggest array::repeat instead
31573157
err.help("consider using `core::array::from_fn` to initialize the array");
3158-
err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information");
3158+
err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information");
31593159
}
31603160

31613161
if self.tcx.sess.is_nightly_build()

library/core/src/num/nonzero.rs

+37
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,43 @@ macro_rules! nonzero_integer {
288288
unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
289289
}
290290

291+
/// Returns the number of ones in the binary representation of `self`.
292+
///
293+
/// # Examples
294+
///
295+
/// Basic usage:
296+
///
297+
/// ```
298+
/// #![feature(non_zero_count_ones)]
299+
/// # fn main() { test().unwrap(); }
300+
/// # fn test() -> Option<()> {
301+
#[doc = concat!("# use std::num::{self, ", stringify!($Ty), "};")]
302+
///
303+
/// let one = num::NonZeroU32::new(1)?;
304+
/// let three = num::NonZeroU32::new(3)?;
305+
#[doc = concat!("let a = ", stringify!($Ty), "::new(0b100_0000)?;")]
306+
#[doc = concat!("let b = ", stringify!($Ty), "::new(0b100_0011)?;")]
307+
///
308+
/// assert_eq!(a.count_ones(), one);
309+
/// assert_eq!(b.count_ones(), three);
310+
/// # Some(())
311+
/// # }
312+
/// ```
313+
///
314+
#[unstable(feature = "non_zero_count_ones", issue = "120287")]
315+
#[rustc_const_unstable(feature = "non_zero_count_ones", issue = "120287")]
316+
#[doc(alias = "popcount")]
317+
#[doc(alias = "popcnt")]
318+
#[must_use = "this returns the result of the operation, \
319+
without modifying the original"]
320+
#[inline(always)]
321+
pub const fn count_ones(self) -> NonZeroU32 {
322+
// SAFETY:
323+
// `self` is non-zero, which means it has at least one bit set, which means
324+
// that the result of `count_ones` is non-zero.
325+
unsafe { NonZeroU32::new_unchecked(self.get().count_ones()) }
326+
}
327+
291328
nonzero_integer_signedness_dependent_methods! {
292329
Self = $Ty,
293330
Primitive = $signedness $Int,

0 commit comments

Comments
 (0)