Skip to content

Commit bce89b6

Browse files
committed
Auto merge of #152230 - JonathanBrouwer:rollup-de59XEq, r=JonathanBrouwer
Rollup of 6 pull requests Successful merges: - #151590 (cmse: don't use `BackendRepr` when checking return type) - #151945 (feat: Add `NonZero::<T>::from_str_radix`) - #152000 (Fix ICE in normalizing inherent associated consts with `#[type_const]`) - #152192 (Always use Xcode-provided Clang in macOS CI) - #152196 (bootstrap: Remove `ShouldRun::paths`) - #152222 (Re-add TaKO8Ki to triagebot review queue)
2 parents 55bfca7 + 4ae29f9 commit bce89b6

40 files changed

Lines changed: 489 additions & 185 deletions

File tree

compiler/rustc_abi/src/layout/ty.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,19 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
290290
/// function call isn't allowed (a.k.a. `va_list`).
291291
///
292292
/// This function handles transparent types automatically.
293-
pub fn pass_indirectly_in_non_rustic_abis<C>(mut self, cx: &C) -> bool
293+
pub fn pass_indirectly_in_non_rustic_abis<C>(self, cx: &C) -> bool
294+
where
295+
Ty: TyAbiInterface<'a, C> + Copy,
296+
{
297+
let base = self.peel_transparent_wrappers(cx);
298+
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base)
299+
}
300+
301+
/// Recursively peel away transparent wrappers, returning the inner value.
302+
///
303+
/// The return value is not `repr(transparent)` and/or does
304+
/// not have a non-1zst field.
305+
pub fn peel_transparent_wrappers<C>(mut self, cx: &C) -> Self
294306
where
295307
Ty: TyAbiInterface<'a, C> + Copy,
296308
{
@@ -300,7 +312,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
300312
self = field;
301313
}
302314

303-
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self)
315+
self
304316
}
305317

306318
/// Finds the one field that is not a 1-ZST.

compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use rustc_abi::{BackendRepr, ExternAbi, Float, Integer, Primitive, Scalar};
1+
use rustc_abi::ExternAbi;
22
use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err};
33
use rustc_hir::{self as hir, HirId};
44
use rustc_middle::bug;
5-
use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
5+
use rustc_middle::ty::layout::{LayoutCx, LayoutError, TyAndLayout};
66
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
77
use rustc_span::Span;
88

@@ -150,34 +150,30 @@ fn is_valid_cmse_output<'tcx>(
150150

151151
let typing_env = ty::TypingEnv::fully_monomorphized();
152152
let layout = tcx.layout_of(typing_env.as_query_input(return_type))?;
153+
let layout_cx = LayoutCx::new(tcx, typing_env);
153154

154-
if !is_valid_cmse_output_layout(layout) {
155+
if !is_valid_cmse_output_layout(layout_cx, layout) {
155156
dcx.emit_err(errors::CmseOutputStackSpill { span: fn_decl.output.span(), abi });
156157
}
157158

158159
Ok(())
159160
}
160161

161162
/// Returns whether the output will fit into the available registers
162-
fn is_valid_cmse_output_layout<'tcx>(layout: TyAndLayout<'tcx>) -> bool {
163+
fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) -> bool {
163164
let size = layout.layout.size().bytes();
164165

165166
if size <= 4 {
166167
return true;
167-
} else if size > 8 {
168+
} else if size != 8 {
168169
return false;
169170
}
170171

171-
// Accept scalar 64-bit types.
172-
let BackendRepr::Scalar(scalar) = layout.layout.backend_repr else {
173-
return false;
174-
};
175-
176-
let Scalar::Initialized { value, .. } = scalar else {
177-
return false;
178-
};
179-
180-
matches!(value, Primitive::Int(Integer::I64, _) | Primitive::Float(Float::F64))
172+
// Accept (transparently wrapped) scalar 64-bit primitives.
173+
matches!(
174+
layout.peel_transparent_wrappers(&cx).ty.kind(),
175+
ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64)
176+
)
181177
}
182178

183179
fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@ use crate::method::{self, MethodCallee};
4545
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
4646

