From 7a09b8a7b52e5f9e9f7145657629bca9d89f16f0 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 24 May 2022 22:33:31 +0400 Subject: [PATCH 1/8] Stabilize `{slice,array}::from_ref` --- library/core/src/array/mod.rs | 2 +- library/core/src/slice/raw.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index fba1a5a751c59..2ea4458bf6427 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -92,7 +92,7 @@ where /// Converts a reference to `T` into a reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_array_from_ref", issue = "90206")] +#[rustc_const_stable(feature = "const_array_from_ref_shared", since = "1.63.0")] pub const fn from_ref(s: &T) -> &[T; 1] { // SAFETY: Converting `&T` to `&[T; 1]` is sound. unsafe { &*(s as *const T).cast::<[T; 1]>() } diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 6bc60b04b5c64..76dc3351d344c 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -144,7 +144,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[rustc_const_stable(feature = "const_slice_from_ref_shared", since = "1.63.0")] #[must_use] pub const fn from_ref(s: &T) -> &[T] { array::from_ref(s) From fafccdced349d655db83e0ec30e91b85dcf65cf7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 2 Jun 2022 09:05:37 -0400 Subject: [PATCH 2/8] add cast kind of from_exposed_addr (int-to-ptr casts) --- compiler/rustc_borrowck/src/type_check/mod.rs | 50 ++++++++++++++----- compiler/rustc_codegen_cranelift/src/base.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 3 +- .../rustc_const_eval/src/interpret/cast.rs | 34 +++++++++---- .../src/transform/check_consts/check.rs | 18 +++---- .../src/transform/promote_consts.rs | 3 +- compiler/rustc_middle/src/mir/mod.rs | 8 ++- .../src/build/expr/as_rvalue.rs | 3 ++ .../reify_fn_ptr.main.ConstProp.diff | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 7 ++- 10 files changed, 93 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index abf77acb8c7ad..e5aed1b60ddc1 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2154,31 +2154,55 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match (cast_ty_from, cast_ty_to) { (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (), _ => { - span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty) + span_mirbug!( + self, + rvalue, + "Invalid PointerExposeAddress cast {:?} -> {:?}", + ty_from, + ty + ) } } } - CastKind::Misc => { + CastKind::PointerFromExposedAddress => { let ty_from = op.ty(body, tcx); let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { - (None, _) - | (_, None | Some(CastTy::FnPtr)) - | (Some(CastTy::Float), Some(CastTy::Ptr(_))) - | ( - Some(CastTy::Ptr(_) | CastTy::FnPtr), - Some(CastTy::Float | CastTy::Int(_)), - ) => { - span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,) + (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (), + _ => { + span_mirbug!( + self, + rvalue, + "Invalid PointerFromExposedAddress cast {:?} -> {:?}", + ty_from, + ty + ) } + } + } + + CastKind::Misc => { + let ty_from = op.ty(body, tcx); + let cast_ty_from = CastTy::from_ty(ty_from); + let cast_ty_to = CastTy::from_ty(*ty); + // Misc casts are either between floats and ints, or one ptr type to another. + match (cast_ty_from, cast_ty_to) { ( - Some(CastTy::Int(_)), - Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)), + Some(CastTy::Int(_) | CastTy::Float), + Some(CastTy::Int(_) | CastTy::Float), ) - | (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float)) | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (), + _ => { + span_mirbug!( + self, + rvalue, + "Invalid Misc cast {:?} -> {:?}", + ty_from, + ty, + ) + } } } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 58bec183c94aa..07136e1b76a9f 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -608,7 +608,9 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, operand.cast_pointer_to(to_layout)); } Rvalue::Cast( - CastKind::Misc | CastKind::PointerExposeAddress, + CastKind::Misc + | CastKind::PointerExposeAddress + | CastKind::PointerFromExposedAddress, ref operand, to_ty, ) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 6ff8d4aa44216..90afb7adcb2b5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -269,7 +269,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::CastKind::Pointer( PointerCast::MutToConstPointer | PointerCast::ArrayToPointer, ) - | mir::CastKind::Misc => { + | mir::CastKind::Misc + | mir::CastKind::PointerFromExposedAddress => { assert!(bx.cx().is_backend_immediate(cast)); let ll_t_out = bx.cx().immediate_backend_type(cast); if operand.layout.abi.is_uninhabited() { diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 520ae409e6b9f..73cc59ad1e674 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -37,6 +37,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(res, dest)?; } + PointerFromExposedAddress => { + let src = self.read_immediate(src)?; + let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?; + self.write_immediate(res, dest)?; + } + Misc => { let src = self.read_immediate(src)?; let res = self.misc_cast(&src, cast_ty)?; @@ -201,6 +207,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into()) } + pub fn pointer_from_exposed_address_cast( + &mut self, + src: &ImmTy<'tcx, M::PointerTag>, + cast_ty: Ty<'tcx>, + ) -> InterpResult<'tcx, Immediate> { + assert!(src.layout.ty.is_integral()); + assert_matches!(cast_ty.kind(), ty::RawPtr(_)); + + // First cast to usize. + let scalar = src.to_scalar()?; + let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?; + let addr = addr.to_machine_usize(self)?; + + // Then turn address into pointer. + let ptr = M::ptr_from_addr_cast(&self, addr); + Ok(Scalar::from_maybe_pointer(ptr, self).into()) + } + pub fn cast_from_int_like( &self, scalar: Scalar, // input value (there is no ScalarTy so we separate data+layout) @@ -225,16 +249,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Scalar::from_uint(v, size) } - RawPtr(_) => { - assert!(src_layout.ty.is_integral()); - - let size = self.pointer_size(); - let addr = u64::try_from(size.truncate(v)).unwrap(); - - let ptr = M::ptr_from_addr_cast(&self, addr); - Scalar::from_maybe_pointer(ptr, self) - } - Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value), Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value), Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value), diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index c07680515f4e7..4b98e19376dda 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -519,32 +519,30 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } - Rvalue::Cast( - CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), - _, - _, - ) => {} - Rvalue::Cast( CastKind::Pointer( - PointerCast::UnsafeFnPointer + PointerCast::MutToConstPointer + | PointerCast::ArrayToPointer + | PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer, ), _, _, ) => { - // Nothing to do here. Function pointer casts are allowed now. + // These are all okay; they only change the type, not the data. } Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => { - // Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur - // in the type of any local, which also excludes casts). + // Unsizing is implemented for CTFE. } Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => { self.check_op(ops::RawPtrToIntCast); } + Rvalue::Cast(CastKind::PointerFromExposedAddress, _, _) => { + // Since no pointer can ever get exposed (rejected above), this is easy to support. + } Rvalue::Cast(CastKind::Misc, _, _) => {} diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index cf5d7b6c70a30..4879e8de10000 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -504,7 +504,8 @@ impl<'tcx> Validator<'_, 'tcx> { // ptr-to-int casts are not possible in consts and thus not promotable Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable), - // int-to-ptr casts are fine, they just use the integer value at pointer type. + // all ohter casts including int-to-ptr casts are fine, they just use the integer value + // at pointer type. Rvalue::Cast(_, operand, _) => { self.validate_operand(operand)?; } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d9cdca8bcb5d7..f3db359ec3348 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2613,12 +2613,18 @@ impl<'tcx> Rvalue<'tcx> { #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum CastKind { - Misc, /// An exposing pointer to address cast. A cast between a pointer and an integer type, or /// between a function pointer and an integer type. /// See the docs on `expose_addr` for more details. PointerExposeAddress, + /// An address-to-pointer cast that picks up an exposed provenance. + /// See the docs on `from_exposed_addr` for more details. + PointerFromExposedAddress, + /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are + /// translated into `&raw mut/const *r`, i.e., they are not actually casts. Pointer(PointerCast), + /// Remaining unclassified casts. + Misc, } #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 7d08b20631e47..8e87ecd27d285 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -196,6 +196,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { CastKind::PointerExposeAddress } + (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => { + CastKind::PointerFromExposedAddress + } (_, _) => CastKind::Misc, }; let source = unpack!( diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff index 04724b13ca64c..037febdf3a579 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff @@ -19,7 +19,7 @@ // + literal: Const { ty: fn() {main}, val: Value(Scalar()) } _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:26 StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:4:25: 4:26 - _1 = move _2 as *const fn() (Misc); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41 + _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:4:13: 4:41 StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:4:40: 4:41 StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:4:41: 4:42 nop; // scope 0 at $DIR/reify_fn_ptr.rs:3:11: 5:2 diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index b1c82ac76e8eb..58abef38ea8be 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -131,7 +131,12 @@ fn check_rvalue<'tcx>( Rvalue::Cast(CastKind::Misc, operand, _) => { check_operand(tcx, operand, span, body) }, - Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => { + Rvalue::Cast( + CastKind::PointerFromExposedAddress + | CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), + operand, + _ + ) => { check_operand(tcx, operand, span, body) }, Rvalue::Cast( From d5a590f53744add6e37eee19f4591f2be6d990f8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 2 Jun 2022 11:10:34 -0400 Subject: [PATCH 3/8] comment Co-authored-by: Oli Scherer --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 3 +++ compiler/rustc_const_eval/src/transform/promote_consts.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 90afb7adcb2b5..81c1897694ce6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -270,6 +270,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { PointerCast::MutToConstPointer | PointerCast::ArrayToPointer, ) | mir::CastKind::Misc + // Since int2ptr can have arbitrary integer types as input (so we have to do + // sign extension and all that), it is currently best handled in the same code + // path as the other integer-to-X casts. | mir::CastKind::PointerFromExposedAddress => { assert!(bx.cx().is_backend_immediate(cast)); let ll_t_out = bx.cx().immediate_backend_type(cast); diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 4879e8de10000..d1e776854b231 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -504,7 +504,7 @@ impl<'tcx> Validator<'_, 'tcx> { // ptr-to-int casts are not possible in consts and thus not promotable Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable), - // all ohter casts including int-to-ptr casts are fine, they just use the integer value + // all other casts including int-to-ptr casts are fine, they just use the integer value // at pointer type. Rvalue::Cast(_, operand, _) => { self.validate_operand(operand)?; From 7676f07d0e6e8d13575652ce7e71a67c1bbd871c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 2 Jun 2022 15:12:08 -0400 Subject: [PATCH 4/8] take back half-baked noaliasing check in Assignment --- compiler/rustc_const_eval/src/interpret/place.rs | 4 +--- compiler/rustc_const_eval/src/interpret/step.rs | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 955480a1a7411..ae7180b674ffd 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -869,8 +869,6 @@ where Ok(src_val) => { assert!(!src.layout.is_unsized(), "cannot have unsized immediates"); // Yay, we got a value that we can write directly. - // FIXME: Add a check to make sure that if `src` is indirect, - // it does not overlap with `dest`. return self.write_immediate_no_validate(*src_val, dest); } Err(mplace) => mplace, @@ -890,7 +888,7 @@ where }); assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true) + self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ false) } /// Copies the data from an operand to a place. The layouts may disagree, but they must diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index e6dfdf54a32d1..9ac86911c7d96 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -158,6 +158,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { place: mir::Place<'tcx>, ) -> InterpResult<'tcx> { let dest = self.eval_place(place)?; + // FIXME: ensure some kind of non-aliasing between LHS and RHS? + // Also see https://github.com/rust-lang/rust/issues/68364. use rustc_middle::mir::Rvalue::*; match *rvalue { From 8567b686f9b5f85b18341d77814088a4a7409238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 Jun 2022 12:34:55 -0700 Subject: [PATCH 5/8] On E0204 suggest missing type param bounds ``` error[E0204]: the trait `Copy` may not be implemented for this type --> f42.rs:9:17 | 9 | #[derive(Debug, Copy, Clone)] | ^^^^ 10 | pub struct AABB{ 11 | pub loc: Vector2, | ------------------- this field does not implement `Copy` 12 | pub size: Vector2 | -------------------- this field does not implement `Copy` | note: the `Copy` impl for `Vector2` requires that `K: Debug` --> f42.rs:11:5 | 11 | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ note: the `Copy` impl for `Vector2` requires that `K: Debug` --> f42.rs:12:5 | 12 | pub size: Vector2 | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` | 10 | pub struct AABB{ | +++++++ ``` Fix #89137. --- compiler/rustc_middle/src/ty/diagnostics.rs | 5 ++- .../rustc_typeck/src/coherence/builtin.rs | 41 ++++++++++++++++++- .../use_of_moved_value_copy_suggestions.fixed | 10 ++--- ...use_of_moved_value_copy_suggestions.stderr | 10 ++--- .../missing-bound-in-derive-copy-impl-2.fixed | 16 ++++++++ .../missing-bound-in-derive-copy-impl-2.rs | 16 ++++++++ ...missing-bound-in-derive-copy-impl-2.stderr | 19 +++++++++ .../missing-bound-in-derive-copy-impl-3.fixed | 16 ++++++++ .../missing-bound-in-derive-copy-impl-3.rs | 16 ++++++++ ...missing-bound-in-derive-copy-impl-3.stderr | 30 ++++++++++++++ .../missing-bound-in-derive-copy-impl.rs | 15 +++++++ .../missing-bound-in-derive-copy-impl.stderr | 30 ++++++++++++++ 12 files changed, 211 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs create mode 100644 src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 462fc27009de9..9bb64d4023bca 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -272,7 +272,10 @@ pub fn suggest_constraining_type_params<'a>( continue; } - let constraint = constraints.iter().map(|&(c, _)| c).collect::>().join(" + "); + let mut constraint = constraints.iter().map(|&(c, _)| c).collect::>(); + constraint.sort(); + constraint.dedup(); + let constraint = constraint.join(" + "); let mut suggest_restrict = |span, bound_list_non_empty| { suggestions.push(( span, diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index d08d9938708c9..5953a13506d6d 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -11,8 +11,7 @@ use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionckMode, TyCtxtInferExt}; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; -use rustc_middle::ty::TypeFoldable; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; use rustc_trait_selection::traits::predicate_for_trait_def; @@ -91,6 +90,19 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { E0204, "the trait `Copy` may not be implemented for this type" ); + + // We'll try to suggest constraining type parameters to fulfill the requirements of + // their `Copy` implementation. + let mut generics = None; + if let ty::Adt(def, _substs) = self_type.kind() { + let self_def_id = def.did(); + if let Some(local) = self_def_id.as_local() { + let self_item = tcx.hir().expect_item(local); + generics = self_item.kind.generics(); + } + } + let mut bounds = vec![]; + for (field, ty) in fields { let field_span = tcx.def_span(field.did); err.span_label(field_span, "this field does not implement `Copy`"); @@ -123,9 +135,34 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { ), ); } + if let ty::PredicateKind::Trait(ty::TraitPredicate { + trait_ref, + polarity: ty::ImplPolarity::Positive, + .. + }) = error_predicate.kind().skip_binder() + { + let ty = trait_ref.self_ty(); + if let ty::Param(_) = ty.kind() { + bounds.push(( + format!("{ty}"), + trait_ref.print_only_trait_path().to_string(), + Some(trait_ref.def_id), + )); + } + } } }); } + if let Some(generics) = generics { + suggest_constraining_type_params( + tcx, + generics, + &mut err, + bounds.iter().map(|(param, constraint, def_id)| { + (param.as_str(), constraint.as_str(), *def_id) + }), + ); + } err.emit(); } Err(CopyImplementationError::NotAnAdt) => { diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed index ba1b745ba8422..45acf5beb1217 100644 --- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -21,7 +21,7 @@ fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { (t, t) //~ use of moved value: `t` } -fn duplicate_custom(t: S) -> (S, S) { +fn duplicate_custom(t: S) -> (S, S) { //~^ HELP consider restricting type parameter `T` (t, t) //~ use of moved value: `t` } @@ -39,14 +39,14 @@ trait A {} trait B {} // Test where bounds are added with different bound placements -fn duplicate_custom_1(t: S) -> (S, S) where { +fn duplicate_custom_1(t: S) -> (S, S) where { //~^ HELP consider restricting type parameter `T` (t, t) //~ use of moved value: `t` } fn duplicate_custom_2(t: S) -> (S, S) where - T: A + Trait + Copy, + T: A + Copy + Trait, //~^ HELP consider further restricting this bound { (t, t) //~ use of moved value: `t` @@ -54,14 +54,14 @@ where fn duplicate_custom_3(t: S) -> (S, S) where - T: A + Trait + Copy, + T: A + Copy + Trait, //~^ HELP consider further restricting this bound T: B, { (t, t) //~ use of moved value: `t` } -fn duplicate_custom_4(t: S) -> (S, S) +fn duplicate_custom_4(t: S) -> (S, S) //~^ HELP consider further restricting this bound where T: B, diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr index 2353cd079a370..5a84e3b81a656 100644 --- a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -75,7 +75,7 @@ LL | (t, t) | help: consider restricting type parameter `T` | -LL | fn duplicate_custom(t: S) -> (S, S) { +LL | fn duplicate_custom(t: S) -> (S, S) { | ++++++++++++++ error[E0382]: use of moved value: `t` @@ -91,7 +91,7 @@ LL | (t, t) | help: consider restricting type parameter `T` | -LL | fn duplicate_custom_1(t: S) -> (S, S) where { +LL | fn duplicate_custom_1(t: S) -> (S, S) where { | ++++++++++++++ error[E0382]: use of moved value: `t` @@ -107,7 +107,7 @@ LL | (t, t) | help: consider further restricting this bound | -LL | T: A + Trait + Copy, +LL | T: A + Copy + Trait, | ++++++++++++++ error[E0382]: use of moved value: `t` @@ -123,7 +123,7 @@ LL | (t, t) | help: consider further restricting this bound | -LL | T: A + Trait + Copy, +LL | T: A + Copy + Trait, | ++++++++++++++ error[E0382]: use of moved value: `t` @@ -139,7 +139,7 @@ LL | (t, t) | help: consider further restricting this bound | -LL | fn duplicate_custom_4(t: S) -> (S, S) +LL | fn duplicate_custom_4(t: S) -> (S, S) | ++++++++++++++ error[E0382]: use of moved value: `t` diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed new file mode 100644 index 0000000000000..ac0b14fba83b6 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed @@ -0,0 +1,16 @@ +// run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] +pub struct AABB{ + pub loc: Vector2, //~ ERROR the trait bound `K: Copy` is not satisfied + pub size: Vector2 +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs new file mode 100644 index 0000000000000..31f8cd6fcf79e --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs @@ -0,0 +1,16 @@ +// run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] +pub struct AABB{ + pub loc: Vector2, //~ ERROR the trait bound `K: Copy` is not satisfied + pub size: Vector2 +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr new file mode 100644 index 0000000000000..03082be690fbf --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `K: Copy` is not satisfied + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ the trait `Copy` is not implemented for `K` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31 + | +LL | pub struct Vector2{ + | ^^^^ required by this bound in `Vector2` +help: consider further restricting this bound + | +LL | pub struct AABB{ + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed new file mode 100644 index 0000000000000..304360d48a261 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -0,0 +1,16 @@ +//run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB{ + pub loc: Vector2, + pub size: Vector2 +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs new file mode 100644 index 0000000000000..14e1fbb33112a --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -0,0 +1,16 @@ +//run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB{ + pub loc: Vector2, + pub size: Vector2 +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr new file mode 100644 index 0000000000000..2dc41709fdc97 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -0,0 +1,30 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ +LL | pub struct AABB{ +LL | pub loc: Vector2, + | ------------------- this field does not implement `Copy` +LL | pub size: Vector2 + | -------------------- this field does not implement `Copy` + | +note: the `Copy` impl for `Vector2` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:5 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^^^^^^^^^^ +note: the `Copy` impl for `Vector2` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:13:5 + | +LL | pub size: Vector2 + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | pub struct AABB{ + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs new file mode 100644 index 0000000000000..52163bddd4ff5 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -0,0 +1,15 @@ +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB{ + pub loc: Vector2, + pub size: Vector2 +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr new file mode 100644 index 0000000000000..1f6932b1fa601 --- /dev/null +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -0,0 +1,30 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ +LL | pub struct AABB{ +LL | pub loc: Vector2, + | ------------------- this field does not implement `Copy` +LL | pub size: Vector2 + | -------------------- this field does not implement `Copy` + | +note: the `Copy` impl for `Vector2` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:5 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^^^^^^^^^^ +note: the `Copy` impl for `Vector2` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:12:5 + | +LL | pub size: Vector2 + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `K` + | +LL | pub struct AABB{ + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. From 7dd3861235ecdcdfb0d5d992f9a8a698ab8caee6 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 2 Jun 2022 14:28:18 -0700 Subject: [PATCH 6/8] rustdoc: clean up primitive.slice.html links --- src/librustdoc/html/format.rs | 38 ++++++++----------- .../rustdoc/slice-links.link_box_generic.html | 1 + .../rustdoc/slice-links.link_box_u32.html | 1 + .../slice-links.link_slice_generic.html | 1 + .../rustdoc/slice-links.link_slice_u32.html | 1 + src/test/rustdoc/slice-links.rs | 28 ++++++++++++++ 6 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 src/test/rustdoc/slice-links.link_box_generic.html create mode 100644 src/test/rustdoc/slice-links.link_box_u32.html create mode 100644 src/test/rustdoc/slice-links.link_slice_generic.html create mode 100644 src/test/rustdoc/slice-links.link_slice_u32.html create mode 100644 src/test/rustdoc/slice-links.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3094683458321..b7789493df647 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -881,11 +881,16 @@ fn fmt_type<'cx>( } } } - clean::Slice(ref t) => { - primitive_link(f, PrimitiveType::Slice, "[", cx)?; - fmt::Display::fmt(&t.print(cx), f)?; - primitive_link(f, PrimitiveType::Slice, "]", cx) - } + clean::Slice(ref t) => match **t { + clean::Generic(name) => { + primitive_link(f, PrimitiveType::Slice, &format!("[{name}]"), cx) + } + _ => { + primitive_link(f, PrimitiveType::Slice, "[", cx)?; + fmt::Display::fmt(&t.print(cx), f)?; + primitive_link(f, PrimitiveType::Slice, "]", cx) + } + }, clean::Array(ref t, ref n) => { primitive_link(f, PrimitiveType::Array, "[", cx)?; fmt::Display::fmt(&t.print(cx), f)?; @@ -924,23 +929,12 @@ fn fmt_type<'cx>( clean::Slice(ref bt) => { // `BorrowedRef{ ... Slice(T) }` is `&[T]` match **bt { - clean::Generic(_) => { - if f.alternate() { - primitive_link( - f, - PrimitiveType::Slice, - &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cx)), - cx, - ) - } else { - primitive_link( - f, - PrimitiveType::Slice, - &format!("{}{}{}[{}]", amp, lt, m, bt.print(cx)), - cx, - ) - } - } + clean::Generic(name) => primitive_link( + f, + PrimitiveType::Slice, + &format!("{amp}{lt}{m}[{name}]"), + cx, + ), _ => { primitive_link( f, diff --git a/src/test/rustdoc/slice-links.link_box_generic.html b/src/test/rustdoc/slice-links.link_box_generic.html new file mode 100644 index 0000000000000..38aaf20808cf1 --- /dev/null +++ b/src/test/rustdoc/slice-links.link_box_generic.html @@ -0,0 +1 @@ +pub fn delta<T>() -> MyBox<[T]> \ No newline at end of file diff --git a/src/test/rustdoc/slice-links.link_box_u32.html b/src/test/rustdoc/slice-links.link_box_u32.html new file mode 100644 index 0000000000000..42fd721a4acf1 --- /dev/null +++ b/src/test/rustdoc/slice-links.link_box_u32.html @@ -0,0 +1 @@ +pub fn gamma() -> MyBox<[u32]> \ No newline at end of file diff --git a/src/test/rustdoc/slice-links.link_slice_generic.html b/src/test/rustdoc/slice-links.link_slice_generic.html new file mode 100644 index 0000000000000..fe79ca7a82da3 --- /dev/null +++ b/src/test/rustdoc/slice-links.link_slice_generic.html @@ -0,0 +1 @@ +pub fn beta<T>() -> &'static [T] \ No newline at end of file diff --git a/src/test/rustdoc/slice-links.link_slice_u32.html b/src/test/rustdoc/slice-links.link_slice_u32.html new file mode 100644 index 0000000000000..c7e430b0607f7 --- /dev/null +++ b/src/test/rustdoc/slice-links.link_slice_u32.html @@ -0,0 +1 @@ +pub fn alpha() -> &'static [u32] \ No newline at end of file diff --git a/src/test/rustdoc/slice-links.rs b/src/test/rustdoc/slice-links.rs new file mode 100644 index 0000000000000..9a78e963e3036 --- /dev/null +++ b/src/test/rustdoc/slice-links.rs @@ -0,0 +1,28 @@ +#![crate_name = "foo"] +#![no_std] + +pub struct MyBox(*const T); + +// @has 'foo/fn.alpha.html' +// @snapshot link_slice_u32 - '//pre[@class="rust fn"]/code' +pub fn alpha() -> &'static [u32] { + loop {} +} + +// @has 'foo/fn.beta.html' +// @snapshot link_slice_generic - '//pre[@class="rust fn"]/code' +pub fn beta() -> &'static [T] { + loop {} +} + +// @has 'foo/fn.gamma.html' +// @snapshot link_box_u32 - '//pre[@class="rust fn"]/code' +pub fn gamma() -> MyBox<[u32]> { + loop {} +} + +// @has 'foo/fn.delta.html' +// @snapshot link_box_generic - '//pre[@class="rust fn"]/code' +pub fn delta() -> MyBox<[T]> { + loop {} +} From dadf3bdefff6c38d7f64d7ae4b14fbaca66ab96a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 2 Jun 2022 15:02:26 -0700 Subject: [PATCH 7/8] rustdoc: add channel normalization to htmldocck.py --- src/etc/htmldocck.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 269b6868e29f9..5eb70ab13dba0 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -423,6 +423,8 @@ def check_snapshot(snapshot_name, actual_tree, normalize_to_text): else: actual_str = flatten(actual_tree) + expected_str = expected_str.replace("{{channel}}", channel) + # Conditions: # 1. Is --bless # 2. Are actual and expected tree different From f9aa2e02cdfdeea64ed58d2956047c2c155186f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 2 Jun 2022 13:15:56 -0700 Subject: [PATCH 8/8] Tweak output --- .../rustc_typeck/src/coherence/builtin.rs | 22 ++++++++++++------- ...missing-bound-in-derive-copy-impl-3.stderr | 3 --- .../missing-bound-in-derive-copy-impl.stderr | 3 --- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 5953a13506d6d..c809b8bdd73db 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -2,7 +2,7 @@ //! up data structures required by type-checking/codegen. use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem}; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -16,6 +16,7 @@ use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; use rustc_trait_selection::traits::predicate_for_trait_def; use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt}; +use std::collections::BTreeMap; pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { let lang_items = tcx.lang_items(); @@ -101,6 +102,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { generics = self_item.kind.generics(); } } + let mut errors: BTreeMap<_, Vec<_>> = Default::default(); let mut bounds = vec![]; for (field, ty) in fields { @@ -127,13 +129,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { // FIXME: This error could be more descriptive, especially if the error_predicate // contains a foreign type or if it's a deeply nested type... if error_predicate != error.root_obligation.predicate { - err.span_note( - error.obligation.cause.span, - &format!( - "the `Copy` impl for `{}` requires that `{}`", - ty, error_predicate - ), - ); + errors + .entry((ty.to_string(), error_predicate.to_string())) + .or_default() + .push(error.obligation.cause.span); } if let ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, @@ -153,6 +152,13 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { } }); } + for ((ty, error_predicate), spans) in errors { + let span: MultiSpan = spans.into(); + err.span_note( + span, + &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate), + ); + } if let Some(generics) = generics { suggest_constraining_type_params( tcx, diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index 2dc41709fdc97..4eb1e318d97c3 100644 --- a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -14,9 +14,6 @@ note: the `Copy` impl for `Vector2` requires that `K: Debug` | LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ -note: the `Copy` impl for `Vector2` requires that `K: Debug` - --> $DIR/missing-bound-in-derive-copy-impl-3.rs:13:5 - | LL | pub size: Vector2 | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 1f6932b1fa601..1cf2ab95bc3a8 100644 --- a/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/src/test/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -14,9 +14,6 @@ note: the `Copy` impl for `Vector2` requires that `K: Debug` | LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ -note: the `Copy` impl for `Vector2` requires that `K: Debug` - --> $DIR/missing-bound-in-derive-copy-impl.rs:12:5 - | LL | pub size: Vector2 | ^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)