about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndrew Cann <shum@canndrew.org>2016-06-25 18:42:52 +0800
committerAndrew Cann <shum@canndrew.org>2016-08-13 21:37:09 +0800
commit0d863616e0a9c554b4da2e4373bdb5f1a98aa02d (patch)
tree8ed23eb359b00b532e8157c3737ccd82ca40eb0f
parentb0a9acd783aec3449f5d8d772bc1bd4e59276cc8 (diff)
Add EmptyToAny adjustment
-rw-r--r--src/librustc/middle/expr_use_visitor.rs1
-rw-r--r--src/librustc/middle/mem_categorization.rs1
-rw-r--r--src/librustc/ty/adjustment.rs15
-rw-r--r--src/librustc/util/ppaux.rs3
-rw-r--r--src/librustc_metadata/astencode.rs16
-rw-r--r--src/librustc_mir/build/expr/as_lvalue.rs1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs1
-rw-r--r--src/librustc_mir/build/expr/category.rs1
-rw-r--r--src/librustc_mir/build/expr/into.rs8
-rw-r--r--src/librustc_mir/hair/cx/expr.rs9
-rw-r--r--src/librustc_mir/hair/mod.rs3
-rw-r--r--src/librustc_passes/consts.rs1
-rw-r--r--src/librustc_trans/consts.rs3
-rw-r--r--src/librustc_trans/expr.rs9
-rw-r--r--src/librustc_typeck/check/writeback.rs4
15 files changed, 69 insertions, 7 deletions
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 18b80a9636b..4980b3abc63 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -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 => {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 0bc3c1ae899..9589687cf26 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -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 |
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 47ca7d335ab..95b3a8bd42e 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -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),
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index fa1d1e0a901..b7851f9879d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -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")
             }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index f03c432c091..99d5758076f 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -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")
                 })
             })
diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs
index dd6c9c02f56..420147d037c 100644
--- a/src/librustc_mir/build/expr/as_lvalue.rs
+++ b/src/librustc_mir/build/expr/as_lvalue.rs
@@ -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 { .. } |
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index f1487992cb5..5cf00a195dc 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -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 { .. } |
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index 658b7779b44..fb5be8e7d1c 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -56,6 +56,7 @@ impl Category {
             ExprKind::LogicalOp { .. } |
             ExprKind::If { .. } |
             ExprKind::Match { .. } |
+            ExprKind::EmptyToAny { .. } |
             ExprKind::Call { .. } =>
                 Some(Category::Rvalue(RvalueFunc::Into)),
 
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index fd9ddc05ab5..2610dc71ef4 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -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));
 
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 88fb65d8eea..28a23e2a499 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -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 {
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index a2746bf30c9..14c3f0e580d 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> {
     Cast {
         source: ExprRef<'tcx>,
     },
+    EmptyToAny {
+        source: ExprRef<'tcx>,
+    },
     ReifyFnPointer {
         source: ExprRef<'tcx>,
     },
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 37e42cdea1b..9cd955b1caf 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -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) => {}
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 769dd008af8..95af6db0260 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -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, _) => {
diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs
index 2a60dd17446..eed543aa31c 100644
--- a/src/librustc_trans/expr.rs
+++ b/src/librustc_trans/expr.rs
@@ -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, _) => {
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 9026920e7f4..5fe9b8742d7 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -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
                     }