4747
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
48+
/// Transform generic args for inherent associated type constants (IACs).
49+
///
50+
/// IACs have a different generic parameter structure than regular associated constants:
51+
/// - Regular assoc const: parent (impl) generic params + own generic params
52+
/// - IAC (type_const): Self type + own generic params
53+
pub(crate) fn transform_args_for_inherent_type_const(
54+
&self,
55+
def_id: DefId,
56+
args: GenericArgsRef<'tcx>,
57+
) -> GenericArgsRef<'tcx> {
58+
let tcx = self.tcx;
59+
if !tcx.is_type_const(def_id) {
60+
return args;
61+
}
62+
let Some(assoc_item) = tcx.opt_associated_item(def_id) else {
63+
return args;
64+
};
65+
if !matches!(assoc_item.container, ty::AssocContainer::InherentImpl) {
66+
return args;
67+
}
68+
69+
let impl_def_id = assoc_item.container_id(tcx);
70+
let generics = tcx.generics_of(def_id);
71+
let impl_args = &args[..generics.parent_count];
72+
let self_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
73+
// Build new args: [Self, own_args...]
74+
let own_args = &args[generics.parent_count..];
75+
tcx.mk_args_from_iter(
76+
std::iter::once(ty::GenericArg::from(self_ty)).chain(own_args.iter().copied()),
77+
)
78+
}
79+
4880
/// Produces warning on the given node, if the current point in the
4981
/// function is unreachable, and there hasn't been another warning.
5082
pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
@@ -1281,8 +1313,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12811313
)
12821314
});
12831315

1316+
let args_for_user_type = if let Res::Def(DefKind::AssocConst, def_id) = res {
1317+
self.transform_args_for_inherent_type_const(def_id, args_raw)
1318+
} else {
1319+
args_raw
1320+
};
1321+
12841322
// First, store the "user args" for later.
1285-
self.write_user_type_annotation_from_args(hir_id, def_id, args_raw, user_self_ty);
1323+
self.write_user_type_annotation_from_args(hir_id, def_id, args_for_user_type, user_self_ty);
12861324

12871325
// Normalize only after registering type annotations.
12881326
let args = self.normalize(span, args_raw);
@@ -1322,6 +1360,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13221360
}
13231361

13241362
debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_instantiated);
1363+
1364+
let args = if let Res::Def(DefKind::AssocConst, def_id) = res {
1365+
self.transform_args_for_inherent_type_const(def_id, args)
1366+
} else {
1367+
args
1368+
};
1369+
13251370
self.write_args(hir_id, args);
13261371

13271372
(ty_instantiated, res)

