Skip to content

Commit 72f7e31

Browse files
committed
Auto merge of rust-lang#97679 - Dylan-DPC:rollup-nswmgmx, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - rust-lang#97366 (Stabilize `{slice,array}::from_ref`) - rust-lang#97653 (add cast kind of from_exposed_addr (int-to-ptr casts)) - rust-lang#97663 (take back half-baked noaliasing check in Assignment) - rust-lang#97664 (On E0204 suggest missing type param bounds) - rust-lang#97668 (rustdoc: clean up primitive.slice.html links) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3a90bed + d6f35b3 commit 72f7e31

33 files changed

+370
-87
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -2154,31 +2154,55 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21542154
match (cast_ty_from, cast_ty_to) {
21552155
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
21562156
_ => {
2157-
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty)
2157+
span_mirbug!(
2158+
self,
2159+
rvalue,
2160+
"Invalid PointerExposeAddress cast {:?} -> {:?}",
2161+
ty_from,
2162+
ty
2163+
)
21582164
}
21592165
}
21602166
}
21612167

2162-
CastKind::Misc => {
2168+
CastKind::PointerFromExposedAddress => {
21632169
let ty_from = op.ty(body, tcx);
21642170
let cast_ty_from = CastTy::from_ty(ty_from);
21652171
let cast_ty_to = CastTy::from_ty(*ty);
21662172
match (cast_ty_from, cast_ty_to) {
2167-
(None, _)
2168-
| (_, None | Some(CastTy::FnPtr))
2169-
| (Some(CastTy::Float), Some(CastTy::Ptr(_)))
2170-
| (
2171-
Some(CastTy::Ptr(_) | CastTy::FnPtr),
2172-
Some(CastTy::Float | CastTy::Int(_)),
2173-
) => {
2174-
span_mirbug!(self, rvalue, "Invalid cast {:?} -> {:?}", ty_from, ty,)
2173+
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
2174+
_ => {
2175+
span_mirbug!(
2176+
self,
2177+
rvalue,
2178+
"Invalid PointerFromExposedAddress cast {:?} -> {:?}",
2179+
ty_from,
2180+
ty
2181+
)
21752182
}
2183+
}
2184+
}
2185+
2186+
CastKind::Misc => {
2187+
let ty_from = op.ty(body, tcx);
2188+
let cast_ty_from = CastTy::from_ty(ty_from);
2189+
let cast_ty_to = CastTy::from_ty(*ty);
2190+
// Misc casts are either between floats and ints, or one ptr type to another.
2191+
match (cast_ty_from, cast_ty_to) {
21762192
(
2177-
Some(CastTy::Int(_)),
2178-
Some(CastTy::Int(_) | CastTy::Float | CastTy::Ptr(_)),
2193+
Some(CastTy::Int(_) | CastTy::Float),
2194+
Some(CastTy::Int(_) | CastTy::Float),
21792195
)
2180-
| (Some(CastTy::Float), Some(CastTy::Int(_) | CastTy::Float))
21812196
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
2197+
_ => {
2198+
span_mirbug!(
2199+
self,
2200+
rvalue,
2201+
"Invalid Misc cast {:?} -> {:?}",
2202+
ty_from,
2203+
ty,
2204+
)
2205+
}
21822206
}
21832207
}
21842208
}

compiler/rustc_codegen_cranelift/src/base.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,9 @@ fn codegen_stmt<'tcx>(
608608
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
609609
}
610610
Rvalue::Cast(
611-
CastKind::Misc | CastKind::PointerExposeAddress,
611+
CastKind::Misc
612+
| CastKind::PointerExposeAddress
613+
| CastKind::PointerFromExposedAddress,
612614
ref operand,
613615
to_ty,
614616
) => {

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
269269
mir::CastKind::Pointer(
270270
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
271271
)
272-
| mir::CastKind::Misc => {
272+
| mir::CastKind::Misc
273+
// Since int2ptr can have arbitrary integer types as input (so we have to do
274+
// sign extension and all that), it is currently best handled in the same code
275+
// path as the other integer-to-X casts.
276+
| mir::CastKind::PointerFromExposedAddress => {
273277
assert!(bx.cx().is_backend_immediate(cast));
274278
let ll_t_out = bx.cx().immediate_backend_type(cast);
275279
if operand.layout.abi.is_uninhabited() {

compiler/rustc_const_eval/src/interpret/cast.rs

+24-10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
3737
self.write_immediate(res, dest)?;
3838
}
3939

40+
PointerFromExposedAddress => {
41+
let src = self.read_immediate(src)?;
42+
let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
43+
self.write_immediate(res, dest)?;
44+
}
45+
4046
Misc => {
4147
let src = self.read_immediate(src)?;
4248
let res = self.misc_cast(&src, cast_ty)?;
@@ -201,6 +207,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
201207
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
202208
}
203209

210+
pub fn pointer_from_exposed_address_cast(
211+
&mut self,
212+
src: &ImmTy<'tcx, M::PointerTag>,
213+
cast_ty: Ty<'tcx>,
214+
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
215+
assert!(src.layout.ty.is_integral());
216+
assert_matches!(cast_ty.kind(), ty::RawPtr(_));
217+
218+
// First cast to usize.
219+
let scalar = src.to_scalar()?;
220+
let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
221+
let addr = addr.to_machine_usize(self)?;
222+
223+
// Then turn address into pointer.
224+
let ptr = M::ptr_from_addr_cast(&self, addr);
225+
Ok(Scalar::from_maybe_pointer(ptr, self).into())
226+
}
227+
204228
pub fn cast_from_int_like(
205229
&self,
206230
scalar: Scalar<M::PointerTag>, // 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> {
225249
Scalar::from_uint(v, size)
226250
}
227251

228-
RawPtr(_) => {
229-
assert!(src_layout.ty.is_integral());
230-
231-
let size = self.pointer_size();
232-
let addr = u64::try_from(size.truncate(v)).unwrap();
233-
234-
let ptr = M::ptr_from_addr_cast(&self, addr);
235-
Scalar::from_maybe_pointer(ptr, self)
236-
}
237-
238252
Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
239253
Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
240254
Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),

compiler/rustc_const_eval/src/interpret/place.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,6 @@ where
869869
Ok(src_val) => {
870870
assert!(!src.layout.is_unsized(), "cannot have unsized immediates");
871871
// Yay, we got a value that we can write directly.
872-
// FIXME: Add a check to make sure that if `src` is indirect,
873-
// it does not overlap with `dest`.
874872
return self.write_immediate_no_validate(*src_val, dest);
875873
}
876874
Err(mplace) => mplace,
@@ -890,7 +888,7 @@ where
890888
});
891889
assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances");
892890

