Skip to content

Commit 53af067

Browse files
committed
Auto merge of #145236 - Zalathar:rollup-1ggbztv, r=Zalathar
Rollup of 7 pull requests Successful merges: - #143949 (Constify remaining traits/impls for `const_ops`) - #144330 (document assumptions about `Clone` and `Eq` traits) - #144350 (std: sys: io: io_slice: Add UEFI types) - #144558 (Point at the `Fn()` or `FnMut()` bound that coerced a closure, which caused a move error) - #145149 (Make config method invoke inside parse use dwn_ctx) - #145227 (Tweak spans providing type context on errors when involving macros) - #145228 (Remove unnecessary parentheses in `assert!`s) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 21a19c2 + fd7d724 commit 53af067

Some content is hidden

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

43 files changed

+2170
-586
lines changed

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use rustc_middle::bug;
99
use rustc_middle::mir::*;
1010
use rustc_middle::ty::{self, Ty, TyCtxt};
1111
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
12-
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
12+
use rustc_span::def_id::DefId;
13+
use rustc_span::{BytePos, DUMMY_SP, ExpnKind, MacroKind, Span};
1314
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
1415
use rustc_trait_selection::infer::InferCtxtExt;
1516
use tracing::debug;
@@ -507,12 +508,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
507508
);
508509

509510
let closure_span = tcx.def_span(def_id);
511+
510512
self.cannot_move_out_of(span, &place_description)
511513
.with_span_label(upvar_span, "captured outer variable")
512514
.with_span_label(
513515
closure_span,
514516
format!("captured by this `{closure_kind}` closure"),
515517
)
518+
.with_span_help(
519+
self.get_closure_bound_clause_span(*def_id),
520+
"`Fn` and `FnMut` closures require captured values to be able to be \
521+
consumed multiple times, but an `FnOnce` consume them only once",
522+
)
516523
}
517524
_ => {
518525
let source = self.borrowed_content_source(deref_base);
@@ -561,6 +568,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
561568
err
562569
}
563570

571+
fn get_closure_bound_clause_span(&self, def_id: DefId) -> Span {
572+
let tcx = self.infcx.tcx;
573+
let typeck_result = tcx.typeck(self.mir_def_id());
574+
// Check whether the closure is an argument to a call, if so,
575+
// get the instantiated where-bounds of that call.
576+
let closure_hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local());
577+
let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return DUMMY_SP };
578+
579+
let predicates = match parent.kind {
580+
hir::ExprKind::Call(callee, _) => {
581+
let Some(ty) = typeck_result.node_type_opt(callee.hir_id) else { return DUMMY_SP };
582+
let ty::FnDef(fn_def_id, args) = ty.kind() else { return DUMMY_SP };
583+
tcx.predicates_of(fn_def_id).instantiate(tcx, args)
584+
}
585+
hir::ExprKind::MethodCall(..) => {
586+
let Some((_, method)) = typeck_result.type_dependent_def(parent.hir_id) else {
587+
return DUMMY_SP;
588+
};
589+
let args = typeck_result.node_args(parent.hir_id);
590+
tcx.predicates_of(method).instantiate(tcx, args)
591+
}
592+
_ => return DUMMY_SP,
593+
};
594+
595+
// Check whether one of the where-bounds requires the closure to impl `Fn[Mut]`.
596+
for (pred, span) in predicates.predicates.iter().zip(predicates.spans.iter()) {
597+
if let Some(clause) = pred.as_trait_clause()
598+
&& let ty::Closure(clause_closure_def_id, _) = clause.self_ty().skip_binder().kind()
599+
&& *clause_closure_def_id == def_id
600+
&& (tcx.lang_items().fn_mut_trait() == Some(clause.def_id())
601+
|| tcx.lang_items().fn_trait() == Some(clause.def_id()))
602+
{
603+
// Found `<TyOfCapturingClosure as FnMut>`
604+
// We point at the `Fn()` or `FnMut()` bound that coerced the closure, which
605+
// could be changed to `FnOnce()` to avoid the move error.
606+
return *span;
607+
}
608+
}
609+
DUMMY_SP
610+
}
611+
564612
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) {
565613
match error {
566614
GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,17 +847,18 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
847847
self
848848
}
849849

850+
with_fn! { with_span_help,
850851
/// Prints the span with some help above it.
851852
/// This is like [`Diag::help()`], but it gets its own span.
852853
#[rustc_lint_diagnostics]
853-
pub fn span_help<S: Into<MultiSpan>>(
854+
pub fn span_help(
854855
&mut self,
855-
sp: S,
856+
sp: impl Into<MultiSpan>,
856857
msg: impl Into<SubdiagMessage>,
857858
) -> &mut Self {
858859
self.sub(Level::Help, msg, sp.into());
859860
self
860-
}
861+
} }
861862

862863
/// Disallow attaching suggestions to this diagnostic.
863864
/// Any suggestions attached e.g. with the `span_suggestion_*` methods

compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
698698
) {
699699
match (self.tcx.parent_hir_node(expr.hir_id), error) {
700700
(hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init: Some(init), .. }), _)
701-
if init.hir_id == expr.hir_id =>
701+
if init.hir_id == expr.hir_id && !ty.span.source_equal(init.span) =>
702702
{
703703
// Point at `let` assignment type.
704704
err.span_label(ty.span, "expected due to this");

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
459459
span,
460460
format!("this is an iterator with items of type `{}`", args.type_at(0)),
461461
);
462-
} else {
462+
} else if !span.overlaps(cause.span) {
463463
let expected_ty = self.tcx.short_string(expected_ty, err.long_ty_path());
464464
err.span_label(span, format!("this expression has type `{expected_ty}`"));
465465
}