compiler/rustc_middle/src/ty/context.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2920,12 +2920,15 @@ impl<'tcx> TyCtxt<'tcx> {
29202920
) -> bool {
29212921
let generics = self.generics_of(def_id);
29222922

2923-
// IATs themselves have a weird arg setup (self + own args), but nested items *in* IATs
2924-
// (namely: opaques, i.e. ATPITs) do not.
2925-
let own_args = if !nested
2926-
&& let DefKind::AssocTy = self.def_kind(def_id)
2927-
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
2928-
{
2923+
// IATs and IACs (inherent associated types/consts with #[type_const]) themselves have a
2924+
// weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e.
2925+
// ATPITs) do not.
2926+
let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy)
2927+
&& matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false });
2928+
let is_inherent_assoc_type_const = matches!(self.def_kind(def_id), DefKind::AssocConst)
2929+
&& matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false })
2930+
&& self.is_type_const(def_id);
2931+
let own_args = if !nested && (is_inherent_assoc_ty || is_inherent_assoc_type_const) {
29292932
if generics.own_params.len() + 1 != args.len() {
29302933
return false;
29312934
}
@@ -2967,9 +2970,12 @@ impl<'tcx> TyCtxt<'tcx> {
29672970
/// and print out the args if not.
29682971
pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
29692972
if cfg!(debug_assertions) && !self.check_args_compatible(def_id, args) {
2970-
if let DefKind::AssocTy = self.def_kind(def_id)
2971-
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
2972-
{
2973+
let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy)
2974+
&& matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false });
2975+
let is_inherent_assoc_type_const = matches!(self.def_kind(def_id), DefKind::AssocConst)
2976+
&& matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false })
2977+
&& self.is_type_const(def_id);
2978+
if is_inherent_assoc_ty || is_inherent_assoc_type_const {
29732979
bug!(
29742980
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
29752981
self.def_path_str(def_id),

compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_hir::def::DefKind;
12
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
23
use rustc_infer::traits::Obligation;
34
use rustc_middle::traits::query::NoSolution;
@@ -96,6 +97,26 @@ fn relate_mir_and_user_args<'tcx>(
9697
let tcx = ocx.infcx.tcx;
9798
let cause = ObligationCause::dummy_with_span(span);
9899

100+
// For IACs, the user args are in the format [SelfTy, GAT_args...] but type_of expects [impl_args..., GAT_args...].
101+
// We need to infer the impl args by equating the impl's self type with the user-provided self type.
102+
let is_inherent_assoc_const = tcx.def_kind(def_id) == DefKind::AssocConst
103+
&& tcx.def_kind(tcx.parent(def_id)) == DefKind::Impl { of_trait: false }
104+
&& tcx.is_type_const(def_id);
105+
106+
let args = if is_inherent_assoc_const {
107+
let impl_def_id = tcx.parent(def_id);
108+
let impl_args = ocx.infcx.fresh_args_for_item(span, impl_def_id);
109+
let impl_self_ty =
110+
ocx.normalize(&cause, param_env, tcx.type_of(impl_def_id).instantiate(tcx, impl_args));
111+
let user_self_ty = ocx.normalize(&cause, param_env, args[0].expect_ty());
112+
ocx.eq(&cause, param_env, impl_self_ty, user_self_ty)?;
113+
114+
let gat_args = &args[1..];
115+
tcx.mk_args_from_iter(impl_args.iter().chain(gat_args.iter().copied()))
116+
} else {
117+
args
118+
};
119+
99120
let ty = tcx.type_of(def_id).instantiate(tcx, args);
100121
let ty = ocx.normalize(&cause, param_env, ty);
101122
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);

library/core/src/num/nonzero.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,16 +1240,78 @@ macro_rules! nonzero_integer {
12401240
// So the result cannot be zero.
12411241
unsafe { Self::new_unchecked(self.get().saturating_pow(other)) }
12421242
}
1243+
1244+
/// Parses a non-zero integer from a string slice with digits in a given base.
1245+
///
1246+
/// The string is expected to be an optional
1247+
#[doc = sign_dependent_expr!{
1248+
$signedness ?
1249+
if signed {
1250+
" `+` or `-` "
1251+
}
1252+
if unsigned {
1253+
" `+` "
1254+
}
1255+
}]
1256+
/// sign followed by only digits. Leading and trailing non-digit characters (including
1257+
/// whitespace) represent an error. Underscores (which are accepted in Rust literals)
1258+
/// also represent an error.
1259+
///
1260+
/// Digits are a subset of these characters, depending on `radix`:
1261+
///
1262+
/// - `0-9`
1263+
/// - `a-z`
1264+
/// - `A-Z`
1265+
///
1266+
/// # Panics
1267+
///
1268+
/// This method panics if `radix` is not in the range from 2 to 36.
1269+
///
1270+
/// # Examples
1271+
///
1272+
/// Basic usage:
1273+
///
1274+
/// ```
1275+
/// #![feature(nonzero_from_str_radix)]
1276+
///
1277+
/// # use std::num::NonZero;
1278+
/// #
1279+
/// # fn main() { test().unwrap(); }
1280+
/// # fn test() -> Option<()> {
1281+
#[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::from_str_radix(\"A\", 16), Ok(NonZero::new(10)?));")]
1282+
/// # Some(())
1283+
/// # }
1284+
/// ```
1285+
///
1286+
/// Trailing space returns error:
1287+
///
1288+
/// ```
1289+
/// #![feature(nonzero_from_str_radix)]
1290+
///
1291+
/// # use std::num::NonZero;
1292+
/// #
1293+
#[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_str_radix(\"1 \", 10).is_err());")]
1294+
/// ```
1295+
#[unstable(feature = "nonzero_from_str_radix", issue = "152193")]
1296+
#[inline]
1297+
pub const fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
1298+
let n = match <$Int>::from_str_radix(src, radix) {
1299+
Ok(n) => n,
1300+
Err(err) => return Err(err),
1301+
};
1302+
if let Some(n) = Self::new(n) {
1303+
Ok(n)
1304+
} else {
1305+
Err(ParseIntError { kind: IntErrorKind::Zero })
1306+
}
1307+
}
12431308
}
12441309

