Disable ref hint for pattern in let and adding ui-tests.

This commit is contained in:
gaurikholkar 2017-04-14 21:04:37 -07:00
parent ace517da0d
commit 5436f859e4
8 changed files with 132 additions and 20 deletions

View File

@ -95,6 +95,14 @@ enum MapEntry<'hir> {
RootCrate,
}
/// Represents the kind of pattern
#[derive(Debug, Clone, Copy)]
pub enum PatternSource<'hir> {
MatchExpr(&'hir Expr),
LetDecl(&'hir Local),
Other,
}
impl<'hir> Clone for MapEntry<'hir> {
fn clone(&self) -> MapEntry<'hir> {
*self
@ -637,7 +645,7 @@ impl<'hir> Map<'hir> {
Err(id) => id,
}
}
/// Returns the nearest enclosing scope. A scope is an item or block.
/// FIXME it is not clear to me that all items qualify as scopes - statics
/// and associated types probably shouldn't, for example. Behaviour in this

View File

@ -23,13 +23,47 @@ use rustc::ty::{self, Ty};
use std::rc::Rc;
use syntax::ast;
use syntax_pos::Span;
use rustc::hir::{self, PatKind};
use rustc::hir::*;
use rustc::hir::map::Node::*;
use rustc::hir::map::{PatternSource};
struct GatherMoveInfo<'tcx> {
id: ast::NodeId,
kind: MoveKind,
cmt: mc::cmt<'tcx>,
span_path_opt: Option<MoveSpanAndPath>
span_path_opt: Option<MoveSpanAndPath<'tcx>>
}
/// Returns the kind of the Pattern
fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> PatternSource<'tcx> {
let parent = tcx.hir.get_parent_node(pat.id);
match tcx.hir.get(parent) {
NodeExpr(ref e) => {
// the enclosing expression must be a `match` or something else
assert!(match e.node {
ExprMatch(..) => true,
_ => return PatternSource::Other,
});
PatternSource::MatchExpr(e)
}
NodeStmt(ref s) => {
// the enclosing statement must be a `let` or something else
match s.node {
StmtDecl(ref decl, _) => {
match decl.node {
DeclLocal(ref local) => PatternSource::LetDecl(local),
_ => return PatternSource::Other,
}
}
_ => return PatternSource::Other,
}
}
_ => return PatternSource::Other,
}
}
pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
@ -95,11 +129,15 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_error_collector: &mut MoveErrorCollector<'tcx>,
move_pat: &hir::Pat,
cmt: mc::cmt<'tcx>) {
let source = get_pattern_source(bccx.tcx,move_pat);
let pat_span_path_opt = match move_pat.node {
PatKind::Binding(_, _, ref path1, _) => {
Some(MoveSpanAndPath{span: move_pat.span,
name: path1.node})
},
Some(MoveSpanAndPath {
span: move_pat.span,
name: path1.node,
pat_source: source,
})
}
_ => None,
};
let move_info = GatherMoveInfo {
@ -108,6 +146,11 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
cmt: cmt,
span_path_opt: pat_span_path_opt,
};
debug!("gather_move_from_pat: move_pat={:?} source={:?}",
move_pat,
source);
gather_move(bccx, move_data, move_error_collector, move_info);
}

View File

@ -17,6 +17,7 @@ use rustc::ty;
use syntax::ast;
use syntax_pos;
use errors::DiagnosticBuilder;
use rustc::hir::map::PatternSource;
pub struct MoveErrorCollector<'tcx> {
errors: Vec<MoveError<'tcx>>
@ -40,12 +41,12 @@ impl<'tcx> MoveErrorCollector<'tcx> {
pub struct MoveError<'tcx> {
move_from: mc::cmt<'tcx>,
move_to: Option<MoveSpanAndPath>
move_to: Option<MoveSpanAndPath<'tcx>>
}
impl<'tcx> MoveError<'tcx> {
pub fn with_move_info(move_from: mc::cmt<'tcx>,
move_to: Option<MoveSpanAndPath>)
move_to: Option<MoveSpanAndPath<'tcx>>)
-> MoveError<'tcx> {
MoveError {
move_from: move_from,
@ -55,32 +56,43 @@ impl<'tcx> MoveError<'tcx> {
}
#[derive(Clone)]
pub struct MoveSpanAndPath {
pub struct MoveSpanAndPath<'tcx> {
pub span: syntax_pos::Span,
pub name: ast::Name,
pub pat_source: PatternSource<'tcx>,
}
pub struct GroupedMoveErrors<'tcx> {
move_from: mc::cmt<'tcx>,
move_to_places: Vec<MoveSpanAndPath>
move_to_places: Vec<MoveSpanAndPath<'tcx>>
}
fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
errors: &Vec<MoveError<'tcx>>) {
fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &Vec<MoveError<'tcx>>) {
let grouped_errors = group_errors_with_same_origin(errors);
for error in &grouped_errors {
let mut err = report_cannot_move_out_of(bccx, error.move_from.clone());
let mut is_first_note = true;
for move_to in &error.move_to_places {
err = note_move_destination(err, move_to.span, move_to.name, is_first_note);
is_first_note = false;
if let Some(pattern_source) = error.move_to_places.get(0){
match pattern_source.pat_source {
PatternSource::LetDecl(_) => {}
_ => {
for move_to in &error.move_to_places {
err = note_move_destination(err, move_to.span, move_to.name, is_first_note);
is_first_note = false;
}
}
}
}
if let NoteClosureEnv(upvar_id) = error.move_from.note {
err.span_label(bccx.tcx.hir.span(upvar_id.var_id), &"captured outer variable");
err.span_label(bccx.tcx.hir.span(upvar_id.var_id), &"captured outer variable");
}
err.emit();
}
}
}
fn group_errors_with_same_origin<'tcx>(errors: &Vec<MoveError<'tcx>>)
-> Vec<GroupedMoveErrors<'tcx>> {

View File

@ -54,7 +54,6 @@ fn c() {
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
//~^ NOTE to prevent move
//~| cannot move out of here
}
@ -68,7 +67,6 @@ fn d() {
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
//~^ NOTE to prevent move
//~| cannot move out of here
}
@ -84,7 +82,6 @@ fn e() {
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
//~^ NOTE to prevent move
//~| cannot move out of here
}

View File

@ -0,0 +1,19 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo {
pub v: Vec<String>,
}
fn main() {
let mut f = Foo { v: Vec::new() };
f.v.push("hello".to_string());
let e = f.v[0];
}

View File

@ -0,0 +1,8 @@
error[E0507]: cannot move out of indexed content
--> $DIR/issue-40402-1.rs:18:13
|
18 | let e = f.v[0];
| ^^^^^^ cannot move out of indexed content
error: aborting due to previous error

View File

@ -0,0 +1,14 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let x = vec![(String::new(), String::new())];
let (a, b) = x[0];
}

View File

@ -0,0 +1,11 @@
error[E0507]: cannot move out of indexed content
--> $DIR/issue-40402-2.rs:13:18
|
13 | let (a, b) = x[0];
| - - ^^^^ cannot move out of indexed content
| | |
| | ...and here (use `ref b` or `ref mut b`)
| hint: to prevent move, use `ref a` or `ref mut a`
error: aborting due to previous error