library/core/src/clone.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,34 @@ mod uninit;
139139
/// // Note: With the manual implementations the above line will compile.
140140
/// ```
141141
///
142+
/// ## `Clone` and `PartialEq`/`Eq`
143+
/// `Clone` is intended for the duplication of objects. Consequently, when implementing
144+
/// both `Clone` and [`PartialEq`], the following property is expected to hold:
145+
/// ```text
146+
/// x == x -> x.clone() == x
147+
/// ```
148+
/// In other words, if an object compares equal to itself,
149+
/// its clone must also compare equal to the original.
150+
///
151+
/// For types that also implement [`Eq`] – for which `x == x` always holds –
152+
/// this implies that `x.clone() == x` must always be true.
153+
/// Standard library collections such as
154+
/// [`HashMap`], [`HashSet`], [`BTreeMap`], [`BTreeSet`] and [`BinaryHeap`]
155+
/// rely on their keys respecting this property for correct behavior.
156+
/// Furthermore, these collections require that cloning a key preserves the outcome of the
157+
/// [`Hash`] and [`Ord`] methods. Thankfully, this follows automatically from `x.clone() == x`
158+
/// if `Hash` and `Ord` are correctly implemented according to their own requirements.
159+
///
160+
/// When deriving both `Clone` and [`PartialEq`] using `#[derive(Clone, PartialEq)]`
161+
/// or when additionally deriving [`Eq`] using `#[derive(Clone, PartialEq, Eq)]`,
162+
/// then this property is automatically upheld – provided that it is satisfied by
163+
/// the underlying types.
164+
///
165+
/// Violating this property is a logic error. The behavior resulting from a logic error is not
166+
/// specified, but users of the trait must ensure that such logic errors do *not* result in
167+
/// undefined behavior. This means that `unsafe` code **must not** rely on this property
168+
/// being satisfied.
169+
///
142170
/// ## Additional implementors
143171
///
144172
/// In addition to the [implementors listed below][impls],
@@ -152,6 +180,11 @@ mod uninit;
152180
/// (even if the referent doesn't),
153181
/// while variables captured by mutable reference never implement `Clone`.
154182
///
183+
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
184+
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
185+
/// [`BTreeMap`]: ../../std/collections/struct.BTreeMap.html
186+
/// [`BTreeSet`]: ../../std/collections/struct.BTreeSet.html
187+
/// [`BinaryHeap`]: ../../std/collections/struct.BinaryHeap.html
155188
/// [impls]: #implementors
156189
#[stable(feature = "rust1", since = "1.0.0")]
157190
#[lang = "clone"]

