about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/transform/type_check.rs29
1 files changed, 23 insertions, 6 deletions
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index ade5cf8b70c..6cbc8b7e619 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -20,7 +20,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::tcx::LvalueTy;
-use rustc::mir::visit::Visitor;
+use rustc::mir::visit::{LvalueContext, Visitor};
 use std::fmt;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
@@ -107,10 +107,10 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     fn visit_lvalue(
         &mut self,
         lvalue: &Lvalue<'tcx>,
-        _context: visit::LvalueContext,
+        context: LvalueContext,
         location: Location,
     ) {
-        self.sanitize_lvalue(lvalue, location);
+        self.sanitize_lvalue(lvalue, location, context);
     }
 
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
@@ -164,9 +164,13 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         }
     }
 
-    fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>, location: Location) -> LvalueTy<'tcx> {
+    fn sanitize_lvalue(&mut self,
+                       lvalue: &Lvalue<'tcx>,
+                       location: Location,
+                       context: LvalueContext)
+                       -> LvalueTy<'tcx> {
         debug!("sanitize_lvalue: {:?}", lvalue);
-        match *lvalue {
+        let lvalue_ty = match *lvalue {
             Lvalue::Local(index) => LvalueTy::Ty {
                 ty: self.mir.local_decls[index].ty,
             },
@@ -189,7 +193,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 LvalueTy::Ty { ty: sty }
             }
             Lvalue::Projection(ref proj) => {
-                let base_ty = self.sanitize_lvalue(&proj.base, location);
+                let base_context = if context.is_mutating_use() {
+                    LvalueContext::Projection(Mutability::Mut)
+                } else {
+                    LvalueContext::Projection(Mutability::Not)
+                };
+                let base_ty = self.sanitize_lvalue(&proj.base, location, base_context);
                 if let LvalueTy::Ty { ty } = base_ty {
                     if ty.references_error() {
                         assert!(self.errors_reported);
@@ -200,7 +209,15 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 }
                 self.sanitize_projection(base_ty, &proj.elem, lvalue, location)
             }
+        };
+        if let LvalueContext::Copy = context {
+            let ty = lvalue_ty.to_ty(self.tcx());
+            if self.cx.infcx.type_moves_by_default(self.cx.param_env, ty, DUMMY_SP) {
+                span_mirbug!(self, lvalue,
+                             "attempted copy of non-Copy type ({:?})", ty);
+            }
         }
+        lvalue_ty
     }
 
     fn sanitize_projection(