Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c559c4a

Browse files
committed
Auto merge of #146224 - tgross35:rollup-1bgjms3, r=tgross35
Rollup of 5 pull requests Successful merges: - #144342 (add exact bitshifts) - #145709 (Fix LoongArch C function ABI when passing/returning structs containing floats) - #146152 (Unify and deduplicate algebraic float tests) - #146207 (std: Implement WASIp2-specific stdio routines) - #146217 (fix ICE when suggesting `::new`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents ad85bc5 + 8ff60a6 commit c559c4a

File tree

21 files changed

+798
-136
lines changed

21 files changed

+798
-136
lines changed

‎compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,12 +2585,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25852585
.filter(|item| item.is_fn() && !item.is_method())
25862586
.filter_map(|item| {
25872587
// Only assoc fns that return `Self`
2588-
let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
2589-
let ret_ty = fn_sig.output();
2590-
let ret_ty = self.tcx.normalize_erasing_late_bound_regions(
2591-
self.typing_env(self.param_env),
2592-
ret_ty,
2593-
);
2588+
let fn_sig = self
2589+
.tcx
2590+
.fn_sig(item.def_id)
2591+
.instantiate(self.tcx, self.fresh_args_for_item(span, item.def_id));
2592+
let ret_ty = self.tcx.instantiate_bound_regions_with_erased(fn_sig.output());
25942593
if !self.can_eq(self.param_env, ret_ty, adt_ty) {
25952594
return None;
25962595
}

‎compiler/rustc_target/src/callconv/loongarch.rs

Lines changed: 105 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ use crate::spec::HasTargetSpec;
88

99
#[derive(Copy, Clone)]
1010
enum RegPassKind {
11-
Float(Reg),
12-
Integer(Reg),
11+
Float{offset_from_start:Size,ty:Reg},
12+
Integer{offset_from_start:Size,ty:Reg},
1313
Unknown,
1414
}
1515

1616
#[derive(Copy, Clone)]
1717
enum FloatConv {
18-
FloatPair(Reg, Reg),
18+
FloatPair{first_ty:Reg, second_ty_offset_from_start:Size,second_ty:Reg},
1919
Float(Reg),
20-
MixedPair(Reg, Reg),
20+
MixedPair{first_ty:Reg, second_ty_offset_from_start:Size,second_ty:Reg},
2121
}
2222

2323
#[derive(Copy, Clone)]
@@ -37,6 +37,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
3737
flen: u64,
3838
field1_kind: &mut RegPassKind,
3939
field2_kind: &mut RegPassKind,
40+
offset_from_start: Size,
4041
) -> Result<(), CannotUseFpConv>
4142
where
4243
Ty: TyAbiInterface<'a, C> + Copy,
@@ -49,16 +50,16 @@ where
4950
}
5051
match (*field1_kind, *field2_kind) {
5152
(RegPassKind::Unknown, _) => {
52-
*field1_kind = RegPassKind::Integer(Reg {
53-
kind:RegKind::Integer,
54-
size: arg_layout.size,
55-
});
53+
*field1_kind = RegPassKind::Integer {
54+
offset_from_start,
55+
ty:Reg{kind:RegKind::Integer,size: arg_layout.size},
56+
};
5657
}
57-
(RegPassKind::Float(_), RegPassKind::Unknown) => {
58-
*field2_kind = RegPassKind::Integer(Reg {
59-
kind:RegKind::Integer,
60-
size: arg_layout.size,
61-
});
58+
(RegPassKind::Float{ .. }, RegPassKind::Unknown) => {
59+
*field2_kind = RegPassKind::Integer {
60+
offset_from_start,
61+
ty:Reg{kind:RegKind::Integer,size: arg_layout.size},
62+
};
6263
}
6364
_ => return Err(CannotUseFpConv),
6465
}
@@ -69,12 +70,16 @@ where
6970
}
7071
match (*field1_kind, *field2_kind) {
7172
(RegPassKind::Unknown, _) => {
72-
*field1_kind =
73-
RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size });
73+
*field1_kind = RegPassKind::Float {
74+
offset_from_start,
75+
ty: Reg { kind: RegKind::Float, size: arg_layout.size },
76+
};
7477
}
7578
(_, RegPassKind::Unknown) => {
76-
*field2_kind =
77-
RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size });
79+
*field2_kind = RegPassKind::Float {
80+
offset_from_start,
81+
ty: Reg { kind: RegKind::Float, size: arg_layout.size },
82+
};
7883
}
7984
_ => return Err(CannotUseFpConv),
8085
}
@@ -96,13 +101,14 @@ where
96101
flen,
97102
field1_kind,
98103
field2_kind,
104+
offset_from_start,
99105
);
100106
}
101107
return Err(CannotUseFpConv);
102108
}
103109
}
104110
FieldsShape::Array { count, .. } => {
105-
for _ in 0..count {
111+
for i in 0..count {
106112
let elem_layout = arg_layout.field(cx, 0);
107113
should_use_fp_conv_helper(
108114
cx,
@@ -111,6 +117,7 @@ where
111117
flen,
112118
field1_kind,
113119
field2_kind,
120+
offset_from_start + elem_layout.size * i,
114121
)?;
115122
}
116123
}
@@ -121,7 +128,15 @@ where
121128
}
122129
for i in arg_layout.fields.index_by_increasing_offset() {
123130
let field = arg_layout.field(cx, i);
124-
should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?;
131+
should_use_fp_conv_helper(
132+
cx,
133+
&field,
134+
xlen,
135+
flen,
136+
field1_kind,
137+
field2_kind,
138+
offset_from_start + arg_layout.fields.offset(i),
139+
)?;
125140
}
126141
}
127142
},
@@ -140,14 +155,52 @@ where
140155
{
141156
let mut field1_kind = RegPassKind::Unknown;
142157
let mut field2_kind = RegPassKind::Unknown;
143-
if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() {
158+
if should_use_fp_conv_helper(
159+
cx,
160+
arg,
161+
xlen,
162+
flen,
163+
&mut field1_kind,
164+
&mut field2_kind,
165+
Size::ZERO,
166+
)
167+
.is_err()
168+
{
144169
return None;
145170
}
146171
match (field1_kind, field2_kind) {
147-
(RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)),
148-
(RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)),
149-
(RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)),
150-
(RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)),
172+
(
173+
RegPassKind::Integer { offset_from_start, .. }
174+
| RegPassKind::Float { offset_from_start, .. },
175+
_,
176+
) if offset_from_start != Size::ZERO => {
177+
panic!("type {:?} has a first field with non-zero offset {offset_from_start:?}", arg.ty)
178+
}
179+
(
180+
RegPassKind::Integer { ty: first_ty, .. },
181+
RegPassKind::Float { offset_from_start, ty: second_ty },
182+
) => Some(FloatConv::MixedPair {
183+
first_ty,
184+
second_ty_offset_from_start: offset_from_start,
185+
second_ty,
186+
}),
187+
(
188+
RegPassKind::Float { ty: first_ty, .. },
189+
RegPassKind::Integer { offset_from_start, ty: second_ty },
190+
) => Some(FloatConv::MixedPair {
191+
first_ty,
192+
second_ty_offset_from_start: offset_from_start,
193+
second_ty,
194+
}),
195+
(
196+
RegPassKind::Float { ty: first_ty, .. },
197+
RegPassKind::Float { offset_from_start, ty: second_ty },
198+
) => Some(FloatConv::FloatPair {
199+
first_ty,
200+
second_ty_offset_from_start: offset_from_start,
201+
second_ty,
202+
}),
203+
(RegPassKind::Float { ty, .. }, RegPassKind::Unknown) => Some(FloatConv::Float(ty)),
151204
_ => None,
152205
}
153206
}
@@ -165,11 +218,19 @@ where
165218
FloatConv::Float(f) => {
166219
arg.cast_to(f);
167220
}
168-
FloatConv::FloatPair(l, r) => {
169-
arg.cast_to(CastTarget::pair(l, r));
221+
FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty } => {
222+
arg.cast_to(CastTarget::offset_pair(
223+
first_ty,
224+
second_ty_offset_from_start,
225+
second_ty,
226+
));
170227
}
171-
FloatConv::MixedPair(l, r) => {
172-
arg.cast_to(CastTarget::pair(l, r));
228+
FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty } => {
229+
arg.cast_to(CastTarget::offset_pair(
230+
first_ty,
231+
second_ty_offset_from_start,
232+
second_ty,
233+
));
173234
}
174235
}
175236
return false;
@@ -233,15 +294,27 @@ fn classify_arg<'a, Ty, C>(
233294
arg.cast_to(f);
234295
return;
235296
}
236-
Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => {
297+
Some(FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty })
298+
if *avail_fprs >= 2 =>
299+
{
237300
*avail_fprs -= 2;
238-
arg.cast_to(CastTarget::pair(l, r));
301+
arg.cast_to(CastTarget::offset_pair(
302+
first_ty,
303+
second_ty_offset_from_start,
304+
second_ty,
305+
));
239306
return;
240307
}
241-
Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => {
308+
Some(FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty })
309+
if *avail_fprs >= 1 && *avail_gprs >= 1 =>
310+
{
242311
*avail_gprs -= 1;
243312
*avail_fprs -= 1;
244-
arg.cast_to(CastTarget::pair(l, r));
313+
arg.cast_to(CastTarget::offset_pair(
314+
first_ty,
315+
second_ty_offset_from_start,
316+
second_ty,
317+
));
245318
return;
246319
}
247320
_ => (),

