Skip to content

Issue 3148 #4628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/etc/tidy.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ def report_error_name_no(name, no, s):
def report_err(s):
report_error_name_no(fileinput.filename(), fileinput.filelineno(), s)

def report_warn(s):
print("%s:%d: %s" % (fileinput.filename(),
fileinput.filelineno(),
s))

def do_license_check(name, contents):
if not check_license(name, contents):
report_error_name_no(name, 1, "incorrect license")
Expand All @@ -44,6 +49,9 @@ def do_license_check(name, contents):
report_err("FIXME without issue number")
if line.find("TODO") != -1:
report_err("TODO is deprecated; use FIXME")
if line.find("// WARN") != -1:
mo = re.match("// WARN (.*)", line)
report_warn("WARN: " + mo.group(1))
if (line.find('\t') != -1 and
fileinput.filename().find("Makefile") == -1):
report_err("tab character")
Expand Down
42 changes: 42 additions & 0 deletions src/librustc/middle/borrowck/gather_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,53 @@ impl gather_loan_ctxt {
}
}

ast::pat_vec(_, Some(tail_pat)) => {
// The `tail_pat` here creates a slice into the
// original vector. This is effectively a borrow of
// the elements of the vector being matched.

let tail_ty = self.tcx().ty(tail_pat);
let (tail_mutbl, tail_r) =
self.vec_slice_info(tail_pat, tail_ty);
let mcx = self.bccx.mc_ctxt();
let cmt_index = mcx.cat_index(tail_pat, cmt);
self.guarantee_valid(cmt_index, tail_mutbl, tail_r);
}

_ => {}
}
}
}

fn vec_slice_info(&self,
pat: @ast::pat,
tail_ty: ty::t) -> (ast::mutability, ty::Region)
{
/*!
*
* In a pattern like [a, b, ..c], normally `c` has slice type,
* but if you have [a, b, ..ref c], then the type of `ref c`
* will be `&&[]`, so to extract the slice details we have
* to recurse through rptrs.
*/

match ty::get(tail_ty).sty {
ty::ty_evec(tail_mt, ty::vstore_slice(tail_r)) => {
(tail_mt.mutbl, tail_r)
}

ty::ty_rptr(_, ref mt) => {
self.vec_slice_info(pat, mt.ty)
}

_ => {
self.tcx().sess.span_bug(
pat.span,
fmt!("Type of tail pattern is not a slice"));
}
}
}

fn pat_is_variant_or_struct(&self, pat: @ast::pat) -> bool {
pat_util::pat_is_variant_or_struct(self.bccx.tcx.def_map, pat)
}
Expand Down
8 changes: 6 additions & 2 deletions src/librustc/middle/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,9 +504,13 @@ impl borrowck_ctxt {
return @{cat:cat_discr(cmt, match_id),.. *cmt};
}

fn mc_ctxt() -> mem_categorization_ctxt {
mem_categorization_ctxt {tcx: self.tcx,
method_map: self.method_map}
}

fn cat_pattern(cmt: cmt, pat: @ast::pat, op: fn(cmt, @ast::pat)) {
let mc = &mem_categorization_ctxt {tcx: self.tcx,
method_map: self.method_map};
let mc = self.mc_ctxt();
mc.cat_pattern(cmt, pat, op);
}

