]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/check/writeback.rs
Fill in some missing parts in the default HIR visitor
[rust.git] / src / librustc_typeck / check / writeback.rs
index 9d7ff3b9613d0ffb9a12796c4dc9dfd0ab99add7..68c0f130c20f18a167eb54491395b8cd605ebc95 100644 (file)
 
 use astconv::AstConv;
 use check::FnCtxt;
+use middle::def_id::DefId;
 use middle::pat_util;
-use middle::ty::{self, Ty, MethodCall, MethodCallee};
-use middle::ty_fold::{TypeFolder,TypeFoldable};
+use middle::ty::{self, Ty, MethodCall, MethodCallee, HasTypeFlags};
+use middle::ty::adjustment;
+use middle::ty::fold::{TypeFolder,TypeFoldable};
 use middle::infer;
 use write_substs_to_tcx;
 use write_ty_to_tcx;
 use std::cell::Cell;
 
 use syntax::ast;
-use syntax::ast_util;
 use syntax::codemap::{DUMMY_SP, Span};
-use syntax::print::pprust::pat_to_string;
-use syntax::visit;
-use syntax::visit::Visitor;
+use rustc_front::print::pprust::pat_to_string;
+use rustc_front::visit;
+use rustc_front::visit::Visitor;
+use rustc_front::util as hir_util;
+use rustc_front::hir;
 
 ///////////////////////////////////////////////////////////////////////////
 // Entry point functions
 
-pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
+pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &hir::Expr) {
     assert_eq!(fcx.writeback_errors.get(), false);
     let mut wbcx = WritebackCx::new(fcx);
     wbcx.visit_expr(e);
@@ -43,8 +46,8 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
 }
 
 pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
-                               decl: &ast::FnDecl,
-                               blk: &ast::Block) {
+                               decl: &hir::FnDecl,
+                               blk: &hir::Block) {
     assert_eq!(fcx.writeback_errors.get(), false);
     let mut wbcx = WritebackCx::new(fcx);
     wbcx.visit_block(blk);
@@ -87,25 +90,54 @@ fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
     // as potentially overloaded. But then, during writeback, if
     // we observe that something like `a+b` is (known to be)
     // operating on scalars, we clear the overload.
-    fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) {
-        if let ast::ExprBinary(ref op, ref lhs, ref rhs) = e.node {
-            let lhs_ty = self.fcx.node_ty(lhs.id);
-            let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
-
-            let rhs_ty = self.fcx.node_ty(rhs.id);
-            let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
-
-            if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
-                self.fcx.inh.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id));
-
-                // weird but true: the by-ref binops put an
-                // adjustment on the lhs but not the rhs; the
-                // adjustment for rhs is kind of baked into the
-                // system.
-                if !ast_util::is_by_value_binop(op.node) {
-                    self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
+    fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) {
+        match e.node {
+            hir::ExprBinary(ref op, ref lhs, ref rhs) |
+            hir::ExprAssignOp(ref op, ref lhs, ref rhs) => {
+                let lhs_ty = self.fcx.node_ty(lhs.id);
+                let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
+
+                let rhs_ty = self.fcx.node_ty(rhs.id);
+                let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
+
+                if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
+                    self.fcx.inh.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id));
+
+                    // weird but true: the by-ref binops put an
+                    // adjustment on the lhs but not the rhs; the
+                    // adjustment for rhs is kind of baked into the
+                    // system.
+                    match e.node {
+                        hir::ExprBinary(..) => {
+                            if !hir_util::is_by_value_binop(op.node) {
+                                self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
+                            }
+                        },
+                        hir::ExprAssignOp(..) => {
+                            self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
+                        },
+                        _ => {},
+                    }
+                } else {
+                    let tcx = self.tcx();
+
+                    if let hir::ExprAssignOp(..) = e.node {
+                        if
+                            !tcx.sess.features.borrow().augmented_assignments &&
+                            !self.fcx.expr_ty(e).references_error()
+                        {
+                            tcx.sess.span_err(
+                                e.span,
+                                "overloaded augmented assignments are not stable");
+                            fileline_help!(
+                                tcx.sess, e.span,
+                                "add #![feature(augmented_assignments)] to the crate features \
+                                 to enable");
+                        }
+                    }
                 }
             }
+            _ => {},
         }
     }
 }