893-
self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ true)
891+
self.mem_copy(src.ptr, src.align, dest.ptr, dest.align, size, /*nonoverlapping*/ false)
894892
}
895893

896894
/// Copies the data from an operand to a place. The layouts may disagree, but they must

compiler/rustc_const_eval/src/interpret/step.rs

+2
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
158158
place: mir::Place<'tcx>,
159159
) -> InterpResult<'tcx> {
160160
let dest = self.eval_place(place)?;
161+
// FIXME: ensure some kind of non-aliasing between LHS and RHS?
162+
// Also see https://github.com/rust-lang/rust/issues/68364.
161163

162164
use rustc_middle::mir::Rvalue::*;
163165
match *rvalue {

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -519,32 +519,30 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
519519
}
520520
}
521521

522-
Rvalue::Cast(
523-
CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
524-
_,
525-
_,
526-
) => {}
527-
528522
Rvalue::Cast(
529523
CastKind::Pointer(
530-
PointerCast::UnsafeFnPointer
524+
PointerCast::MutToConstPointer
525+
| PointerCast::ArrayToPointer
526+
| PointerCast::UnsafeFnPointer
531527
| PointerCast::ClosureFnPointer(_)
532528
| PointerCast::ReifyFnPointer,
533529
),
534530
_,
535531
_,
536532
) => {
537-
// Nothing to do here. Function pointer casts are allowed now.
533+
// These are all okay; they only change the type, not the data.
538534
}
539535

