Skip to content

Commit 401d9e1

Browse files
authored
Rollup merge of rust-lang#65831 - matthewjasper:array-ptr-cast, r=oli-obk
Don't cast directly from &[T; N] to *const T Split out from rust-lang#64588 r? @oli-obk
2 parents e88aa39 + 972c3be commit 401d9e1

File tree

7 files changed

+131
-56
lines changed

7 files changed

+131
-56
lines changed

src/librustc/ty/adjustment.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub enum PointerCast {
2020
/// Go from a mut raw pointer to a const raw pointer.
2121
MutToConstPointer,
2222

23+
/// Go from `*const [T; N]` to `*const T`
24+
ArrayToPointer,
25+
2326
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
2427
/// `&[T]`. Note that the source could be a thin or fat pointer.
2528
/// This will do things like convert thin pointers to fat

src/librustc_codegen_ssa/mir/rvalue.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
269269
}
270270
}
271271
mir::CastKind::Pointer(PointerCast::MutToConstPointer)
272+
| mir::CastKind::Pointer(PointerCast::ArrayToPointer)
272273
| mir::CastKind::Misc => {
273274
assert!(bx.cx().is_backend_immediate(cast));
274275
let ll_t_out = bx.cx().immediate_backend_type(cast);

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 108 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
3636
use rustc::traits::query::{Fallible, NoSolution};
3737
use rustc::traits::{self, ObligationCause, PredicateObligations};
3838
use rustc::ty::adjustment::{PointerCast};
39+
use rustc::ty::cast::CastTy;
3940
use rustc::ty::fold::TypeFoldable;
4041
use rustc::ty::subst::{Subst, SubstsRef, GenericArgKind, UserSubsts};
4142
use rustc::ty::{
@@ -2177,72 +2178,125 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21772178
ty_from,
21782179
ty_to,
21792180
terr
2180-
)
2181+
);
21812182
}
21822183
}
21832184

