Add EmptyToAny adjustment
This commit is contained in:
parent
b0a9acd783
commit
0d863616e0
@ -717,6 +717,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone());
|
||||
if let Some(adjustment) = adj {
|
||||
match adjustment {
|
||||
adjustment::AdjustEmptyToAny(..) |
|
||||
adjustment::AdjustReifyFnPointer |
|
||||
adjustment::AdjustUnsafeFnPointer |
|
||||
adjustment::AdjustMutToConstPointer => {
|
||||
|
@ -451,6 +451,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
self.cat_expr_autoderefd(expr, autoderefs)
|
||||
}
|
||||
|
||||
adjustment::AdjustEmptyToAny(..) |
|
||||
adjustment::AdjustReifyFnPointer |
|
||||
adjustment::AdjustUnsafeFnPointer |
|
||||
adjustment::AdjustMutToConstPointer |
|
||||
|
@ -11,7 +11,7 @@
|
||||
pub use self::AutoAdjustment::*;
|
||||
pub use self::AutoRef::*;
|
||||
|
||||
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable};
|
||||
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeVariants};
|
||||
use ty::LvaluePreference::{NoPreference};
|
||||
|
||||
use syntax::ast;
|
||||
@ -21,9 +21,10 @@ use hir;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AutoAdjustment<'tcx> {
|
||||
AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type
|
||||
AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer
|
||||
AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer
|
||||
AdjustEmptyToAny(Ty<'tcx>), // go from ! to any type
|
||||
AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type
|
||||
AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer
|
||||
AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer
|
||||
AdjustDerefRef(AutoDerefRef<'tcx>),
|
||||
}
|
||||
|
||||
@ -106,6 +107,10 @@ pub struct AutoDerefRef<'tcx> {
|
||||
impl<'tcx> AutoAdjustment<'tcx> {
|
||||
pub fn is_identity(&self) -> bool {
|
||||
match *self {
|
||||
AdjustEmptyToAny(ref ty) => match ty.sty {
|
||||
TypeVariants::TyEmpty => true,
|
||||
_ => false,
|
||||
},
|
||||
AdjustReifyFnPointer |
|
||||
AdjustUnsafeFnPointer |
|
||||
AdjustMutToConstPointer => false,
|
||||
@ -154,6 +159,8 @@ impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> {
|
||||
return match adjustment {
|
||||
Some(adjustment) => {
|
||||
match *adjustment {
|
||||
AdjustEmptyToAny(ref ty) => ty,
|
||||
|
||||
AdjustReifyFnPointer => {
|
||||
match self.sty {
|
||||
ty::TyFnDef(_, _, f) => tcx.mk_fn_ptr(f),
|
||||
|
@ -429,6 +429,9 @@ impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
|
||||
impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ty::adjustment::AdjustEmptyToAny(ref target) => {
|
||||
write!(f, "AdjustEmptyToAny({:?})", target)
|
||||
}
|
||||
ty::adjustment::AdjustReifyFnPointer => {
|
||||
write!(f, "AdjustReifyFnPointer")
|
||||
}
|
||||
|
@ -644,6 +644,12 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
|
||||
|this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
|
||||
})
|
||||
}
|
||||
|
||||
adjustment::AdjustEmptyToAny(ref ty) => {
|
||||
this.emit_enum_variant("AdjustEmptyToAny", 5, 1, |this| {
|
||||
this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ecx, ty)))
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1017,7 +1023,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
-> adjustment::AutoAdjustment<'tcx> {
|
||||
self.read_enum("AutoAdjustment", |this| {
|
||||
let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer",
|
||||
"AdjustMutToConstPointer", "AdjustDerefRef"];
|
||||
"AdjustMutToConstPointer", "AdjustDerefRef",
|
||||
"AdjustEmptyToAny"];
|
||||
this.read_enum_variant(&variants, |this, i| {
|
||||
Ok(match i {
|
||||
1 => adjustment::AdjustReifyFnPointer,
|
||||
@ -1030,6 +1037,13 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
|
||||
adjustment::AdjustDerefRef(auto_deref_ref)
|
||||
}
|
||||
5 => {
|
||||
let ty: Ty<'tcx> = this.read_enum_variant_arg(0, |this| {
|
||||
Ok(this.read_ty(dcx))
|
||||
}).unwrap();
|
||||
|
||||
adjustment::AdjustEmptyToAny(ty)
|
||||
}
|
||||
_ => bug!("bad enum variant for adjustment::AutoAdjustment")
|
||||
})
|
||||
})
|
||||
|
@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ExprKind::LogicalOp { .. } |
|
||||
ExprKind::Box { .. } |
|
||||
ExprKind::Cast { .. } |
|
||||
ExprKind::EmptyToAny { .. } |
|
||||
ExprKind::ReifyFnPointer { .. } |
|
||||
ExprKind::UnsafeFnPointer { .. } |
|
||||
ExprKind::Unsize { .. } |
|
||||
|
@ -219,6 +219,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ExprKind::Block { .. } |
|
||||
ExprKind::Match { .. } |
|
||||
ExprKind::If { .. } |
|
||||
ExprKind::EmptyToAny { .. } |
|
||||
ExprKind::Loop { .. } |
|
||||
ExprKind::LogicalOp { .. } |
|
||||
ExprKind::Call { .. } |
|
||||
|
@ -56,6 +56,7 @@ impl Category {
|
||||
ExprKind::LogicalOp { .. } |
|
||||
ExprKind::If { .. } |
|
||||
ExprKind::Match { .. } |
|
||||
ExprKind::EmptyToAny { .. } |
|
||||
ExprKind::Call { .. } =>
|
||||
Some(Category::Rvalue(RvalueFunc::Into)),
|
||||
|
||||
|
@ -45,6 +45,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ExprKind::Match { discriminant, arms } => {
|
||||
this.match_expr(destination, expr_span, block, discriminant, arms)
|
||||
}
|
||||
ExprKind::EmptyToAny { source } => {
|
||||
// TODO(canndrew): Do we need to do this?
|
||||
unpack!(block = this.as_rvalue(block, source));
|
||||
|
||||
this.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
|
||||
let end_block = this.cfg.start_new_block();
|
||||
end_block.unit()
|
||||
}
|
||||
ExprKind::If { condition: cond_expr, then: then_expr, otherwise: else_expr } => {
|
||||
let operand = unpack!(block = this.as_operand(block, cond_expr));
|
||||
|
||||
|
@ -60,6 +60,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
|
||||
};
|
||||
}
|
||||
Some(&ty::adjustment::AdjustEmptyToAny(..)) => {
|
||||
let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
|
||||
expr = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: adjusted_ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::EmptyToAny { source: expr.to_ref() },
|
||||
};
|
||||
}
|
||||
Some(&ty::adjustment::AdjustMutToConstPointer) => {
|
||||
let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
|
||||
expr = Expr {
|
||||
|
@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> {
|
||||
Cast {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
EmptyToAny {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
ReifyFnPointer {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
|
@ -632,6 +632,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
|
||||
fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
|
||||
match v.tcx.tables.borrow().adjustments.get(&e.id) {
|
||||
None |
|
||||
Some(&ty::adjustment::AdjustEmptyToAny(..)) |
|
||||
Some(&ty::adjustment::AdjustReifyFnPointer) |
|
||||
Some(&ty::adjustment::AdjustUnsafeFnPointer) |
|
||||
Some(&ty::adjustment::AdjustMutToConstPointer) => {}
|
||||
|
@ -34,7 +34,7 @@ use type_of;
|
||||
use value::Value;
|
||||
use Disr;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
|
||||
use rustc::ty::adjustment::{AdjustEmptyToAny, AdjustDerefRef, AdjustReifyFnPointer};
|
||||
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::cast::{CastTy,IntTy};
|
||||
@ -348,6 +348,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
&cx.tcx().expr_ty_adjusted(e));
|
||||
let opt_adj = cx.tcx().tables.borrow().adjustments.get(&e.id).cloned();
|
||||
match opt_adj {
|
||||
Some(AdjustEmptyToAny(..)) => span_bug!(e.span, "const expression of type ! encountered"),
|
||||
Some(AdjustReifyFnPointer) => {
|
||||
match ety.sty {
|
||||
ty::TyFnDef(def_id, substs, _) => {
|
||||
|
@ -69,7 +69,7 @@ use tvec;
|
||||
use type_of;
|
||||
use value::Value;
|
||||
use Disr;
|
||||
use rustc::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
|
||||
use rustc::ty::adjustment::{AdjustEmptyToAny, AdjustDerefRef, AdjustReifyFnPointer};
|
||||
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
|
||||
use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
@ -348,6 +348,7 @@ fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
|
||||
match adjustment {
|
||||
AdjustEmptyToAny(..) => true,
|
||||
AdjustReifyFnPointer => true,
|
||||
AdjustUnsafeFnPointer | AdjustMutToConstPointer => {
|
||||
// purely a type-level thing
|
||||
@ -380,6 +381,12 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
debug!("unadjusted datum for expr {:?}: {:?} adjustment={:?}",
|
||||
expr, datum, adjustment);
|
||||
match adjustment {
|
||||
AdjustEmptyToAny(..) => {
|
||||
let const_ty = expr_ty(bcx, expr);
|
||||
let llty = type_of::type_of(bcx.ccx(), const_ty);
|
||||
let dummy = C_undef(llty.ptr_to());
|
||||
datum = Datum::new(dummy, const_ty, Rvalue::new(ByRef)).to_expr_datum();
|
||||
}
|
||||
AdjustReifyFnPointer => {
|
||||
match datum.ty.sty {
|
||||
ty::TyFnDef(def_id, substs, _) => {
|
||||
|
@ -378,6 +378,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
|
||||
Some(adjustment) => {
|
||||
let resolved_adjustment = match adjustment {
|
||||
adjustment::AdjustEmptyToAny(ty) => {
|
||||
adjustment::AdjustEmptyToAny(self.resolve(&ty, reason))
|
||||
}
|
||||
|
||||
adjustment::AdjustReifyFnPointer => {
|
||||
adjustment::AdjustReifyFnPointer
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user