@@ -119,20 +151,20 @@ fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) {
 // traffic in node-ids or update tables in the type context etc.
 
 impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
-    fn visit_item(&mut self, _: &ast::Item) {
+    fn visit_item(&mut self, _: &hir::Item) {
         // Ignore items
     }
 
-    fn visit_stmt(&mut self, s: &ast::Stmt) {
+    fn visit_stmt(&mut self, s: &hir::Stmt) {
         if self.fcx.writeback_errors.get() {
             return;
         }
 
-        self.visit_node_id(ResolvingExpr(s.span), ast_util::stmt_id(s));
+        self.visit_node_id(ResolvingExpr(s.span), hir_util::stmt_id(s));
         visit::walk_stmt(self, s);
     }
 
-    fn visit_expr(&mut self, e: &ast::Expr) {
+    fn visit_expr(&mut self, e: &hir::Expr) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -143,7 +175,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
         self.visit_method_map_entry(ResolvingExpr(e.span),
                                     MethodCall::expr(e.id));
 
-        if let ast::ExprClosure(_, ref decl, _) = e.node {
+        if let hir::ExprClosure(_, ref decl, _) = e.node {
             for input in &decl.inputs {
                 self.visit_node_id(ResolvingExpr(e.span), input.id);
             }
@@ -152,7 +184,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
         visit::walk_expr(self, e);
     }
 
-    fn visit_block(&mut self, b: &ast::Block) {
+    fn visit_block(&mut self, b: &hir::Block) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -161,7 +193,7 @@ fn visit_block(&mut self, b: &ast::Block) {
         visit::walk_block(self, b);
     }
 
-    fn visit_pat(&mut self, p: &ast::Pat) {
+    fn visit_pat(&mut self, p: &hir::Pat) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -176,7 +208,7 @@ fn visit_pat(&mut self, p: &ast::Pat) {
         visit::walk_pat(self, p);
     }
 
-    fn visit_local(&mut self, l: &ast::Local) {
+    fn visit_local(&mut self, l: &hir::Local) {
         if self.fcx.writeback_errors.get() {
             return;
         }
@@ -187,12 +219,16 @@ fn visit_local(&mut self, l: &ast::Local) {
         visit::walk_local(self, l);
     }
 
-    fn visit_ty(&mut self, t: &ast::Ty) {
+    fn visit_ty(&mut self, t: &hir::Ty) {
         match t.node {
-            ast::TyFixedLengthVec(ref ty, ref count_expr) => {
+            hir::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
                 write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.usize);
             }
+            hir::TyBareFn(ref function_declaration) => {
+                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
+                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
+            }
             _ => visit::walk_ty(self, t)
         }
     }
@@ -266,19 +302,21 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
 
             Some(adjustment) => {
                 let resolved_adjustment = match adjustment {
-                    ty::AdjustReifyFnPointer => ty::AdjustReifyFnPointer,
+                    adjustment::AdjustReifyFnPointer => {
+                        adjustment::AdjustReifyFnPointer
+                    }
 
-                    ty::AdjustUnsafeFnPointer => {
-                        ty::AdjustUnsafeFnPointer
+                    adjustment::AdjustUnsafeFnPointer => {
+                        adjustment::AdjustUnsafeFnPointer
                     }
 
-                    ty::AdjustDerefRef(adj) => {
+                    adjustment::AdjustDerefRef(adj) => {
                         for autoderef in 0..adj.autoderefs {
                             let method_call = MethodCall::autoderef(id, autoderef as u32);
                             self.visit_method_map_entry(reason, method_call);
                         }
 
-                        ty::AdjustDerefRef(ty::AutoDerefRef {
+                        adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
                             autoderefs: adj.autoderefs,
                             autoref: self.resolve(&adj.autoref, reason),
                             unsize: self.resolve(&adj.unsize, reason),
@@ -337,7 +375,7 @@ enum ResolveReason {
     ResolvingLocal(Span),
     ResolvingPattern(Span),
     ResolvingUpvar(ty::UpvarId),
-    ResolvingClosure(ast::DefId),
+    ResolvingClosure(DefId),
 }
 
 impl ResolveReason {
@@ -350,7 +388,7 @@ fn span(&self, tcx: &ty::ctxt) -> Span {
                 tcx.expr_span(upvar_id.closure_expr_id)
             }
             ResolvingClosure(did) => {
-                if did.krate == ast::LOCAL_CRATE {
+                if did.is_local() {
                     tcx.expr_span(did.node)
                 } else {
                     DUMMY_SP