debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
match adjustment.kind {
adjustment::Adjust::NeverToAny |
- adjustment::Adjust::ReifyFnPointer |
- adjustment::Adjust::UnsafeFnPointer |
- adjustment::Adjust::ClosureFnPointer(_) |
- adjustment::Adjust::MutToConstPointer |
- adjustment::Adjust::Unsize => {
+ adjustment::Adjust::Pointer(_) => {
// Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue.
self.delegate_consume(expr.hir_id, expr.span, &cmt);
}
adjustment::Adjust::NeverToAny |
- adjustment::Adjust::ReifyFnPointer |
- adjustment::Adjust::UnsafeFnPointer |
- adjustment::Adjust::ClosureFnPointer(_) |
- adjustment::Adjust::MutToConstPointer |
- adjustment::Adjust::Borrow(_) |
- adjustment::Adjust::Unsize => {
+ adjustment::Adjust::Pointer(_) |
+ adjustment::Adjust::Borrow(_) => {
// Result is an rvalue.
Ok(self.cat_rvalue_node(expr.hir_id, expr.span, target))
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
pub enum PointerCast {
+ /// Go from a fn-item type to a fn-pointer type.
ReifyFnPointer,
+
+ /// Go from a safe fn pointer to an unsafe fn pointer.
UnsafeFnPointer,
+
+ /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
+ /// It cannot convert a closure that requires unsafe.
ClosureFnPointer(hir::Unsafety),
+
+ /// Go from a mut raw pointer to a const raw pointer.
MutToConstPointer,
+
+ /// Unsize a pointer/reference value, e.g., `&[T; n]` to
+ /// `&[T]`. Note that the source could be a thin or fat pointer.
+ /// This will do things like convert thin pointers to fat
+ /// pointers, or convert structs containing thin pointers to
+ /// structs containing fat pointers, or convert between fat
+ /// pointers. We don't store the details of how the transform is
+ /// done (in fact, we don't know that, because it might depend on
+ /// the precise type parameters). We just store the target
+ /// type. Codegen backends and miri figure out what has to be done
+ /// based on the precise source/target type at hand.
Unsize,
}
/// Go from ! to any type.
NeverToAny,
- /// Go from a fn-item type to a fn-pointer type.
- ReifyFnPointer,
-
- /// Go from a safe fn pointer to an unsafe fn pointer.
- UnsafeFnPointer,
-
- /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
- /// It cannot convert a closure that requires unsafe.
- ClosureFnPointer(hir::Unsafety),
-
- /// Go from a mut raw pointer to a const raw pointer.
- MutToConstPointer,
-
/// Dereference once, producing a place.
Deref(Option<OverloadedDeref<'tcx>>),
/// Take the address and produce either a `&` or `*` pointer.
Borrow(AutoBorrow<'tcx>),
- /// Unsize a pointer/reference value, e.g., `&[T; n]` to
- /// `&[T]`. Note that the source could be a thin or fat pointer.
- /// This will do things like convert thin pointers to fat
- /// pointers, or convert structs containing thin pointers to
- /// structs containing fat pointers, or convert between fat
- /// pointers. We don't store the details of how the transform is
- /// done (in fact, we don't know that, because it might depend on
- /// the precise type parameters). We just store the target
- /// type. Codegen backends and miri figure out what has to be done
- /// based on the precise source/target type at hand.
- Unsize,
+ Pointer(PointerCast),
}
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
use crate::mir::ProjectionKind;
use crate::mir::interpret::ConstValue;
use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid};
+use crate::ty::adjustment::{PointerCast};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::print::{FmtPrinter, Printer};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
match *self {
ty::adjustment::Adjust::NeverToAny =>
Some(ty::adjustment::Adjust::NeverToAny),
- ty::adjustment::Adjust::ReifyFnPointer =>
- Some(ty::adjustment::Adjust::ReifyFnPointer),
- ty::adjustment::Adjust::UnsafeFnPointer =>
- Some(ty::adjustment::Adjust::UnsafeFnPointer),
- ty::adjustment::Adjust::ClosureFnPointer(unsafety) =>
- Some(ty::adjustment::Adjust::ClosureFnPointer(unsafety)),
- ty::adjustment::Adjust::MutToConstPointer =>
- Some(ty::adjustment::Adjust::MutToConstPointer),
- ty::adjustment::Adjust::Unsize =>
- Some(ty::adjustment::Adjust::Unsize),
+ ty::adjustment::Adjust::Pointer(PointerCast::ReifyFnPointer) =>
+ Some(ty::adjustment::Adjust::Pointer(PointerCast::ReifyFnPointer)),
+ ty::adjustment::Adjust::Pointer(PointerCast::UnsafeFnPointer) =>
+ Some(ty::adjustment::Adjust::Pointer(PointerCast::UnsafeFnPointer)),
+ ty::adjustment::Adjust::Pointer(PointerCast::ClosureFnPointer(unsafety)) =>
+ Some(ty::adjustment::Adjust::Pointer(PointerCast::ClosureFnPointer(unsafety))),
+ ty::adjustment::Adjust::Pointer(PointerCast::MutToConstPointer) =>
+ Some(ty::adjustment::Adjust::Pointer(PointerCast::MutToConstPointer)),
+ ty::adjustment::Adjust::Pointer(PointerCast::Unsize) =>
+ Some(ty::adjustment::Adjust::Pointer(PointerCast::Unsize)),
ty::adjustment::Adjust::Deref(ref overloaded) => {
tcx.lift(overloaded).map(ty::adjustment::Adjust::Deref)
}
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
(ty::adjustment::Adjust::NeverToAny),
- (ty::adjustment::Adjust::ReifyFnPointer),
- (ty::adjustment::Adjust::UnsafeFnPointer),
- (ty::adjustment::Adjust::ClosureFnPointer)(a),
- (ty::adjustment::Adjust::MutToConstPointer),
- (ty::adjustment::Adjust::Unsize),
+ (ty::adjustment::Adjust::Pointer)(a),
(ty::adjustment::Adjust::Deref)(a),
(ty::adjustment::Adjust::Borrow)(a),
}
}
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::PointerCast {
+ (ty::adjustment::PointerCast::ReifyFnPointer),
+ (ty::adjustment::PointerCast::UnsafeFnPointer),
+ (ty::adjustment::PointerCast::ClosureFnPointer)(a),
+ (ty::adjustment::PointerCast::MutToConstPointer),
+ (ty::adjustment::PointerCast::Unsize),
+ }
+}
+
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::OverloadedDeref<'tcx> {
region, mutbl,
use rustc::hir::def::{CtorOf, Def, CtorKind};
use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
use rustc::ty::{self, AdtKind, Ty};
-use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
+use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast};
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::hir;
use rustc::hir::def_id::LocalDefId;
-> Expr<'tcx> {
let Expr { temp_lifetime, mut span, .. } = expr;
let kind = match adjustment.kind {
- Adjust::ReifyFnPointer => {
+ Adjust::Pointer(PointerCast::ReifyFnPointer) => {
ExprKind::ReifyFnPointer { source: expr.to_ref() }
}
- Adjust::UnsafeFnPointer => {
+ Adjust::Pointer(PointerCast::UnsafeFnPointer) => {
ExprKind::UnsafeFnPointer { source: expr.to_ref() }
}
- Adjust::ClosureFnPointer(unsafety) => {
+ Adjust::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
ExprKind::ClosureFnPointer { source: expr.to_ref(), unsafety }
}
Adjust::NeverToAny => {
ExprKind::NeverToAny { source: expr.to_ref() }
}
- Adjust::MutToConstPointer => {
+ Adjust::Pointer(PointerCast::MutToConstPointer) => {
ExprKind::MutToConstPointer { source: expr.to_ref() }
}
Adjust::Deref(None) => {
// since they get rid of a borrow implicitly.
ExprKind::Use { source: cast_expr.to_ref() }
}
- Adjust::Unsize => {
+ Adjust::Pointer(PointerCast::Unsize) => {
// See the above comment for Adjust::Deref
if let ExprKind::Block { body } = expr.kind {
if let Some(ref last_expr) = body.expr {
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::traits::{self, TraitEngine};
-use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, adjustment::{PointerCast}};
+use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
use rustc::ty::cast::CastTy;
use rustc::ty::query::Providers;
use rustc::mir::*;
Rvalue::UnaryOp(UnOp::Not, _) |
Rvalue::NullaryOp(NullOp::SizeOf, _) |
Rvalue::CheckedBinaryOp(..) |
- Rvalue::Cast(CastKind::Pointer(PointerCast::ReifyFnPointer), ..) |
- Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), ..) |
- Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), ..) |
- Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), ..) |
- Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), ..) |
+ Rvalue::Cast(CastKind::Pointer(_), ..) |
Rvalue::Discriminant(..) |
Rvalue::Len(_) |
Rvalue::Ref(..) |
while let Some(adjustment) = adjustments.next() {
match adjustment.kind {
Adjust::NeverToAny |
- Adjust::ReifyFnPointer |
- Adjust::UnsafeFnPointer |
- Adjust::ClosureFnPointer(_) |
- Adjust::MutToConstPointer |
- Adjust::Borrow(_) |
- Adjust::Unsize => {}
+ Adjust::Pointer(_) |
+ Adjust::Borrow(_) => {}
Adjust::Deref(_) => {
if let Some(next_adjustment) = adjustments.peek() {
use rustc::infer::{Coercion, InferResult, InferOk};
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
-use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
+use rustc::ty::adjustment::{
+ Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast
+};
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError;
let coerce_target = self.next_ty_var(origin);
let mut coercion = self.unify_and(coerce_target, target, |target| {
let unsize = Adjustment {
- kind: Adjust::Unsize,
+ kind: Adjust::Pointer(PointerCast::Unsize),
target
};
match reborrow {
debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
self.coerce_from_safe_fn(a, fn_ty_a, b,
- simple(Adjust::UnsafeFnPointer), identity)
+ simple(Adjust::Pointer(PointerCast::UnsafeFnPointer)), identity)
}
fn coerce_from_fn_item(&self,
b,
|unsafe_ty| {
vec![
- Adjustment { kind: Adjust::ReifyFnPointer, target: a_fn_pointer },
- Adjustment { kind: Adjust::UnsafeFnPointer, target: unsafe_ty },
+ Adjustment {
+ kind: Adjust::Pointer(PointerCast::ReifyFnPointer),
+ target: a_fn_pointer
+ },
+ Adjustment {
+ kind: Adjust::Pointer(PointerCast::UnsafeFnPointer),
+ target: unsafe_ty
+ },
]
},
- simple(Adjust::ReifyFnPointer)
+ simple(Adjust::Pointer(PointerCast::ReifyFnPointer))
)?;
obligations.extend(o2);
let pointer_ty = self.tcx.coerce_closure_fn_ty(sig, unsafety);
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
a, b, pointer_ty);
- self.unify_and(pointer_ty, b, simple(Adjust::ClosureFnPointer(unsafety)))
+ self.unify_and(pointer_ty, b, simple(
+ Adjust::Pointer(PointerCast::ClosureFnPointer(unsafety))
+ ))
}
_ => self.unify_and(a, b, identity),
}
}]
})
} else if mt_a.mutbl != mutbl_b {
- self.unify_and(a_unsafe, b, simple(Adjust::MutToConstPointer))
+ self.unify_and(
+ a_unsafe, b, simple(Adjust::Pointer(PointerCast::MutToConstPointer))
+ )
} else {
self.unify_and(a_unsafe, b, identity)
}
// The only adjustment that can produce an fn item is
// `NeverToAny`, so this should always be valid.
self.apply_adjustments(expr, vec![Adjustment {
- kind: Adjust::ReifyFnPointer,
+ kind: Adjust::Pointer(PointerCast::ReifyFnPointer),
target: fn_ptr
}]);
}
use rustc::ty::subst::{Subst, SubstsRef};
use rustc::traits;
use rustc::ty::{self, Ty, GenericParamDefKind};
-use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
+use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref, PointerCast};
use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::infer::{self, InferOk};
ty: unsize_target
});
adjustments.push(Adjustment {
- kind: Adjust::Unsize,
+ kind: Adjust::Pointer(PointerCast::Unsize),
target
});
}
// If we have an autoref followed by unsizing at the end, fix the unsize target.
match adjustments[..] {
[.., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. },
- Adjustment { kind: Adjust::Unsize, ref mut target }] => {
+ Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }] => {
*target = method.sig.inputs()[0];
}
_ => {}
self, AdtKind, CanonicalUserType, Ty, TyCtxt, GenericParamDefKind, Visibility,
ToPolyTraitRef, ToPredicate, RegionKind, UserType
};
-use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
+use rustc::ty::adjustment::{
+ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast
+};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
use rustc::ty::subst::{UnpackedKind, Subst, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
}
if unsize {
adjustments.push(Adjustment {
- kind: Adjust::Unsize,
+ kind: Adjust::Pointer(PointerCast::Unsize),
target: method.sig.inputs()[0]
});
}
use rustc::hir::def_id::{DefId, DefIndex};
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::infer::InferCtxt;
-use rustc::ty::adjustment::{Adjust, Adjustment};
+use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
use rustc::ty::subst::UnpackedKind;
use rustc::ty::{self, Ty, TyCtxt};
// Since this is "after" the other adjustment to be
// discarded, we do an extra `pop()`
Some(Adjustment {
- kind: Adjust::Unsize,
+ kind: Adjust::Pointer(PointerCast::Unsize),
..
}) => {
// So the borrow discard actually happens here