(index<- )        ./librustc/middle/borrowck/gather_loans/move_error.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  use mc = middle::mem_categorization;
  12  use middle::borrowck::BorrowckCtxt;
  13  use middle::ty;
  14  
  15  use std::cell::RefCell;
  16  use syntax::ast;
  17  use syntax::codemap;
  18  use syntax::print::pprust;
  19  use util::ppaux::UserString;
  20  
  21  pub struct MoveErrorCollector {
  22      errors: RefCell<Vec<MoveError>>
  23  }
  24  
  25  impl MoveErrorCollector {
  26      pub fn new() -> MoveErrorCollector {
  27          MoveErrorCollector {
  28              errors: RefCell::new(Vec::new())
  29          }
  30      }
  31  
  32      pub fn add_error(&self, errorMoveError) {
  33          self.errors.borrow_mut().push(error);
  34      }
  35  
  36      pub fn report_potential_errors(&self, bccx&BorrowckCtxt) {
  37          report_move_errors(bccx, self.errors.borrow().deref())
  38      }
  39  }
  40  
  41  pub struct MoveError {
  42      move_from: mc::cmt,
  43      move_to: Option<MoveSpanAndPath>
  44  }
  45  
  46  impl MoveError {
  47      pub fn with_move_info(move_frommc::cmt,
  48                            move_toOption<MoveSpanAndPath>)
  49                            -> MoveError {
  50          MoveError {
  51              move_from: move_from,
  52              move_to: move_to,
  53          }
  54      }
  55  }
  56  
  57  #[deriving(Clone)]
  58  pub struct MoveSpanAndPath {
  59      span: codemap::Span,
  60      path: ast::Path
  61  }
  62  
  63  impl MoveSpanAndPath {
  64      pub fn with_span_and_path(spancodemap::Span,
  65                                pathast::Path)
  66                                -> MoveSpanAndPath {
  67          MoveSpanAndPath {
  68              span: span,
  69              path: path,
  70          }
  71      }
  72  }
  73  
  74  pub struct GroupedMoveErrors {
  75      move_from: mc::cmt,
  76      move_to_places: Vec<MoveSpanAndPath>
  77  }
  78  
  79  fn report_move_errors(bccx: &BorrowckCtxt, errors: &Vec<MoveError>) {
  80      let grouped_errors = group_errors_with_same_origin(errors);
  81      for error in grouped_errors.iter() {
  82          report_cannot_move_out_of(bccx, error.move_from.clone());
  83          let mut is_first_note = true;
  84          for move_to in error.move_to_places.iter() {
  85              note_move_destination(bccx, move_to.span,
  86                                    &move_to.path, is_first_note);
  87              is_first_note = false;
  88          }
  89      }
  90  }
  91  
  92  fn group_errors_with_same_origin(errors: &Vec<MoveError>)
  93                                   -> Vec<GroupedMoveErrors> {
  94      let mut grouped_errors = Vec::new();
  95      for error in errors.iter() {
  96          append_to_grouped_errors(&mut grouped_errors, error)
  97      }
  98      return grouped_errors;
  99  
 100      fn append_to_grouped_errors(grouped_errors&mut Vec<GroupedMoveErrors>,
 101                                  error: &MoveError) {
 102          let move_from_id = error.move_from.id;
 103          debug!("append_to_grouped_errors(move_from_id={})", move_from_id);
 104          let move_to = if error.move_to.is_some() {
 105              vec!(error.move_to.clone().unwrap())
 106          } else {
 107              Vec::new()
 108          };
 109          for ge in grouped_errors.mut_iter() {
 110              if move_from_id == ge.move_from.id && error.move_to.is_some() {
 111                  debug!("appending move_to to list");
 112                  ge.move_to_places.push_all_move(move_to);
 113                  return
 114              }
 115          }
 116          debug!("found a new move from location");
 117          grouped_errors.push(GroupedMoveErrors {
 118              move_from: error.move_from.clone(),
 119              move_to_places: move_to
 120          })
 121      }
 122  }
 123  
 124  fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_frommc::cmt) {
 125      match move_from.cat {
 126          mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
 127          mc::cat_deref(_, _, mc::GcPtr) |
 128          mc::cat_deref(_, _, mc::UnsafePtr(..)) |
 129          mc::cat_upvar(..) | mc::cat_static_item |
 130          mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
 131              bccx.span_err(
 132                  move_from.span,
 133                  format!("cannot move out of {}",
 134                          bccx.cmt_to_str(&*move_from)));
 135          }
 136  
 137          mc::cat_downcast(ref b) |
 138          mc::cat_interior(ref b, _) => {
 139              match ty::get(b.ty).sty {
 140                  ty::ty_struct(did, _)
 141                  | ty::ty_enum(did, _) if ty::has_dtor(bccx.tcx, did) => {
 142                      bccx.span_err(
 143                          move_from.span,
 144                          format!("cannot move out of type `{}`, \
 145                                   which defines the `Drop` trait",
 146                                  b.ty.user_string(bccx.tcx)));
 147                  },
 148                  _ => fail!("this path should not cause illegal move")
 149              }
 150          }
 151          _ => fail!("this path should not cause illegal move")
 152      }
 153  }
 154  
 155  fn note_move_destination(bccx: &BorrowckCtxt,
 156                           move_to_spancodemap::Span,
 157                           pat_ident_path: &ast::Path,
 158                           is_first_note: bool) {
 159      let pat_name = pprust::path_to_str(pat_ident_path);
 160      if is_first_note {
 161          bccx.span_note(
 162              move_to_span,
 163              format!("attempting to move value to here (to prevent the move, \
 164                       use `ref {0}` or `ref mut {0}` to capture value by \
 165                       reference)",
 166                      pat_name));
 167      } else {
 168          bccx.span_note(move_to_span,
 169                         format!("and here (use `ref {0}` or `ref mut {0}`)",
 170                                 pat_name));
 171      }
 172  }