Expand Down
62 changes: 36 additions & 26 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ enum special_kind {
// a complete categorization of a value indicating where it originated
// and how it is located, as well as the mutability of the memory in
// which the value is stored.
//
// note: cmt stands for "categorized mutable type".
type cmt_ = {id: ast::node_id, // id of expr/pat producing this value
span: span, // span of same expr/pat
cat: categorization, // categorization of expr
Expand Down Expand Up @@ -519,8 +521,8 @@ impl &mem_categorization_ctxt {
ty: self.tcx.ty(arg)}
}

fn cat_rvalue(expr: @ast::expr, expr_ty: ty::t) -> cmt {
@{id:expr.id, span:expr.span,
fn cat_rvalue<N: ast_node>(elt: N, expr_ty: ty::t) -> cmt {
@{id:elt.id(), span:elt.span(),
cat:cat_rvalue, lp:None,
mutbl:m_imm, ty:expr_ty}
}
Expand Down Expand Up @@ -641,12 +643,12 @@ impl &mem_categorization_ctxt {
}
}

fn cat_index(expr: @ast::expr, base_cmt: cmt) -> cmt {
fn cat_index<N: ast_node>(elt: N, base_cmt: cmt) -> cmt {
let mt = match ty::index(self.tcx, base_cmt.ty) {
Some(mt) => mt,
None => {
self.tcx.sess.span_bug(
expr.span,
elt.span(),
fmt!("Explicit index of non-index type `%s`",
ty_to_str(self.tcx, base_cmt.ty)));
}
Expand All @@ -673,25 +675,27 @@ impl &mem_categorization_ctxt {
};

// (c) the deref is explicit in the resulting cmt
let deref_cmt = @{id:expr.id, span:expr.span,
let deref_cmt = @{id:elt.id(), span:elt.span(),
cat:cat_deref(base_cmt, 0u, ptr), lp:deref_lp,
mutbl:m, ty:mt.ty};

comp(expr, deref_cmt, base_cmt.ty, m, mt.ty)
comp(elt, deref_cmt, base_cmt.ty, m, mt.ty)
}

deref_comp(_) => {
// fixed-length vectors have no deref
let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl);
comp(expr, base_cmt, base_cmt.ty, m, mt.ty)
comp(elt, base_cmt, base_cmt.ty, m, mt.ty)
}
};

fn comp(expr: @ast::expr, of_cmt: cmt,
vect: ty::t, mutbl: ast::mutability, ty: ty::t) -> cmt {
fn comp<N: ast_node>(elt: N, of_cmt: cmt,
vect: ty::t, mutbl: ast::mutability,
ty: ty::t) -> cmt
{
let comp = comp_index(vect, mutbl);
let index_lp = of_cmt.lp.map(|lp| @lp_comp(*lp, comp) );
@{id:expr.id, span:expr.span,
@{id:elt.id(), span:elt.span(),
cat:cat_comp(of_cmt, comp), lp:index_lp,
mutbl:mutbl, ty:ty}
}
Expand Down Expand Up @@ -721,8 +725,6 @@ impl &mem_categorization_ctxt {

fn cat_pattern(cmt: cmt, pat: @ast::pat, op: fn(cmt, @ast::pat)) {

op(cmt, pat);

// Here, `cmt` is the categorization for the value being
// matched and pat is the pattern it is being matched against.
//
Expand Down Expand Up @@ -757,21 +759,23 @@ impl &mem_categorization_ctxt {
// and the id of `local(x)->@->@` is the id of the `y` pattern.


let _i = indenter();
let tcx = self.tcx;
debug!("cat_pattern: id=%d pat=%s cmt=%s",
pat.id, pprust::pat_to_str(pat, tcx.sess.intr()),
self.cmt_to_repr(cmt));
let _i = indenter();

op(cmt, pat);

match /*bad*/copy pat.node {
match pat.node {
ast::pat_wild => {
// _
}

ast::pat_enum(_, None) => {
// variant(*)
}
ast::pat_enum(_, Some(subpats)) => {
ast::pat_enum(_, Some(ref subpats)) => {
match self.tcx.def_map.find(pat.id) {
Some(ast::def_variant(enum_did, _)) => {
// variant(x, y, z)
Expand Down Expand Up @@ -803,23 +807,16 @@ impl &mem_categorization_ctxt {
// nullary variant or identifier: ignore
}

ast::pat_rec(field_pats, _) => {
// {f1: p1, ..., fN: pN}
for field_pats.each |fp| {
let cmt_field = self.cat_field(fp.pat, cmt, fp.ident, pat.id);
self.cat_pattern(cmt_field, fp.pat, op);
}
}

ast::pat_struct(_, field_pats, _) => {
ast::pat_rec(ref field_pats, _) |
ast::pat_struct(_, ref field_pats, _) => {
// {f1: p1, ..., fN: pN}
for field_pats.each |fp| {
let cmt_field = self.cat_field(fp.pat, cmt, fp.ident, pat.id);
self.cat_pattern(cmt_field, fp.pat, op);
}
}

ast::pat_tup(subpats) => {
ast::pat_tup(ref subpats) => {
// (p1, ..., pN)
for subpats.each |subpat| {
let subcmt = self.cat_tuple_elt(*subpat, cmt);
Expand All @@ -834,7 +831,20 @@ impl &mem_categorization_ctxt {
self.cat_pattern(subcmt, subpat, op);
}

ast::pat_vec(*) | ast::pat_lit(_) | ast::pat_range(_, _) => {
ast::pat_vec(ref pats, opt_tail_pat) => {
for pats.each |pat| {
let elt_cmt = self.cat_index(*pat, cmt);
self.cat_pattern(elt_cmt, *pat, op);
}

for opt_tail_pat.each |tail_pat| {
let tail_ty = self.tcx.ty(*tail_pat);
let tail_cmt = self.cat_rvalue(*tail_pat, tail_ty);
self.cat_pattern(tail_cmt, *tail_pat, op);
}
}

ast::pat_lit(_) | ast::pat_range(_, _) => {
/*always ok*/
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use core::str;
use core::vec;
use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm};
use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk, capture_clause};
use syntax::ast::{bind_by_value, bind_infer, bind_by_ref, bind_by_move};
use syntax::ast::{crate, crate_num, decl_item, def, def_arg, def_binding};
use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
Expand Down Expand Up @@ -4521,6 +4522,10 @@ impl Resolver {
struct or enum variant",
self.session.str_of(ident));

self.enforce_default_binding_mode(
pattern,
binding_mode,
"an enum variant");
self.record_def(pattern.id, def);
}
FoundStructOrEnumVariant(_) => {
Expand All @@ -4537,6 +4542,10 @@ impl Resolver {
constant",
self.session.str_of(ident));

self.enforce_default_binding_mode(
pattern,
binding_mode,
"a constant");
self.record_def(pattern.id, def);
}
FoundConst(_) => {
Expand Down Expand Up @@ -5371,6 +5380,32 @@ impl Resolver {
self.def_map.insert(node_id, def);
}

fn enforce_default_binding_mode(pat: @pat,
pat_binding_mode: binding_mode,
descr: &str) {
match pat_binding_mode {
bind_infer => {}
bind_by_value => {
self.session.span_err(
pat.span,
fmt!("cannot use `copy` binding mode with %s",
descr));
}
bind_by_move => {
self.session.span_err(
pat.span,
fmt!("cannot use `move` binding mode with %s",
descr));
}
bind_by_ref(*) => {
self.session.span_err(
pat.span,
fmt!("cannot use `ref` binding mode with %s",
descr));
}
}
}

//
// main function checking
//
Expand Down
13 changes: 12 additions & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export ty_opaque_box, mk_opaque_box;
export ty_float, mk_float, mk_mach_float, type_is_fp;
export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn;
export ty_fn_proto, ty_fn_purity, ty_fn_ret, tys_in_fn_sig;
export ty_vstore;
export replace_fn_return_type;
export ty_int, mk_int, mk_mach_int, mk_char;
export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
Expand Down Expand Up @@ -3005,10 +3006,20 @@ fn is_fn_ty(fty: t) -> bool {
}
}

pure fn ty_vstore(ty: t) -> vstore {
match get(ty).sty {
ty_evec(_, vstore) => vstore,
ty_estr(vstore) => vstore,
ref s => fail fmt!("ty_vstore() called on invalid sty: %?", s)
}
}

fn ty_region(ty: t) -> Region {
match get(ty).sty {
ty_rptr(r, _) => r,
ref s => fail fmt!("ty_region() invoked on non-rptr: %?", (*s))
ty_evec(_, vstore_slice(r)) => r,
ty_estr(vstore_slice(r)) => r,
ref s => fail fmt!("ty_region() invoked on in appropriate ty: %?", (*s))
}
}

Expand Down
13 changes: 8 additions & 5 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ use middle::typeck::{isr_alist, lookup_def_ccx, method_map_entry};
use middle::typeck::{method_origin, method_self, method_trait, no_params};
use middle::typeck::{require_same_types};
use util::common::{block_query, indenter, loop_query};
use util::ppaux::{bound_region_to_str, expr_repr};
use util::ppaux::{bound_region_to_str, expr_repr, pat_repr};
use util::ppaux;

use core::either;
Expand All @@ -127,7 +127,6 @@ use syntax::ast_util;
use syntax::codemap::span;
use syntax::codemap;
use syntax::parse::token::special_idents;
use syntax::print::pprust::{expr_to_str, pat_to_str};
use syntax::print::pprust;
use syntax::visit;
use syntax;
Expand Down Expand Up @@ -469,7 +468,7 @@ fn check_fn(ccx: @crate_ctxt,
};
assign(local.span, local.node.id, o_ty);
debug!("Local variable %s is assigned to %s",
pat_to_str(local.node.pat, tcx.sess.intr()),
fcx.pat_to_str(local.node.pat),
fcx.inh.locals.get(local.node.id).to_str());
visit::visit_local(local, e, v);
};
Expand Down Expand Up @@ -756,6 +755,10 @@ impl @fn_ctxt {
expr_repr(self.tcx(), expr)
}

fn pat_to_str(pat: @ast::pat) -> ~str {
pat_repr(self.tcx(), pat)
}

fn expr_ty(ex: @ast::expr) -> ty::t {
match self.inh.node_types.find(ex.id) {
Some(t) => t,
Expand Down Expand Up @@ -1600,7 +1603,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
let fty = ty::mk_fn(tcx, copy fn_ty);

debug!("check_expr_fn_with_unifier %s fty=%s",
expr_to_str(expr, tcx.sess.intr()),
fcx.expr_to_str(expr),
fcx.infcx().ty_to_str(fty));

fcx.write_ty(expr.id, fty);
Expand Down Expand Up @@ -2713,7 +2716,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
do v.node.disr_expr.iter |e_ref| {
let e = *e_ref;
debug!("disr expr, checking %s",
expr_to_str(e, ccx.tcx.sess.intr()));
pprust::expr_to_str(e, ccx.tcx.sess.intr()));
let declty = ty::mk_int(ccx.tcx);
let fcx = blank_fn_ctxt(ccx, rty, e.id);
check_const_with_ty(fcx, e.span, e, declty);
Expand Down
Loading