12451310
#[stable(feature = "nonzero_parse", since = "1.35.0")]
12461311
impl FromStr for NonZero<$Int> {
12471312
type Err = ParseIntError;
12481313
fn from_str(src: &str) -> Result<Self, Self::Err> {
1249-
Self::new(<$Int>::from_str_radix(src, 10)?)
1250-
.ok_or(ParseIntError {
1251-
kind: IntErrorKind::Zero
1252-
})
1314+
Self::from_str_radix(src, 10)
12531315
}
12541316
}
12551317

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
#![feature(new_range_api)]
9191
#![feature(next_index)]
9292
#![feature(non_exhaustive_omitted_patterns_lint)]
93+
#![feature(nonzero_from_str_radix)]
9394
#![feature(numfmt)]
9495
#![feature(one_sided_range)]
9596
#![feature(option_reduce)]

library/coretests/tests/nonzero.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,41 @@ fn test_from_signed_nonzero() {
124124
assert_eq!(num, 1i32);
125125
}
126126

127+
#[test]
128+
fn test_from_str_radix() {
129+
assert_eq!(NonZero::<u8>::from_str_radix("123", 10), Ok(NonZero::new(123).unwrap()));
130+
assert_eq!(NonZero::<u8>::from_str_radix("1001", 2), Ok(NonZero::new(9).unwrap()));
131+
assert_eq!(NonZero::<u8>::from_str_radix("123", 8), Ok(NonZero::new(83).unwrap()));
132+
assert_eq!(NonZero::<u16>::from_str_radix("123", 16), Ok(NonZero::new(291).unwrap()));
133+
assert_eq!(NonZero::<u16>::from_str_radix("ffff", 16), Ok(NonZero::new(65535).unwrap()));
134+
assert_eq!(NonZero::<u8>::from_str_radix("z", 36), Ok(NonZero::new(35).unwrap()));
135+
assert_eq!(
136+
NonZero::<u8>::from_str_radix("0", 10).err().map(|e| e.kind().clone()),
137+
Some(IntErrorKind::Zero)
138+
);
139+
assert_eq!(
140+
NonZero::<u8>::from_str_radix("-1", 10).err().map(|e| e.kind().clone()),
141+
Some(IntErrorKind::InvalidDigit)
142+
);
143+
assert_eq!(
144+
NonZero::<i8>::from_str_radix("-129", 10).err().map(|e| e.kind().clone()),
145+
Some(IntErrorKind::NegOverflow)
146+
);
147+
assert_eq!(
148+
NonZero::<u8>::from_str_radix("257", 10).err().map(|e| e.kind().clone()),
149+
Some(IntErrorKind::PosOverflow)
150+
);
151+
152+
assert_eq!(
153+
NonZero::<u8>::from_str_radix("Z", 10).err().map(|e| e.kind().clone()),
154+
Some(IntErrorKind::InvalidDigit)
155+
);
156+
assert_eq!(
157+
NonZero::<u8>::from_str_radix("_", 2).err().map(|e| e.kind().clone()),
158+
Some(IntErrorKind::InvalidDigit)
159+
);
160+
}
161+
127162
#[test]
128163
fn test_from_str() {
129164
assert_eq!("123".parse::<NonZero<u8>>(), Ok(NonZero::new(123).unwrap()));

src/bootstrap/src/core/build_steps/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ macro_rules! tool_check_step {
706706
const IS_HOST: bool = true;
707707

708708
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
709-
run.paths(&[ $path, $( $alt_path ),* ])
709+
run.path($path) $( .path( $alt_path ) )*
710710
}
711711

712712
fn is_default_step(_builder: &Builder<'_>) -> bool {

src/bootstrap/src/core/build_steps/test.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,7 +3156,7 @@ impl Step for CrateRustdoc {
31563156
const IS_HOST: bool = true;
31573157

31583158
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3159-
run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3159+
run.path("src/librustdoc").path("src/tools/rustdoc")
31603160
}
31613161

31623162
fn is_default_step(_builder: &Builder<'_>) -> bool {
@@ -3817,7 +3817,7 @@ impl Step for CodegenCranelift {
38173817
const IS_HOST: bool = true;
38183818

38193819
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3820-
run.paths(&["compiler/rustc_codegen_cranelift"])
3820+
run.path("compiler/rustc_codegen_cranelift")
38213821
}
38223822

38233823
fn is_default_step(_builder: &Builder<'_>) -> bool {
@@ -3938,7 +3938,7 @@ impl Step for CodegenGCC {
39383938
const IS_HOST: bool = true;
39393939

39403940
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3941-
run.paths(&["compiler/rustc_codegen_gcc"])
3941+
run.path("compiler/rustc_codegen_gcc")
39423942
}
39433943

39443944
fn is_default_step(_builder: &Builder<'_>) -> bool {

0 commit comments

Comments
 (0)