540536
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, _) => {
541-
// Nothing to check here (`check_local_or_return_ty` ensures no trait objects occur
542-
// in the type of any local, which also excludes casts).
537+
// Unsizing is implemented for CTFE.
543538
}
544539

545540
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
546541
self.check_op(ops::RawPtrToIntCast);
547542
}
543+
Rvalue::Cast(CastKind::PointerFromExposedAddress, _, _) => {
544+
// Since no pointer can ever get exposed (rejected above), this is easy to support.
545+
}
548546

549547
Rvalue::Cast(CastKind::Misc, _, _) => {}
550548

compiler/rustc_const_eval/src/transform/promote_consts.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ impl<'tcx> Validator<'_, 'tcx> {
504504
// ptr-to-int casts are not possible in consts and thus not promotable
505505
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => return Err(Unpromotable),
506506

507-
// int-to-ptr casts are fine, they just use the integer value at pointer type.
507+
// all other casts including int-to-ptr casts are fine, they just use the integer value
508+
// at pointer type.
508509
Rvalue::Cast(_, operand, _) => {
509510
self.validate_operand(operand)?;
510511
}

compiler/rustc_middle/src/mir/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2613,12 +2613,18 @@ impl<'tcx> Rvalue<'tcx> {
26132613

26142614
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
26152615
pub enum CastKind {
2616-
Misc,
26172616
/// An exposing pointer to address cast. A cast between a pointer and an integer type, or
26182617
/// between a function pointer and an integer type.
26192618
/// See the docs on `expose_addr` for more details.
26202619
PointerExposeAddress,
2620+
/// An address-to-pointer cast that picks up an exposed provenance.
2621+
/// See the docs on `from_exposed_addr` for more details.
2622+
PointerFromExposedAddress,
2623+
/// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
2624+
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
26212625
Pointer(PointerCast),
2626+
/// Remaining unclassified casts.
2627+
Misc,
26222628
}
26232629

26242630
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]

compiler/rustc_middle/src/ty/diagnostics.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ pub fn suggest_constraining_type_params<'a>(
272272
continue;
273273
}
274274

275-
let constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>().join(" + ");
275+
let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>();
276+
constraint.sort();
277+
constraint.dedup();
278+
let constraint = constraint.join(" + ");
276279
let mut suggest_restrict = |span, bound_list_non_empty| {
277280
suggestions.push((
278281
span,

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+3
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
196196
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
197197
CastKind::PointerExposeAddress
198198
}
199+
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
200+
CastKind::PointerFromExposedAddress
201+
}
199202
(_, _) => CastKind::Misc,
200203
};
201204
let source = unpack!(

compiler/rustc_typeck/src/coherence/builtin.rs

+53-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! up data structures required by type-checking/codegen.
33
44
use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
5-
use rustc_errors::struct_span_err;
5+
use rustc_errors::{struct_span_err, MultiSpan};
66
use rustc_hir as hir;
77
use rustc_hir::def_id::{DefId, LocalDefId};
88
use rustc_hir::lang_items::LangItem;
@@ -11,12 +11,12 @@ use rustc_infer::infer;
1111
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1212
use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
1313
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
14-
use rustc_middle::ty::TypeFoldable;
15-
use rustc_middle::ty::{self, Ty, TyCtxt};
14+
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeFoldable};
1615
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
1716
use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
1817
use rustc_trait_selection::traits::predicate_for_trait_def;
1918
use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt};
19+
use std::collections::BTreeMap;
2020

