Skip to content

Commit 2cfd644

Browse files
committed
Auto merge of #58673 - matthewjasper:typeck-ptr-coercions, r=pnkfelix
[NLL] Type check operations with pointer types It seems these were forgotten about. Moving to `Rvalue::AddressOf` simplifies the coercions from references, but I want this to be fixed as soon as possible. r? @pnkfelix
2 parents c0086b9 + 19a54e8 commit 2cfd644

18 files changed

+408
-16
lines changed

src/librustc/ich/impls_mir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ impl_stable_hash_for!(enum mir::CastKind {
378378
ReifyFnPointer,
379379
ClosureFnPointer,
380380
UnsafeFnPointer,
381+
MutToConstPointer,
381382
Unsize
382383
});
383384

src/librustc/mir/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,9 @@ pub enum CastKind {
22372237
/// Converts safe fn() to unsafe fn()
22382238
UnsafeFnPointer,
22392239

2240+
/// Coerces *mut T to *const T, preserving T.
2241+
MutToConstPointer,
2242+
22402243
/// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
22412244
/// codegen must figure out the details once full monomorphization
22422245
/// is known. For example, this could be used to cast from a

src/librustc/ty/context.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ use std::hash::{Hash, Hasher};
5959
use std::fmt;
6060
use std::mem;
6161
use std::ops::{Deref, Bound};
62-
use std::ptr;
6362
use std::iter;
6463
use std::sync::mpsc;
6564
use std::sync::Arc;
@@ -171,7 +170,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
171170

172171
// Make sure we don't end up with inference
173172
// types/regions in the global interner
174-
if ptr::eq(local, global) {
173+
if ptr_eq(local, global) {
175174
bug!("Attempted to intern `{:?}` which contains \
176175
inference types/regions in the global type context",
177176
&ty_struct);
@@ -1163,7 +1162,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11631162

11641163
/// Returns `true` if self is the same as self.global_tcx().
11651164
fn is_global(self) -> bool {
1166-
ptr::eq(self.interners, &self.global_interners)
1165+
ptr_eq(self.interners, &self.global_interners)
11671166
}
11681167

11691168
/// Creates a type context and call the closure with a `TyCtxt` reference
@@ -1817,12 +1816,11 @@ impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation {
18171816
}
18181817

18191818
pub mod tls {
1820-
use super::{GlobalCtxt, TyCtxt};
1819+
use super::{GlobalCtxt, TyCtxt, ptr_eq};
18211820

18221821
use std::fmt;
18231822
use std::mem;
18241823
use std::marker::PhantomData;
1825-
use std::ptr;
18261824
use syntax_pos;
18271825
use crate::ty::query;
18281826
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
@@ -2065,7 +2063,7 @@ pub mod tls {
20652063
{
20662064
with_context(|context| {
20672065
unsafe {
2068-
assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
2066+
assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
20692067
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
20702068
f(context)
20712069
}
@@ -2083,8 +2081,8 @@ pub mod tls {
20832081
{
20842082
with_context(|context| {
20852083
unsafe {
2086-
assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
2087-
assert!(ptr::eq(context.tcx.interners, tcx.interners));
2084+
assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
2085+
assert!(ptr_eq(context.tcx.interners, tcx.interners));
20882086
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
20892087
f(context)
20902088
}
@@ -2970,6 +2968,12 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
29702968
}
29712969
}
29722970

2971+
// We are comparing types with different invariant lifetimes, so `ptr::eq`
2972+
// won't work for us.
2973+
fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
2974+
t as *const () == u as *const ()
2975+
}
2976+
29732977
pub fn provide(providers: &mut ty::query::Providers<'_>) {
29742978
providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
29752979
providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();

src/librustc_codegen_ssa/mir/rvalue.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
257257
}
258258
}
259259
}
260-
mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
260+
mir::CastKind::MutToConstPointer
261+
| mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
261262
if let OperandValue::Pair(data_ptr, meta) = operand.val {
262263
if bx.cx().is_backend_scalar_pair(cast) {
263264
let data_cast = bx.pointercast(data_ptr,
@@ -274,7 +275,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
274275
bug!("Unexpected non-Pair operand")
275276
}
276277
}
277-
mir::CastKind::Misc => {
278+
mir::CastKind::MutToConstPointer
279+
| mir::CastKind::Misc => {
278280
assert!(bx.cx().is_backend_immediate(cast));
279281
let ll_t_out = bx.cx().immediate_backend_type(cast);
280282
if operand.layout.abi.is_uninhabited() {

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

+151-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc::hir::def_id::DefId;
2727
use rustc::infer::canonical::QueryRegionConstraint;
2828
use rustc::infer::outlives::env::RegionBoundPairs;
2929
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
30+
use rustc::infer::type_variable::TypeVariableOrigin;
3031
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
3132
use rustc::mir::tcx::PlaceTy;
3233
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
@@ -2074,15 +2075,163 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
20742075
);
20752076
}
20762077

2077-
CastKind::Misc => {}
2078+
CastKind::MutToConstPointer => {
2079+
let ty_from = match op.ty(mir, tcx).sty {
2080+
ty::RawPtr(ty::TypeAndMut {
2081+
ty: ty_from,
2082+
mutbl: hir::MutMutable,
2083+
}) => ty_from,
2084+
_ => {
2085+
span_mirbug!(
2086+
self,
2087+
rvalue,
2088+
"unexpected base type for cast {:?}",
2089+
ty,
2090+
);
2091+
return;
2092+
}
2093+
};
2094+
let ty_to = match ty.sty {
2095+
ty::RawPtr(ty::TypeAndMut {
2096+
ty: ty_to,
2097+
mutbl: hir::MutImmutable,
2098+
}) => ty_to,
2099+
_ => {
2100+
span_mirbug!(
2101+
self,
2102+
rvalue,
2103+
"unexpected target type for cast {:?}",
2104+
ty,
2105+
);
2106+
return;
2107+
}
2108+
};
2109+
if let Err(terr) = self.sub_types(
2110+
ty_from,
2111+
ty_to,
2112+
location.to_locations(),
2113+
ConstraintCategory::Cast,
2114+
) {
2115+
span_mirbug!(
2116+
self,
2117+
rvalue,
2118+
"relating {:?} with {:?} yields {:?}",
2119+
ty_from,
2120+
ty_to,
2121+
terr
2122+
)
2123+
}
2124+
}
2125+
2126+
CastKind::Misc => {
2127+
if let ty::Ref(_, mut ty_from, _) = op.ty(mir, tcx).sty {
2128+
let (mut ty_to, mutability) = if let ty::RawPtr(ty::TypeAndMut {
2129+
ty: ty_to,
2130+
mutbl,
2131+
}) = ty.sty {
2132+
(ty_to, mutbl)
2133+
} else {
2134+
span_mirbug!(
2135+
self,
2136+
rvalue,
2137+
"invalid cast types {:?} -> {:?}",
2138+
op.ty(mir, tcx),
2139+
ty,
2140+
);
2141+
return;
2142+
};
2143+
2144+
// Handle the direct cast from `&[T; N]` to `*const T` by unwrapping
2145+
// any array we find.
2146+
while let ty::Array(ty_elem_from, _) = ty_from.sty {
2147+
ty_from = ty_elem_from;
2148+
if let ty::Array(ty_elem_to, _) = ty_to.sty {
2149+
ty_to = ty_elem_to;
2150+
} else {
2151+
break;
2152+
}
2153+
}
2154+
2155+
if let hir::MutMutable = mutability {
2156+
if let Err(terr) = self.eq_types(
2157+
ty_from,
2158+
ty_to,
2159+
location.to_locations(),
2160+
ConstraintCategory::Cast,
2161+
) {
2162+
span_mirbug!(
2163+
self,
2164+
rvalue,
2165+
"equating {:?} with {:?} yields {:?}",
2166+
ty_from,
2167+
ty_to,
2168+
terr
2169+
)
2170+
}
2171+
} else {
2172+
if let Err(terr) = self.sub_types(
2173+
ty_from,
2174+
ty_to,
2175+
location.to_locations(),
2176+
ConstraintCategory::Cast,
2177+
) {
2178+
span_mirbug!(
2179+
self,
2180+
rvalue,
2181+
"relating {:?} with {:?} yields {:?}",
2182+
ty_from,
2183+
ty_to,
2184+
terr
2185+
)
2186+
}
2187+
}
2188+
}
2189+
}
20782190
}
20792191
}
20802192

20812193
Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
20822194
self.add_reborrow_constraint(mir, location, region, borrowed_place);
20832195
}
20842196

2085-
// FIXME: These other cases have to be implemented in future PRs
2197+
Rvalue::BinaryOp(BinOp::Eq, left, right)
2198+
| Rvalue::BinaryOp(BinOp::Ne, left, right)
2199+
| Rvalue::BinaryOp(BinOp::Lt, left, right)
2200+
| Rvalue::BinaryOp(BinOp::Le, left, right)
2201+
| Rvalue::BinaryOp(BinOp::Gt, left, right)
2202+
| Rvalue::BinaryOp(BinOp::Ge, left, right) => {
2203+
let ty_left = left.ty(mir, tcx);
2204+
if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.sty {
2205+
let ty_right = right.ty(mir, tcx);
2206+
let common_ty = self.infcx.next_ty_var(
2207+
TypeVariableOrigin::MiscVariable(mir.source_info(location).span),
2208+
);
2209+
self.sub_types(
2210+
common_ty,
2211+
ty_left,
2212+
location.to_locations(),
2213+
ConstraintCategory::Boring
2214+
).unwrap_or_else(|err| {
2215+
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
2216+
});
2217+
if let Err(terr) = self.sub_types(
2218+
common_ty,
2219+
ty_right,
2220+
location.to_locations(),
2221+
ConstraintCategory::Boring
2222+
) {
2223+
span_mirbug!(
2224+
self,
2225+
rvalue,
2226+
"unexpected comparison types {:?} and {:?} yields {:?}",
2227+
ty_left,
2228+
ty_right,
2229+
terr
2230+
)
2231+
}
2232+
}
2233+
}
2234+
20862235
Rvalue::Use(..)
20872236
| Rvalue::Len(..)
20882237
| Rvalue::BinaryOp(..)

src/librustc_mir/build/expr/as_place.rs

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
196196
| ExprKind::ReifyFnPointer { .. }
197197
| ExprKind::ClosureFnPointer { .. }
198198
| ExprKind::UnsafeFnPointer { .. }
199+
| ExprKind::MutToConstPointer { .. }
199200
| ExprKind::Unsize { .. }
200201
| ExprKind::Repeat { .. }
201202
| ExprKind::Borrow { .. }

src/librustc_mir/build/expr/as_rvalue.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
147147
block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
148148
}
149149
ExprKind::Cast { source } => {
150-
let source = this.hir.mirror(source);
151-
152150
let source = unpack!(block = this.as_operand(block, scope, source));
153151
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
154152
}
@@ -168,6 +166,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
168166
let source = unpack!(block = this.as_operand(block, scope, source));
169167
block.and(Rvalue::Cast(CastKind::ClosureFnPointer, source, expr.ty))
170168
}
169+
ExprKind::MutToConstPointer { source } => {
170+
let source = unpack!(block = this.as_operand(block, scope, source));
171+
block.and(Rvalue::Cast(CastKind::MutToConstPointer, source, expr.ty))
172+
}
171173
ExprKind::Unsize { source } => {
172174
let source = unpack!(block = this.as_operand(block, scope, source));
173175
block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty))

src/librustc_mir/build/expr/category.rs

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl Category {
6262
| ExprKind::ReifyFnPointer { .. }
6363
| ExprKind::ClosureFnPointer { .. }
6464
| ExprKind::UnsafeFnPointer { .. }
65+
| ExprKind::MutToConstPointer { .. }
6566
| ExprKind::Unsize { .. }
6667
| ExprKind::Repeat { .. }
6768
| ExprKind::Borrow { .. }

src/librustc_mir/build/expr/into.rs

+1
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
383383
| ExprKind::ReifyFnPointer { .. }
384384
| ExprKind::ClosureFnPointer { .. }
385385
| ExprKind::UnsafeFnPointer { .. }
386+
| ExprKind::MutToConstPointer { .. }
386387
| ExprKind::Unsize { .. }
387388
| ExprKind::Repeat { .. }
388389
| ExprKind::Borrow { .. }

src/librustc_mir/hair/cx/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
8989
ExprKind::NeverToAny { source: expr.to_ref() }
9090
}
9191
Adjust::MutToConstPointer => {
92-
ExprKind::Cast { source: expr.to_ref() }
92+
ExprKind::MutToConstPointer { source: expr.to_ref() }
9393
}
9494
Adjust::Deref(None) => {
9595
// Adjust the span from the block, to the last expression of the

src/librustc_mir/hair/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ pub enum ExprKind<'tcx> {
190190
UnsafeFnPointer {
191191
source: ExprRef<'tcx>,
192192
},
193+
MutToConstPointer {
194+
source: ExprRef<'tcx>,
195+
},
193196
Unsize {
194197
source: ExprRef<'tcx>,
195198
},

src/librustc_mir/interpret/cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
3333
self.unsize_into(src, dest)?;
3434
}
3535

36-
Misc => {
36+
Misc | MutToConstPointer => {
3737
let src = self.read_immediate(src)?;
3838

3939
if self.type_is_fat_ptr(src.layout.ty) {

src/librustc_mir/transform/qualify_consts.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
10951095
Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
10961096
Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
10971097
Rvalue::Cast(CastKind::Unsize, ..) |
1098+
Rvalue::Cast(CastKind::MutToConstPointer, ..) |
10981099
Rvalue::Discriminant(..) |
10991100
Rvalue::Len(_) |
11001101
Rvalue::Ref(..) |

src/librustc_mir/transform/qualify_min_const_fn.rs

+3
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ fn check_rvalue(
152152
_ => check_operand(tcx, mir, operand, span),
153153
}
154154
}
155+
Rvalue::Cast(CastKind::MutToConstPointer, operand, _) => {
156+
check_operand(tcx, mir, operand, span)
157+
}
155158
Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
156159
Rvalue::Cast(CastKind::ClosureFnPointer, _, _) |
157160
Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((

0 commit comments

Comments
 (0)