2184-
CastKind::Misc => {
2185-
if let ty::Ref(_, mut ty_from, _) = op.ty(body, tcx).kind {
2186-
let (mut ty_to, mutability) = if let ty::RawPtr(ty::TypeAndMut {
2187-
ty: ty_to,
2188-
mutbl,
2189-
}) = ty.kind {
2190-
(ty_to, mutbl)
2191-
} else {
2185+
CastKind::Pointer(PointerCast::ArrayToPointer) => {
2186+
let ty_from = op.ty(body, tcx);
2187+
2188+
let opt_ty_elem = match ty_from.kind {
2189+
ty::RawPtr(
2190+
ty::TypeAndMut { mutbl: hir::MutImmutable, ty: array_ty }
2191+
) => {
2192+
match array_ty.kind {
2193+
ty::Array(ty_elem, _) => Some(ty_elem),
2194+
_ => None,
2195+
}
2196+
}
2197+
_ => None,
2198+
};
2199+
2200+
let ty_elem = match opt_ty_elem {
2201+
Some(ty_elem) => ty_elem,
2202+
None => {
21922203
span_mirbug!(
21932204
self,
21942205
rvalue,
2195-
"invalid cast types {:?} -> {:?}",
2196-
op.ty(body, tcx),
2206+
"ArrayToPointer cast from unexpected type {:?}",
2207+
ty_from,
2208+
);
2209+
return;
2210+
}
2211+
};
2212+
2213+
let ty_to = match ty.kind {
2214+
ty::RawPtr(
2215+
ty::TypeAndMut { mutbl: hir::MutImmutable, ty: ty_to }
2216+
) => {
2217+
ty_to
2218+
}
2219+
_ => {
2220+
span_mirbug!(
2221+
self,
2222+
rvalue,
2223+
"ArrayToPointer cast to unexpected type {:?}",
21972224
ty,
21982225
);
21992226
return;
2200-
};
2201-
2202-
// Handle the direct cast from `&[T; N]` to `*const T` by unwrapping
2203-
// any array we find.
2204-
while let ty::Array(ty_elem_from, _) = ty_from.kind {
2205-
ty_from = ty_elem_from;
2206-
if let ty::Array(ty_elem_to, _) = ty_to.kind {
2207-
ty_to = ty_elem_to;
2208-
} else {
2209-
break;
2210-
}
22112227
}
2228+
};
22122229

2213-
if let hir::MutMutable = mutability {
2214-
if let Err(terr) = self.eq_types(
2215-
ty_from,
2216-
ty_to,
2217-
location.to_locations(),
2218-
ConstraintCategory::Cast,
2219-
) {
2220-
span_mirbug!(
2221-
self,
2222-
rvalue,
2223-
"equating {:?} with {:?} yields {:?}",
2224-
ty_from,
2225-
ty_to,
2226-
terr
2227-
)
2228-
}
2229-
} else {
2230-
if let Err(terr) = self.sub_types(
2231-
ty_from,
2232-
ty_to,
2233-
location.to_locations(),
2234-
ConstraintCategory::Cast,
2235-
) {
2236-
span_mirbug!(
2237-
self,
2238-
rvalue,
2239-
"relating {:?} with {:?} yields {:?}",
2240-
ty_from,
2241-
ty_to,
2242-
terr
2243-
)
2230+
if let Err(terr) = self.sub_types(
2231+
ty_elem,
2232+
ty_to,
2233+
location.to_locations(),
2234+
ConstraintCategory::Cast,
2235+
) {
2236+
span_mirbug!(
2237+
self,
2238+
rvalue,
2239+
"relating {:?} with {:?} yields {:?}",
2240+
ty_elem,
2241+
ty_to,
2242+
terr
2243+
)
2244+
}
2245+
}
2246+
2247+
CastKind::Misc => {
2248+
let ty_from = op.ty(body, tcx);
2249+
let cast_ty_from = CastTy::from_ty(ty_from);
2250+
let cast_ty_to = CastTy::from_ty(ty);
2251+
match (cast_ty_from, cast_ty_to) {
2252+
(Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => {
2253+
if let hir::MutMutable = ptr_tm.mutbl {
2254+
if let Err(terr) = self.eq_types(
2255+
ref_tm.ty,
2256+
ptr_tm.ty,
2257+
location.to_locations(),
2258+
ConstraintCategory::Cast,
2259+
) {
2260+
span_mirbug!(
2261+
self,
2262+
rvalue,
2263+
"equating {:?} with {:?} yields {:?}",
2264+
ref_tm.ty,
2265+
ptr_tm.ty,
2266+
terr
2267+
)
2268+
}
2269+
} else {
2270+
if let Err(terr) = self.sub_types(
2271+
ref_tm.ty,
2272+
ptr_tm.ty,
2273+
location.to_locations(),
2274+
ConstraintCategory::Cast,
2275+
) {
2276+
span_mirbug!(
2277+
self,
2278+
rvalue,
2279+
"relating {:?} with {:?} yields {:?}",
2280+
ref_tm.ty,
2281+
ptr_tm.ty,
2282+
terr
2283+
)
2284+
}
22442285
}
2245-
}
2286+
},
2287+
(None, _)
2288+
| (_, None)
2289+
| (_, Some(CastTy::FnPtr))
2290+
| (Some(CastTy::Float), Some(CastTy::Ptr(_)))
2291+
| (Some(CastTy::Ptr(_)), Some(CastTy::Float))
2292+
| (Some(CastTy::FnPtr), Some(CastTy::Float)) => span_mirbug!(
2293+
self,
2294+
rvalue,
2295+
"Invalid cast {:?} -> {:?}",
2296+
ty_from,
2297+
ty,
2298+
),
2299+
_ => (),
22462300
}
22472301
}
22482302
}

src/librustc_mir/hair/cx/expr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
628628
let cast = if cx.tables().is_coercion_cast(source.hir_id) {
629629
// Convert the lexpr to a vexpr.
630630
ExprKind::Use { source: source.to_ref() }
631+
} else if cx.tables().expr_ty(source).is_region_ptr() {
632+
// Special cased so that we can type check that the element
633+
// type of the source matches the pointed to type of the
634+
// destination.
635+
ExprKind::Pointer { source: source.to_ref(), cast: PointerCast::ArrayToPointer }
631636
} else {
632637
// check whether this is casting an enum variant discriminant
633638
// to prevent cycles, we refer to the discriminant initializer

src/librustc_mir/interpret/cast.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
2626
self.unsize_into(src, dest)?;
2727
}
2828

29-
Misc | Pointer(PointerCast::MutToConstPointer) => {
29+
Misc
30+
| Pointer(PointerCast::MutToConstPointer)
31+
| Pointer(PointerCast::ArrayToPointer) => {
3032
let src = self.read_immediate(src)?;
3133
let res = self.cast_immediate(src, dest.layout)?;
3234
self.write_immediate(res, dest)?;

src/librustc_mir/transform/qualify_min_const_fn.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ fn check_rvalue(
150150
_ => check_operand(tcx, operand, span, def_id, body),
151151
}
152152
}
153-
Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _) => {
153+
Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _)
154+
| Rvalue::Cast(CastKind::Pointer(PointerCast::ArrayToPointer), operand, _) => {
154155
check_operand(tcx, operand, span, def_id, body)
155156
}
156157
Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), _, _) |

src/librustc_typeck/check/cast.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
636636
// need to special-case obtaining a raw pointer
637637
// from a region pointer to a vector.
638638

639+
// Coerce to a raw pointer so that we generate AddressOf in MIR.
640+
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
641+
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
642+
.unwrap_or_else(|_| bug!(
643+
"could not cast from reference to array to pointer to array ({:?} to {:?})",
644+
self.expr_ty,
645+
array_ptr_type,
646+
));
647+
639648
// this will report a type mismatch if needed
640649
fcx.demand_eqtype(self.span, ety, m_cast.ty);
641650
return Ok(CastKind::ArrayPtrCast);

0 commit comments

Comments
 (0)