librustc/middle/borrowck/gather_loans/move_error.rs:57:19-57:19 -struct- definition:
pub struct MoveSpanAndPath {
    span: codemap::Span,
    path: ast::Path
references:- 11
66:                               -> MoveSpanAndPath {
67:         MoveSpanAndPath {
68:             span: span,
--
75:     move_from: mc::cmt,
76:     move_to_places: Vec<MoveSpanAndPath>
77: }
librustc/middle/borrowck/gather_loans/gather_moves.rs:
31:     cmt: mc::cmt,
32:     span_path_opt: Option<MoveSpanAndPath>
33: }
librustc/middle/borrowck/gather_loans/move_error.rs:
65:                               path: ast::Path)
66:                               -> MoveSpanAndPath {
67:         MoveSpanAndPath {


librustc/middle/borrowck/gather_loans/move_error.rs:40:1-40:1 -struct- definition:
pub struct MoveError {
    move_from: mc::cmt,
    move_to: Option<MoveSpanAndPath>
references:- 8
49:                           -> MoveError {
50:         MoveError {
51:             move_from: move_from,
--
92: fn group_errors_with_same_origin(errors: &Vec<MoveError>)
93:                                  -> Vec<GroupedMoveErrors> {
--
100:     fn append_to_grouped_errors(grouped_errors: &mut Vec<GroupedMoveErrors>,
101:                                 error: &MoveError) {
102:         let move_from_id = error.move_from.id;


librustc/middle/borrowck/gather_loans/move_error.rs:20:1-20:1 -struct- definition:
pub struct MoveErrorCollector {
    errors: RefCell<Vec<MoveError>>
}
references:- 7
26:     pub fn new() -> MoveErrorCollector {
27:         MoveErrorCollector {
28:             errors: RefCell::new(Vec::new())
librustc/middle/borrowck/gather_loans/mod.rs:
62:     move_data: move_data::MoveData,
63:     move_error_collector: move_error::MoveErrorCollector,
64:     all_loans: Vec<Loan>,
librustc/middle/borrowck/gather_loans/gather_moves.rs:
80:                move_data: &MoveData,
81:                move_error_collector: &MoveErrorCollector,
82:                move_info: GatherMoveInfo) {


librustc/middle/borrowck/gather_loans/move_error.rs:73:1-73:1 -struct- definition:
pub struct GroupedMoveErrors {
    move_from: mc::cmt,
    move_to_places: Vec<MoveSpanAndPath>
references:- 3
92: fn group_errors_with_same_origin(errors: &Vec<MoveError>)
93:                                  -> Vec<GroupedMoveErrors> {
94:     let mut grouped_errors = Vec::new();
--
100:     fn append_to_grouped_errors(grouped_errors: &mut Vec<GroupedMoveErrors>,
101:                                 error: &MoveError) {
--
116:         debug!("found a new move from location");
117:         grouped_errors.push(GroupedMoveErrors {
118:             move_from: error.move_from.clone(),