Skip to content

Commit a3af208

Browse files
committed
Auto merge of #130016 - matthiaskrgr:rollup-fopistw, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #129021 (Check WF of source type's signature on fn pointer cast) - #129781 (Make `./x.py <cmd> compiler/<crate>` aware of the crate's features) - #129963 (Inaccurate `{Path,OsStr}::to_string_lossy()` documentation) - #129969 (Make `Ty::boxed_ty` return an `Option`) - #129995 (Remove wasm32-wasip2's tier 2 status from release notes) - #130013 (coverage: Count await when the Future is immediately ready ) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d678b81 + 11d5614 commit a3af208

Some content is hidden

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

47 files changed

+395
-138
lines changed

RELEASES.md

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ Compiler
3434
- [Add Tier 3 `std` Xtensa targets:](https://github.com/rust-lang/rust/pull/126380/) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf`
3535
- [Add Tier 3 i686 Redox OS target:](https://github.com/rust-lang/rust/pull/126192/) `i686-unknown-redox`
3636
- [Promote `arm64ec-pc-windows-msvc` to Tier 2.](https://github.com/rust-lang/rust/pull/126039/)
37-
- [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/)
3837
- [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/126298/)
3938
- [Enable full tools and profiler for LoongArch Linux targets.](https://github.com/rust-lang/rust/pull/127078/)
4039
- [Unconditionally warn on usage of `wasm32-wasi`.](https://github.com/rust-lang/rust/pull/126662/) (see compatibility note below)

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
662662
// `&dyn Trait`
663663
ty::Ref(_, ty, _) if ty.is_trait() => true,
664664
// `Box<dyn Trait>`
665-
_ if ty.is_box() && ty.boxed_ty().is_trait() => {
665+
_ if ty.boxed_ty().is_some_and(Ty::is_trait) => {
666666
true
667667
}
668+
668669
// `dyn Trait`
669670
_ if ty.is_trait() => true,
670671
// Anything else.

compiler/rustc_borrowck/src/diagnostics/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
345345
variant_index: Option<VariantIdx>,
346346
including_tuple_field: IncludingTupleField,
347347
) -> Option<String> {
348-
if ty.is_box() {
348+
if let Some(boxed_ty) = ty.boxed_ty() {
349349
// If the type is a box, the field is described from the boxed type
350-
self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field)
350+
self.describe_field_from_ty(boxed_ty, field, variant_index, including_tuple_field)
351351
} else {
352352
match *ty.kind() {
353353
ty::Adt(def, _) => {

compiler/rustc_borrowck/src/type_check/mod.rs

+64-7
Original file line numberDiff line numberDiff line change
@@ -1979,19 +1979,76 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19791979

19801980
match cast_kind {
19811981
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
1982-
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
1982+
let src_sig = op.ty(body, tcx).fn_sig(tcx);
1983+
1984+
// HACK: This shouldn't be necessary... We can remove this when we actually
1985+
// get binders with where clauses, then elaborate implied bounds into that
1986+
// binder, and implement a higher-ranked subtyping algorithm that actually
1987+
// respects these implied bounds.
1988+
//
1989+
// This protects against the case where we are casting from a higher-ranked
1990+
// fn item to a non-higher-ranked fn pointer, where the cast throws away
1991+
// implied bounds that would've needed to be checked at the call site. This
1992+
// only works when we're casting to a non-higher-ranked fn ptr, since
1993+
// placeholders in the target signature could have untracked implied
1994+
// bounds, resulting in incorrect errors.
1995+
//
1996+
// We check that this signature is WF before subtyping the signature with
1997+
// the target fn sig.
1998+
if src_sig.has_bound_regions()
1999+
&& let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
2000+
&& let target_sig = target_fn_tys.with(target_hdr)
2001+
&& let Some(target_sig) = target_sig.no_bound_vars()
2002+
{
2003+
let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
2004+
span,
2005+
BoundRegionConversionTime::HigherRankedType,
2006+
src_sig,
2007+
);
2008+
let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
2009+
self.prove_predicate(
2010+
ty::ClauseKind::WellFormed(src_ty.into()),
2011+
location.to_locations(),
2012+
ConstraintCategory::Cast { unsize_to: None },
2013+
);
2014+
2015+
let src_ty = self.normalize(src_ty, location);
2016+
if let Err(terr) = self.sub_types(
2017+
src_ty,
2018+
*ty,
2019+
location.to_locations(),
2020+
ConstraintCategory::Cast { unsize_to: None },
2021+
) {
2022+
span_mirbug!(
2023+
self,
2024+
rvalue,
2025+
"equating {:?} with {:?} yields {:?}",
2026+
target_sig,
2027+
src_sig,
2028+
terr
2029+
);
2030+
};
2031+
}
2032+
2033+
let src_ty = Ty::new_fn_ptr(tcx, src_sig);
2034+
// HACK: We want to assert that the signature of the source fn is
2035+
// well-formed, because we don't enforce that via the WF of FnDef
2036+
// types normally. This should be removed when we improve the tracking
2037+
// of implied bounds of fn signatures.
2038+
self.prove_predicate(
2039+
ty::ClauseKind::WellFormed(src_ty.into()),
2040+
location.to_locations(),
2041+
ConstraintCategory::Cast { unsize_to: None },
2042+
);
19832043

19842044
// The type that we see in the fcx is like
19852045
// `foo::<'a, 'b>`, where `foo` is the path to a
19862046
// function definition. When we extract the
19872047
// signature, it comes from the `fn_sig` query,
19882048
// and hence may contain unnormalized results.
1989-
let fn_sig = self.normalize(fn_sig, location);
1990-
1991-
let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
1992-
2049+
let src_ty = self.normalize(src_ty, location);
19932050
if let Err(terr) = self.sub_types(
1994-
ty_fn_ptr_from,
2051+
src_ty,
19952052
*ty,
19962053
location.to_locations(),
19972054
ConstraintCategory::Cast { unsize_to: None },
@@ -2000,7 +2057,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20002057
self,
20012058
rvalue,
20022059
"equating {:?} with {:?} yields {:?}",
2003-
ty_fn_ptr_from,
2060+
src_ty,
20042061
ty,
20052062
terr
20062063
);

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
456456
if def.is_box()
457457
&& args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) =>
458458
{
459-
build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
459+
build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id)
460460
}
461461
ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id),
462462
ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),

compiler/rustc_const_eval/src/interpret/call.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
189189
ty::Ref(_, ty, _) => *ty,
190190
ty::RawPtr(ty, _) => *ty,
191191
// We only accept `Box` with the default allocator.
192-
_ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
192+
_ if ty.is_box_global(*self.tcx) => ty.expect_boxed_ty(),
193193
_ => return Ok(None),
194194
}))
195195
};

compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6363
// Instead, the problem is that the array-into_iter hack will no longer
6464
// apply in Rust 2021.
6565
(ARRAY_INTO_ITER, "2021")
66-
} else if self_ty.is_box()
67-
&& self_ty.boxed_ty().is_slice()
66+
} else if self_ty.boxed_ty().is_some_and(Ty::is_slice)
6867
&& !span.at_least_rust_2024()
6968
{
7069
// In this case, it wasn't really a prelude addition that was the problem.

compiler/rustc_hir_typeck/src/method/probe.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1485,8 +1485,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14851485

14861486
// Some trait methods are excluded for boxed slices before 2024.
14871487
// (`boxed_slice.into_iter()` wants a slice iterator for compatibility.)
1488-
if self_ty.is_box()
1489-
&& self_ty.boxed_ty().is_slice()
1488+
if self_ty.boxed_ty().is_some_and(Ty::is_slice)
14901489
&& !method_name.span.at_least_rust_2024()
14911490
{
14921491
let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());

compiler/rustc_lint/src/shadowed_into_iter.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
9494
fn is_ref_to_array(ty: Ty<'_>) -> bool {
9595
if let ty::Ref(_, pointee_ty, _) = *ty.kind() { pointee_ty.is_array() } else { false }
9696
}
97-
fn is_boxed_slice(ty: Ty<'_>) -> bool {
98-
ty.is_box() && ty.boxed_ty().is_slice()
99-
}
10097
fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool {
10198
if let ty::Ref(_, pointee_ty, _) = *ty.kind() {
102-
is_boxed_slice(pointee_ty)
99+
pointee_ty.boxed_ty().is_some_and(Ty::is_slice)
103100
} else {
104101
false
105102
}
@@ -119,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
119116
.iter()
120117
.copied()
121118
.take_while(|ty| !is_ref_to_boxed_slice(*ty))
122-
.position(|ty| is_boxed_slice(ty))
119+
.position(|ty| ty.boxed_ty().is_some_and(Ty::is_slice))
123120
{
124121
(BOXED_SLICE_INTO_ITER, "Box<[T]>", "2024", idx == 0)
125122
} else {

compiler/rustc_lint/src/types.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1304,8 +1304,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13041304

13051305
match *ty.kind() {
13061306
ty::Adt(def, args) => {
1307-
if def.is_box() && matches!(self.mode, CItemKind::Definition) {
1308-
if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
1307+
if let Some(boxed) = ty.boxed_ty()
1308+
&& matches!(self.mode, CItemKind::Definition)
1309+
{
1310+
if boxed.is_sized(tcx, self.cx.param_env) {
13091311
return FfiSafe;
13101312
} else {
13111313
return FfiUnsafe {

compiler/rustc_lint/src/unused.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
283283
}
284284

285285
match *ty.kind() {
286-
ty::Adt(..) if ty.is_box() => {
287-
let boxed_ty = ty.boxed_ty();
288-
is_ty_must_use(cx, boxed_ty, expr, span)
286+
ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => {
287+
is_ty_must_use(cx, boxed, expr, span)
289288
.map(|inner| MustUsePath::Boxed(Box::new(inner)))
290289
}
291290
ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {

compiler/rustc_middle/src/ty/layout.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1075,11 +1075,13 @@ where
10751075
// the raw pointer, so size and align are set to the boxed type, but `pointee.safe`
10761076
// will still be `None`.
10771077
if let Some(ref mut pointee) = result {
1078-
if offset.bytes() == 0 && this.ty.is_box() {
1078+
if offset.bytes() == 0
1079+
&& let Some(boxed_ty) = this.ty.boxed_ty()
1080+
{
10791081
debug_assert!(pointee.safe.is_none());
10801082
let optimize = tcx.sess.opts.optimize != OptLevel::No;
10811083
pointee.safe = Some(PointerKind::Box {
1082-
unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
1084+
unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()),
10831085
global: this.ty.is_box_global(tcx),
10841086
});
10851087
}

compiler/rustc_middle/src/ty/sty.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -1170,14 +1170,19 @@ impl<'tcx> Ty<'tcx> {
11701170
}
11711171
}
11721172

1173-
/// Panics if called on any type other than `Box<T>`.
1174-
pub fn boxed_ty(self) -> Ty<'tcx> {
1173+
pub fn boxed_ty(self) -> Option<Ty<'tcx>> {
11751174
match self.kind() {
1176-
Adt(def, args) if def.is_box() => args.type_at(0),
1177-
_ => bug!("`boxed_ty` is called on non-box type {:?}", self),
1175+
Adt(def, args) if def.is_box() => Some(args.type_at(0)),
1176+
_ => None,
11781177
}
11791178
}
11801179

1180+
/// Panics if called on any type other than `Box<T>`.
1181+
pub fn expect_boxed_ty(self) -> Ty<'tcx> {
1182+
self.boxed_ty()
1183+
.unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self))
1184+
}
1185+
11811186
/// A scalar type is one that denotes an atomic datum, with no sub-components.
11821187
/// (A RawPtr is scalar because it represents a non-managed pointer, so its
11831188
/// contents are abstract to rustc.)
@@ -1323,7 +1328,7 @@ impl<'tcx> Ty<'tcx> {
13231328
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
13241329
pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
13251330
match *self.kind() {
1326-
Adt(def, _) if def.is_box() => Some(self.boxed_ty()),
1331+
_ if let Some(boxed) = self.boxed_ty() => Some(boxed),
13271332
Ref(_, ty, _) => Some(ty),
13281333
RawPtr(ty, _) if explicit => Some(ty),
13291334
_ => None,

compiler/rustc_middle/src/ty/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ impl<'tcx> ExplicitSelf<'tcx> {
16281628
_ if is_self_ty(self_arg_ty) => ByValue,
16291629
ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl),
16301630
ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl),
1631-
ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox,
1631+
_ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox,
16321632
_ => Other,
16331633
}
16341634
}

compiler/rustc_mir_transform/src/coverage/spans.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::VecDeque;
33
use rustc_data_structures::captures::Captures;
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_middle::mir;
6-
use rustc_span::Span;
6+
use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
77
use tracing::{debug, debug_span, instrument};
88

99
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
@@ -25,7 +25,7 @@ pub(super) fn extract_refined_covspans(
2525

2626
// First, perform the passes that need macro information.
2727
covspans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb));
28-
remove_unwanted_macro_spans(&mut covspans);
28+
remove_unwanted_expansion_spans(&mut covspans);
2929
split_visible_macro_spans(&mut covspans);
3030

3131
// We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
@@ -76,18 +76,24 @@ pub(super) fn extract_refined_covspans(
7676
/// invocation, which is unhelpful. Keeping only the first such span seems to
7777
/// give better mappings, so remove the others.
7878
///
79+
/// Similarly, `await` expands to a branch on the discriminant of `Poll`, which
80+
/// leads to incorrect coverage if the `Future` is immediately ready (#98712).
81+
///
7982
/// (The input spans should be sorted in BCB dominator order, so that the
8083
/// retained "first" span is likely to dominate the others.)
81-
fn remove_unwanted_macro_spans(covspans: &mut Vec<SpanFromMir>) {
82-
let mut seen_macro_spans = FxHashSet::default();
84+
fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
85+
let mut deduplicated_spans = FxHashSet::default();
86+
8387
covspans.retain(|covspan| {
84-
// Ignore (retain) non-macro-expansion spans.
85-
if covspan.visible_macro.is_none() {
86-
return true;
88+
match covspan.expn_kind {
89+
// Retain only the first await-related or macro-expanded covspan with this span.
90+
Some(ExpnKind::Desugaring(kind)) if kind == DesugaringKind::Await => {
91+
deduplicated_spans.insert(covspan.span)
92+
}
93+
Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span),
94+
// Ignore (retain) other spans.
95+
_ => true,
8796
}
88-
89-
// Retain only the first macro-expanded covspan with this span.
90-
seen_macro_spans.insert(covspan.span)
9197
});
9298
}
9399

@@ -99,7 +105,9 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
99105
let mut extra_spans = vec![];
100106

101107
covspans.retain(|covspan| {
102-
let Some(visible_macro) = covspan.visible_macro else { return true };
108+
let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
109+
return true;
110+
};
103111

104112
let split_len = visible_macro.as_str().len() as u32 + 1;
105113
let (before, after) = covspan.span.split_at(split_len);
@@ -111,8 +119,8 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
111119
return true;
112120
}
113121

114-
extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb));
115-
extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb));
122+
extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
123+
extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
116124
false // Discard the original covspan that we just split.
117125
});
118126

0 commit comments

Comments
 (0)