Skip to content

Commit

Permalink
Auto merge of #58673 - matthewjasper:typeck-ptr-coercions, r=pnkfelix
Browse files Browse the repository at this point in the history
[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
  • Loading branch information
bors committed Mar 3, 2019
2 parents c0086b9 + 19a54e8 commit 2cfd644
Show file tree
Hide file tree
Showing 18 changed files with 408 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ impl_stable_hash_for!(enum mir::CastKind {
ReifyFnPointer,
ClosureFnPointer,
UnsafeFnPointer,
MutToConstPointer,
Unsize
});

Expand Down
3 changes: 3 additions & 0 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2237,6 +2237,9 @@ pub enum CastKind {
/// Converts safe fn() to unsafe fn()
UnsafeFnPointer,

/// Coerces *mut T to *const T, preserving T.
MutToConstPointer,

/// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
/// codegen must figure out the details once full monomorphization
/// is known. For example, this could be used to cast from a
Expand Down
20 changes: 12 additions & 8 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ use std::hash::{Hash, Hasher};
use std::fmt;
use std::mem;
use std::ops::{Deref, Bound};
use std::ptr;
use std::iter;
use std::sync::mpsc;
use std::sync::Arc;
Expand Down Expand Up @@ -171,7 +170,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {

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

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

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

pub mod tls {
use super::{GlobalCtxt, TyCtxt};
use super::{GlobalCtxt, TyCtxt, ptr_eq};

use std::fmt;
use std::mem;
use std::marker::PhantomData;
use std::ptr;
use syntax_pos;
use crate::ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
Expand Down Expand Up @@ -2065,7 +2063,7 @@ pub mod tls {
{
with_context(|context| {
unsafe {
assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
Expand All @@ -2083,8 +2081,8 @@ pub mod tls {
{
with_context(|context| {
unsafe {
assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
assert!(ptr::eq(context.tcx.interners, tcx.interners));
assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
assert!(ptr_eq(context.tcx.interners, tcx.interners));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
Expand Down Expand Up @@ -2970,6 +2968,12 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
}
}

// We are comparing types with different invariant lifetimes, so `ptr::eq`
// won't work for us.
fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
t as *const () == u as *const ()
}

pub fn provide(providers: &mut ty::query::Providers<'_>) {
providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
}
mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
mir::CastKind::MutToConstPointer
| mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
if let OperandValue::Pair(data_ptr, meta) = operand.val {
if bx.cx().is_backend_scalar_pair(cast) {
let data_cast = bx.pointercast(data_ptr,
Expand All @@ -274,7 +275,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bug!("Unexpected non-Pair operand")
}
}
mir::CastKind::Misc => {
mir::CastKind::MutToConstPointer
| mir::CastKind::Misc => {
assert!(bx.cx().is_backend_immediate(cast));
let ll_t_out = bx.cx().immediate_backend_type(cast);
if operand.layout.abi.is_uninhabited() {
Expand Down
153 changes: 151 additions & 2 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use rustc::hir::def_id::DefId;
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
use rustc::mir::tcx::PlaceTy;
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
Expand Down Expand Up @@ -2074,15 +2075,163 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
);
}

CastKind::Misc => {}
CastKind::MutToConstPointer => {
let ty_from = match op.ty(mir, tcx).sty {
ty::RawPtr(ty::TypeAndMut {
ty: ty_from,
mutbl: hir::MutMutable,
}) => ty_from,
_ => {
span_mirbug!(
self,
rvalue,
"unexpected base type for cast {:?}",
ty,
);
return;
}
};
let ty_to = match ty.sty {
ty::RawPtr(ty::TypeAndMut {
ty: ty_to,
mutbl: hir::MutImmutable,
}) => ty_to,
_ => {
span_mirbug!(
self,
rvalue,
"unexpected target type for cast {:?}",
ty,
);
return;
}
};
if let Err(terr) = self.sub_types(
ty_from,
ty_to,
location.to_locations(),
ConstraintCategory::Cast,
) {
span_mirbug!(
self,
rvalue,
"relating {:?} with {:?} yields {:?}",
ty_from,
ty_to,
terr
)
}
}

CastKind::Misc => {
if let ty::Ref(_, mut ty_from, _) = op.ty(mir, tcx).sty {
let (mut ty_to, mutability) = if let ty::RawPtr(ty::TypeAndMut {
ty: ty_to,
mutbl,
}) = ty.sty {
(ty_to, mutbl)
} else {
span_mirbug!(
self,
rvalue,
"invalid cast types {:?} -> {:?}",
op.ty(mir, tcx),
ty,
);
return;
};

// Handle the direct cast from `&[T; N]` to `*const T` by unwrapping
// any array we find.
while let ty::Array(ty_elem_from, _) = ty_from.sty {
ty_from = ty_elem_from;
if let ty::Array(ty_elem_to, _) = ty_to.sty {
ty_to = ty_elem_to;
} else {
break;
}
}

if let hir::MutMutable = mutability {
if let Err(terr) = self.eq_types(
ty_from,
ty_to,
location.to_locations(),
ConstraintCategory::Cast,
) {
span_mirbug!(
self,
rvalue,
"equating {:?} with {:?} yields {:?}",
ty_from,
ty_to,
terr
)
}
} else {
if let Err(terr) = self.sub_types(
ty_from,
ty_to,
location.to_locations(),
ConstraintCategory::Cast,
) {
span_mirbug!(
self,
rvalue,
"relating {:?} with {:?} yields {:?}",
ty_from,
ty_to,
terr
)
}
}
}
}
}
}

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

// FIXME: These other cases have to be implemented in future PRs
Rvalue::BinaryOp(BinOp::Eq, left, right)
| Rvalue::BinaryOp(BinOp::Ne, left, right)
| Rvalue::BinaryOp(BinOp::Lt, left, right)
| Rvalue::BinaryOp(BinOp::Le, left, right)
| Rvalue::BinaryOp(BinOp::Gt, left, right)
| Rvalue::BinaryOp(BinOp::Ge, left, right) => {
let ty_left = left.ty(mir, tcx);
if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.sty {
let ty_right = right.ty(mir, tcx);
let common_ty = self.infcx.next_ty_var(
TypeVariableOrigin::MiscVariable(mir.source_info(location).span),
);
self.sub_types(
common_ty,
ty_left,
location.to_locations(),
ConstraintCategory::Boring
).unwrap_or_else(|err| {
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
});
if let Err(terr) = self.sub_types(
common_ty,
ty_right,
location.to_locations(),
ConstraintCategory::Boring
) {
span_mirbug!(
self,
rvalue,
"unexpected comparison types {:?} and {:?} yields {:?}",
ty_left,
ty_right,
terr
)
}
}
}

Rvalue::Use(..)
| Rvalue::Len(..)
| Rvalue::BinaryOp(..)
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
| ExprKind::ReifyFnPointer { .. }
| ExprKind::ClosureFnPointer { .. }
| ExprKind::UnsafeFnPointer { .. }
| ExprKind::MutToConstPointer { .. }
| ExprKind::Unsize { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
}
ExprKind::Cast { source } => {
let source = this.hir.mirror(source);

let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
}
Expand All @@ -168,6 +166,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::ClosureFnPointer, source, expr.ty))
}
ExprKind::MutToConstPointer { source } => {
let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::MutToConstPointer, source, expr.ty))
}
ExprKind::Unsize { source } => {
let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty))
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/build/expr/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl Category {
| ExprKind::ReifyFnPointer { .. }
| ExprKind::ClosureFnPointer { .. }
| ExprKind::UnsafeFnPointer { .. }
| ExprKind::MutToConstPointer { .. }
| ExprKind::Unsize { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
| ExprKind::ReifyFnPointer { .. }
| ExprKind::ClosureFnPointer { .. }
| ExprKind::UnsafeFnPointer { .. }
| ExprKind::MutToConstPointer { .. }
| ExprKind::Unsize { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/hair/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ExprKind::NeverToAny { source: expr.to_ref() }
}
Adjust::MutToConstPointer => {
ExprKind::Cast { source: expr.to_ref() }
ExprKind::MutToConstPointer { source: expr.to_ref() }
}
Adjust::Deref(None) => {
// Adjust the span from the block, to the last expression of the
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_mir/hair/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ pub enum ExprKind<'tcx> {
UnsafeFnPointer {
source: ExprRef<'tcx>,
},
MutToConstPointer {
source: ExprRef<'tcx>,
},
Unsize {
source: ExprRef<'tcx>,
},
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
self.unsize_into(src, dest)?;
}

Misc => {
Misc | MutToConstPointer => {
let src = self.read_immediate(src)?;

if self.type_is_fat_ptr(src.layout.ty) {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
Rvalue::Cast(CastKind::Unsize, ..) |
Rvalue::Cast(CastKind::MutToConstPointer, ..) |
Rvalue::Discriminant(..) |
Rvalue::Len(_) |
Rvalue::Ref(..) |
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_mir/transform/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ fn check_rvalue(
_ => check_operand(tcx, mir, operand, span),
}
}
Rvalue::Cast(CastKind::MutToConstPointer, operand, _) => {
check_operand(tcx, mir, operand, span)
}
Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
Rvalue::Cast(CastKind::ClosureFnPointer, _, _) |
Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
Expand Down
Loading

0 comments on commit 2cfd644

Please sign in to comment.