]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/liveness.rs
hir, mir: Separate HIR expressions / MIR operands from InlineAsm.
[rust.git] / src / librustc / middle / liveness.rs
index 04240bf2875746dc6644f5cc73ae16c87fee23a0..d78e0ca79aa82650790190b79a4ae7da37a2dfea 100644 (file)
 use dep_graph::DepNode;
 use middle::def::*;
 use middle::pat_util;
-use middle::ty::{self, TyCtxt};
+use middle::ty::{self, TyCtxt, ParameterEnvironment};
+use middle::traits::{self, ProjectionMode};
+use middle::infer;
 use lint;
 use util::nodemap::NodeMap;
 
@@ -1168,25 +1170,21 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_expr(&e, succ)
           }
 
-          hir::ExprInlineAsm(ref ia) => {
-
-            let succ = ia.outputs.iter().rev().fold(succ,
-                |succ, out| {
-                    // see comment on lvalues
-                    // in propagate_through_lvalue_components()
-                    if out.is_indirect {
-                        self.propagate_through_expr(&out.expr, succ)
-                    } else {
-                        let acc = if out.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
-                        let succ = self.write_lvalue(&out.expr, succ, acc);
-                        self.propagate_through_lvalue_components(&out.expr, succ)
-                    }
+          hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => {
+            let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| {
+                // see comment on lvalues
+                // in propagate_through_lvalue_components()
+                if o.is_indirect {
+                    self.propagate_through_expr(output, succ)
+                } else {
+                    let acc = if o.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
+                    let succ = self.write_lvalue(output, succ, acc);
+                    self.propagate_through_lvalue_components(output, succ)
                 }
-            );
+            });
+
             // Inputs are executed first. Propagate last because of rev order
-            ia.inputs.iter().rev().fold(succ, |succ, &(_, ref expr)| {
-                self.propagate_through_expr(&expr, succ)
-            })
+            self.propagate_through_exprs(inputs, succ)
           }
 
           hir::ExprLit(..) => {
@@ -1423,17 +1421,17 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
         intravisit::walk_expr(this, expr);
       }
 
-      hir::ExprInlineAsm(ref ia) => {
-        for &(_, ref input) in &ia.inputs {
-          this.visit_expr(&input);
+      hir::ExprInlineAsm(ref ia, ref outputs, ref inputs) => {
+        for input in inputs {
+          this.visit_expr(input);
         }
 
         // Output operands must be lvalues
-        for out in &ia.outputs {
-          if !out.is_indirect {
-            this.check_lvalue(&out.expr);
+        for (o, output) in ia.outputs.iter().zip(outputs) {
+          if !o.is_indirect {
+            this.check_lvalue(output);
           }
-          this.visit_expr(&out.expr);
+          this.visit_expr(output);
         }
 
         intravisit::walk_expr(this, expr);
@@ -1490,9 +1488,19 @@ fn check_ret(&self,
 
         match fn_ret {
             ty::FnConverging(t_ret)
-                if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => {
-
-                if t_ret.is_nil() {
+                    if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => {
+
+                let param_env = ParameterEnvironment::for_item(&self.ir.tcx, id);
+                let infcx = infer::new_infer_ctxt(&self.ir.tcx,
+                                                  &self.ir.tcx.tables,
+                                                  Some(param_env),
+                                                  ProjectionMode::Any);
+                let cause = traits::ObligationCause::dummy();
+                let norm = traits::fully_normalize(&infcx,
+                                                   cause,
+                                                   &t_ret);
+
+                if norm.unwrap().is_nil() {
                     // for nil return types, it is ok to not return a value expl.
                 } else {
                     let ends_with_stmt = match body.expr {