‎library/core/src/num/int_macros.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,66 @@ macro_rules! int_impl {
14131413
}
14141414
}
14151415

1416+
/// Exact shift left. Computes `self << rhs` as long as it can be reversed losslessly.
1417+
///
1418+
/// Returns `None` if any bits that would be shifted out differ from the resulting sign bit
1419+
/// or if `rhs` >=
1420+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1421+
/// Otherwise, returns `Some(self << rhs)`.
1422+
///
1423+
/// # Examples
1424+
///
1425+
/// ```
1426+
/// #![feature(exact_bitshifts)]
1427+
///
1428+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(4), Some(0x10));")]
1429+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 2), Some(1 << ", stringify!($SelfT), "::BITS - 2));")]
1430+
#[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
1431+
#[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 2), Some(-0x2 << ", stringify!($SelfT), "::BITS - 2));")]
1432+
#[doc = concat!("assert_eq!((-0x2", stringify!($SelfT), ").exact_shl(", stringify!($SelfT), "::BITS - 1), None);")]
1433+
/// ```
1434+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1435+
#[must_use = "this returns the result of the operation, \
1436+
without modifying the original"]
1437+
#[inline]
1438+
pub const fn exact_shl(self, rhs: u32) -> Option<$SelfT> {
1439+
if rhs < self.leading_zeros() || rhs < self.leading_ones() {
1440+
// SAFETY: rhs is checked above
1441+
Some(unsafe { self.unchecked_shl(rhs) })
1442+
} else {
1443+
None
1444+
}
1445+
}
1446+
1447+
/// Unchecked exact shift left. Computes `self << rhs`, assuming the operation can be
1448+
/// losslessly reversed and `rhs` cannot be larger than
1449+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1450+
///
1451+
/// # Safety
1452+
///
1453+
/// This results in undefined behavior when `rhs >= self.leading_zeros() && rhs >=
1454+
/// self.leading_ones()` i.e. when
1455+
#[doc = concat!("[`", stringify!($SelfT), "::exact_shl`]")]
1456+
/// would return `None`.
1457+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1458+
#[must_use = "this returns the result of the operation, \
1459+
without modifying the original"]
1460+
#[inline]
1461+
pub const unsafe fn unchecked_exact_shl(self, rhs: u32) -> $SelfT {
1462+
assert_unsafe_precondition!(
1463+
check_language_ub,
1464+
concat!(stringify!($SelfT), "::unchecked_exact_shl cannot shift out non-zero bits"),
1465+
(
1466+
zeros: u32 = self.leading_zeros(),
1467+
ones: u32 = self.leading_ones(),
1468+
rhs: u32 = rhs,
1469+
) => rhs < zeros || rhs < ones,
1470+
);
1471+
1472+
// SAFETY: this is guaranteed to be safe by the caller
1473+
unsafe { self.unchecked_shl(rhs) }
1474+
}
1475+
14161476
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
14171477
/// larger than or equal to the number of bits in `self`.
14181478
///
@@ -1534,6 +1594,63 @@ macro_rules! int_impl {
15341594
}
15351595
}
15361596