2121
pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
2222
let lang_items = tcx.lang_items();
@@ -91,6 +91,20 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
9191
E0204,
9292
"the trait `Copy` may not be implemented for this type"
9393
);
94+
95+
// We'll try to suggest constraining type parameters to fulfill the requirements of
96+
// their `Copy` implementation.
97+
let mut generics = None;
98+
if let ty::Adt(def, _substs) = self_type.kind() {
99+
let self_def_id = def.did();
100+
if let Some(local) = self_def_id.as_local() {
101+
let self_item = tcx.hir().expect_item(local);
102+
generics = self_item.kind.generics();
103+
}
104+
}
105+
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
106+
let mut bounds = vec![];
107+
94108
for (field, ty) in fields {
95109
let field_span = tcx.def_span(field.did);
96110
err.span_label(field_span, "this field does not implement `Copy`");
@@ -115,17 +129,46 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
115129
// FIXME: This error could be more descriptive, especially if the error_predicate
116130
// contains a foreign type or if it's a deeply nested type...
117131
if error_predicate != error.root_obligation.predicate {
118-
err.span_note(
119-
error.obligation.cause.span,
120-
&format!(
121-
"the `Copy` impl for `{}` requires that `{}`",
122-
ty, error_predicate
123-
),
124-
);
132+
errors
133+
.entry((ty.to_string(), error_predicate.to_string()))
134+
.or_default()
135+
.push(error.obligation.cause.span);
136+
}
137+
if let ty::PredicateKind::Trait(ty::TraitPredicate {
138+
trait_ref,
139+
polarity: ty::ImplPolarity::Positive,
140+
..
141+
}) = error_predicate.kind().skip_binder()
142+
{
143+
let ty = trait_ref.self_ty();
144+
if let ty::Param(_) = ty.kind() {
145+
bounds.push((
146+
format!("{ty}"),
147+
trait_ref.print_only_trait_path().to_string(),
148+
Some(trait_ref.def_id),
149+
));
150+
}
125151
}
126152
}
127153
});
128154
}
155+
for ((ty, error_predicate), spans) in errors {
156+
let span: MultiSpan = spans.into();
157+
err.span_note(
158+
span,
159+
&format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
160+
);
161+
}
162+
if let Some(generics) = generics {
163+
suggest_constraining_type_params(
164+
tcx,
165+
generics,
166+
&mut err,
167+
bounds.iter().map(|(param, constraint, def_id)| {
168+
(param.as_str(), constraint.as_str(), *def_id)
169+
}),
170+
);
171+
}
129172
err.emit();
130173
}
131174
Err(CopyImplementationError::NotAnAdt) => {

library/core/src/array/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ where
9292

9393
/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
9494
#[stable(feature = "array_from_ref", since = "1.53.0")]
95-
#[rustc_const_unstable(feature = "const_array_from_ref", issue = "90206")]
95+
#[rustc_const_stable(feature = "const_array_from_ref_shared", since = "1.63.0")]
9696
pub const fn from_ref<T>(s: &T) -> &[T; 1] {
9797
// SAFETY: Converting `&T` to `&[T; 1]` is sound.
9898
unsafe { &*(s as *const T).cast::<[T; 1]>() }

library/core/src/slice/raw.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m
144144

145145
/// Converts a reference to T into a slice of length 1 (without copying).
146146
#[stable(feature = "from_ref", since = "1.28.0")]
147-
#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")]
147+
#[rustc_const_stable(feature = "const_slice_from_ref_shared", since = "1.63.0")]
148148
#[must_use]
149149
pub const fn from_ref<T>(s: &T) -> &[T] {
150150
array::from_ref(s)

src/etc/htmldocck.py

+2
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
423423
else:
424424
actual_str = flatten(actual_tree)
425425

426+
expected_str = expected_str.replace("{{channel}}", channel)
427+
426428
# Conditions:
427429
# 1. Is --bless
428430
# 2. Are actual and expected tree different

0 commit comments

Comments
 (0)