library/core/src/internal_macros.rs

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
// implements the unary operator "op &T"
22
// based on "op T" where T is expected to be `Copy`able
33
macro_rules! forward_ref_unop {
4-
(impl $imp:ident, $method:ident for $t:ty) => {
5-
forward_ref_unop!(impl $imp, $method for $t,
6-
#[stable(feature = "rust1", since = "1.0.0")]);
7-
};
8-
(impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
9-
#[$attr]
10-
impl $imp for &$t {
4+
(impl $imp:ident, $method:ident for $t:ty, $(#[$attr:meta])+) => {
5+
$(#[$attr])+
6+
impl const $imp for &$t {
117
type Output = <$t as $imp>::Output;
128

139
#[inline]
@@ -21,13 +17,9 @@ macro_rules! forward_ref_unop {
2117
// implements binary operators "&T op U", "T op &U", "&T op &U"
2218
// based on "T op U" where T and U are expected to be `Copy`able
2319
macro_rules! forward_ref_binop {
24-
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
25-
forward_ref_binop!(impl $imp, $method for $t, $u,
26-
#[stable(feature = "rust1", since = "1.0.0")]);
27-
};
28-
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
29-
#[$attr]
30-
impl<'a> $imp<$u> for &'a $t {
20+
(impl $imp:ident, $method:ident for $t:ty, $u:ty, $(#[$attr:meta])+) => {
21+
$(#[$attr])+
22+
impl const $imp<$u> for &$t {
3123
type Output = <$t as $imp<$u>>::Output;
3224

3325
#[inline]
@@ -37,8 +29,8 @@ macro_rules! forward_ref_binop {
3729
}
3830
}
3931

40-
#[$attr]
41-
impl $imp<&$u> for $t {
32+
$(#[$attr])+
33+
impl const $imp<&$u> for $t {
4234
type Output = <$t as $imp<$u>>::Output;
4335

4436
#[inline]
@@ -48,8 +40,8 @@ macro_rules! forward_ref_binop {
4840
}
4941
}
5042

51-
#[$attr]
52-
impl $imp<&$u> for &$t {
43+
$(#[$attr])+
44+
impl const $imp<&$u> for &$t {
5345
type Output = <$t as $imp<$u>>::Output;
5446

5547
#[inline]
@@ -64,13 +56,9 @@ macro_rules! forward_ref_binop {
6456
// implements "T op= &U", based on "T op= U"
6557
// where U is expected to be `Copy`able
6658
macro_rules! forward_ref_op_assign {
67-
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
68-
forward_ref_op_assign!(impl $imp, $method for $t, $u,
69-
#[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
70-
};
71-
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
72-
#[$attr]
73-
impl $imp<&$u> for $t {
59+
(impl $imp:ident, $method:ident for $t:ty, $u:ty, $(#[$attr:meta])+) => {
60+
$(#[$attr])+
61+
impl const $imp<&$u> for $t {
7462
#[inline]
7563
#[track_caller]
7664
fn $method(&mut self, other: &$u) {

library/core/src/net/ip_addr.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use super::display_buffer::DisplayBuffer;
22
use crate::cmp::Ordering;
33
use crate::fmt::{self, Write};
44
use crate::hash::{Hash, Hasher};
5-
use crate::iter;
65
use crate::mem::transmute;
76
use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
87

@@ -2348,20 +2347,24 @@ impl const From<[u16; 8]> for IpAddr {
23482347
}
23492348

23502349
#[stable(feature = "ip_bitops", since = "1.75.0")]
2351-
impl Not for Ipv4Addr {
2350+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2351+
impl const Not for Ipv4Addr {
23522352
type Output = Ipv4Addr;
23532353

23542354
#[inline]
23552355
fn not(mut self) -> Ipv4Addr {
2356-
for octet in &mut self.octets {
2357-
*octet = !*octet;
2356+
let mut idx = 0;
2357+
while idx < 4 {
2358+
self.octets[idx] = !self.octets[idx];
2359+
idx += 1;
23582360
}
23592361
self
23602362
}
23612363
}
23622364

23632365
#[stable(feature = "ip_bitops", since = "1.75.0")]
2364-
impl Not for &'_ Ipv4Addr {
2366+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2367+
impl const Not for &'_ Ipv4Addr {
23652368
type Output = Ipv4Addr;
23662369

23672370
#[inline]
@@ -2371,20 +2374,24 @@ impl Not for &'_ Ipv4Addr {
23712374
}
23722375

23732376
#[stable(feature = "ip_bitops", since = "1.75.0")]
2374-
impl Not for Ipv6Addr {
2377+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2378+
impl const Not for Ipv6Addr {
23752379
type Output = Ipv6Addr;
23762380

23772381
#[inline]
23782382
fn not(mut self) -> Ipv6Addr {
2379-
for octet in &mut self.octets {
2380-
*octet = !*octet;
2383+
let mut idx = 0;
2384+
while idx < 16 {
2385+
self.octets[idx] = !self.octets[idx];
2386+
idx += 1;
23812387
}
23822388
self
23832389
}
23842390
}
23852391

23862392
#[stable(feature = "ip_bitops", since = "1.75.0")]
2387-
impl Not for &'_ Ipv6Addr {
2393+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
2394+
impl const Not for &'_ Ipv6Addr {
23882395
type Output = Ipv6Addr;
23892396

23902397
#[inline]
@@ -2400,23 +2407,25 @@ macro_rules! bitop_impls {
24002407
)*) => {
24012408
$(
24022409
$(#[$attr])*
2403-
impl $BitOpAssign for $ty {
2410+
impl const $BitOpAssign for $ty {
24042411
fn $bitop_assign(&mut self, rhs: $ty) {
2405-
for (lhs, rhs) in iter::zip(&mut self.octets, rhs.octets) {
2406-
lhs.$bitop_assign(rhs);
2412+
let mut idx = 0;
2413+
while idx < self.octets.len() {
2414+
self.octets[idx].$bitop_assign(rhs.octets[idx]);
2415+
idx += 1;
24072416
}
24082417
}
24092418
}
24102419

24112420
$(#[$attr])*
2412-
impl $BitOpAssign<&'_ $ty> for $ty {
2421+
impl const $BitOpAssign<&'_ $ty> for $ty {
24132422
fn $bitop_assign(&mut self, rhs: &'_ $ty) {
24142423
self.$bitop_assign(*rhs);
24152424
}
24162425
}
24172426

24182427
$(#[$attr])*
2419-
impl $BitOp for $ty {
2428+
impl const $BitOp for $ty {
24202429
type Output = $ty;
24212430

24222431
#[inline]
@@ -2427,7 +2436,7 @@ macro_rules! bitop_impls {
24272436
}
24282437

24292438
$(#[$attr])*
2430-
impl $BitOp<&'_ $ty> for $ty {
2439+
impl const $BitOp<&'_ $ty> for $ty {
24312440
type Output = $ty;
24322441

24332442
#[inline]
@@ -2438,7 +2447,7 @@ macro_rules! bitop_impls {
24382447
}
24392448

24402449
$(#[$attr])*
2441-
impl $BitOp<$ty> for &'_ $ty {
2450+
impl const $BitOp<$ty> for &'_ $ty {
24422451
type Output = $ty;
24432452

24442453
#[inline]
@@ -2450,7 +2459,7 @@ macro_rules! bitop_impls {
24502459
}
24512460

24522461
$(#[$attr])*
2453-
impl $BitOp<&'_ $ty> for &'_ $ty {
2462+
impl const $BitOp<&'_ $ty> for &'_ $ty {
24542463
type Output = $ty;
24552464

24562465
#[inline]
@@ -2466,12 +2475,16 @@ macro_rules! bitop_impls {
24662475

24672476
bitop_impls! {
24682477
#[stable(feature = "ip_bitops", since = "1.75.0")]
2478+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24692479
impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign);
24702480
#[stable(feature = "ip_bitops", since = "1.75.0")]
2481+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24712482
impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign);
24722483

24732484
#[stable(feature = "ip_bitops", since = "1.75.0")]
2485+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24742486
impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign);
24752487
#[stable(feature = "ip_bitops", since = "1.75.0")]
2488+
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
24762489
impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign);
24772490
}

0 commit comments

Comments
 (0)