1597+
/// Exact shift right. Computes `self >> rhs` as long as it can be reversed losslessly.
1598+
///
1599+
/// Returns `None` if any non-zero bits would be shifted out or if `rhs` >=
1600+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1601+
/// Otherwise, returns `Some(self >> rhs)`.
1602+
///
1603+
/// # Examples
1604+
///
1605+
/// ```
1606+
/// #![feature(exact_bitshifts)]
1607+
///
1608+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(4), Some(0x1));")]
1609+
#[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".exact_shr(5), None);")]
1610+
/// ```
1611+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1612+
#[must_use = "this returns the result of the operation, \
1613+
without modifying the original"]
1614+
#[inline]
1615+
pub const fn exact_shr(self, rhs: u32) -> Option<$SelfT> {
1616+
if rhs <= self.trailing_zeros() && rhs < <$SelfT>::BITS {
1617+
// SAFETY: rhs is checked above
1618+
Some(unsafe { self.unchecked_shr(rhs) })
1619+
} else {
1620+
None
1621+
}
1622+
}
1623+
1624+
/// Unchecked exact shift right. Computes `self >> rhs`, assuming the operation can be
1625+
/// losslessly reversed and `rhs` cannot be larger than
1626+
#[doc = concat!("`", stringify!($SelfT), "::BITS`.")]
1627+
///
1628+
/// # Safety
1629+
///
1630+
/// This results in undefined behavior when `rhs > self.trailing_zeros() || rhs >=
1631+
#[doc = concat!(stringify!($SelfT), "::BITS`")]
1632+
/// i.e. when
1633+
#[doc = concat!("[`", stringify!($SelfT), "::exact_shr`]")]
1634+
/// would return `None`.
1635+
#[unstable(feature = "exact_bitshifts", issue = "144336")]
1636+
#[must_use = "this returns the result of the operation, \
1637+
without modifying the original"]
1638+
#[inline]
1639+
pub const unsafe fn unchecked_exact_shr(self, rhs: u32) -> $SelfT {
1640+
assert_unsafe_precondition!(
1641+
check_language_ub,
1642+
concat!(stringify!($SelfT), "::unchecked_exact_shr cannot shift out non-zero bits"),
1643+
(
1644+
zeros: u32 = self.trailing_zeros(),
1645+
bits: u32 = <$SelfT>::BITS,
1646+
rhs: u32 = rhs,
1647+
) => rhs <= zeros && rhs < bits,
1648+
);
1649+
1650+
// SAFETY: this is guaranteed to be safe by the caller
1651+
unsafe { self.unchecked_shr(rhs) }
1652+
}
1653+
15371654
/// Checked absolute value. Computes `self.abs()`, returning `None` if
15381655
/// `self == MIN`.
15391656
///

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /