rustc: Parse by-reference pattern bindings with the "ref" keyword
This commit is contained in:
@@ -473,11 +473,13 @@ impl methods for gather_loan_ctxt {
|
||||
}
|
||||
}
|
||||
|
||||
ast::pat_ident(_, none) if self.pat_is_variant(pat) {
|
||||
ast::pat_ident(_, _, none) if self.pat_is_variant(pat) {
|
||||
// nullary variant
|
||||
debug!{"nullary variant"};
|
||||
}
|
||||
ast::pat_ident(id, o_pat) {
|
||||
ast::pat_ident(_, id, o_pat) {
|
||||
// XXX: Needs to take by-ref/by-val into account.
|
||||
|
||||
// x or x @ p --- `x` must remain valid for the scope of the alt
|
||||
debug!{"defines identifier %s", pprust::path_to_str(id)};
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ fn check_arms(tcx: ty::ctxt, arms: ~[arm]) {
|
||||
|
||||
fn raw_pat(p: @pat) -> @pat {
|
||||
alt p.node {
|
||||
pat_ident(_, some(s)) { raw_pat(s) }
|
||||
_ { p }
|
||||
pat_ident(_, _, some(s)) => { raw_pat(s) }
|
||||
_ => { p }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,32 +199,34 @@ fn is_useful_specialized(tcx: ty::ctxt, m: matrix, v: ~[@pat], ctor: ctor,
|
||||
fn pat_ctor_id(tcx: ty::ctxt, p: @pat) -> option<ctor> {
|
||||
let pat = raw_pat(p);
|
||||
alt pat.node {
|
||||
pat_wild { none }
|
||||
pat_ident(_, _) | pat_enum(_, _) {
|
||||
pat_wild => { none }
|
||||
pat_ident(_, _, _) | pat_enum(_, _) => {
|
||||
alt tcx.def_map.find(pat.id) {
|
||||
some(def_variant(_, id)) { some(variant(id)) }
|
||||
_ { none }
|
||||
}
|
||||
}
|
||||
pat_lit(expr) { some(val(eval_const_expr(tcx, expr))) }
|
||||
pat_range(lo, hi) {
|
||||
pat_lit(expr) => { some(val(eval_const_expr(tcx, expr))) }
|
||||
pat_range(lo, hi) => {
|
||||
some(range(eval_const_expr(tcx, lo), eval_const_expr(tcx, hi)))
|
||||
}
|
||||
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) { some(single) }
|
||||
pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) => {
|
||||
some(single)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_wild(tcx: ty::ctxt, p: @pat) -> bool {
|
||||
let pat = raw_pat(p);
|
||||
alt pat.node {
|
||||
pat_wild { true }
|
||||
pat_ident(_, _) {
|
||||
pat_wild => { true }
|
||||
pat_ident(_, _, _) => {
|
||||
alt tcx.def_map.find(pat.id) {
|
||||
some(def_variant(_, _)) { false }
|
||||
_ { true }
|
||||
some(def_variant(_, _)) => { false }
|
||||
_ => { true }
|
||||
}
|
||||
}
|
||||
_ { false }
|
||||
_ => { false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +298,7 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
|
||||
alt r0.node {
|
||||
pat_wild { some(vec::append(vec::from_elem(arity, wild()),
|
||||
vec::tail(r))) }
|
||||
pat_ident(_, _) {
|
||||
pat_ident(_, _, _) {
|
||||
alt tcx.def_map.find(r0.id) {
|
||||
some(def_variant(_, id)) {
|
||||
if variant(id) == ctor_id { some(vec::tail(r)) }
|
||||
@@ -377,26 +379,26 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
||||
}
|
||||
|
||||
alt pat.node {
|
||||
pat_box(sub) | pat_uniq(sub) | pat_ident(_, some(sub)) {
|
||||
pat_box(sub) | pat_uniq(sub) | pat_ident(_, _, some(sub)) => {
|
||||
is_refutable(tcx, sub)
|
||||
}
|
||||
pat_wild | pat_ident(_, none) { false }
|
||||
pat_lit(_) | pat_range(_, _) { true }
|
||||
pat_rec(fields, _) {
|
||||
pat_wild | pat_ident(_, _, none) => { false }
|
||||
pat_lit(_) | pat_range(_, _) => { true }
|
||||
pat_rec(fields, _) => {
|
||||
for fields.each |it| {
|
||||
if is_refutable(tcx, it.pat) { ret true; }
|
||||
}
|
||||
false
|
||||
}
|
||||
pat_tup(elts) {
|
||||
pat_tup(elts) => {
|
||||
for elts.each |elt| { if is_refutable(tcx, elt) { ret true; } }
|
||||
false
|
||||
}
|
||||
pat_enum(_, some(args)) {
|
||||
pat_enum(_, some(args)) => {
|
||||
for args.each |p| { if is_refutable(tcx, p) { ret true; } };
|
||||
false
|
||||
}
|
||||
pat_enum(_,_) { false }
|
||||
pat_enum(_,_) => { false }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ fn pat_id_map(dm: resolve3::DefMap, pat: @pat) -> pat_id_map {
|
||||
fn pat_is_variant(dm: resolve3::DefMap, pat: @pat) -> bool {
|
||||
alt pat.node {
|
||||
pat_enum(_, _) { true }
|
||||
pat_ident(_, none) {
|
||||
pat_ident(_, _, none) {
|
||||
alt dm.find(pat.id) {
|
||||
some(def_variant(_, _)) { true }
|
||||
_ { false }
|
||||
@@ -38,7 +38,7 @@ fn pat_bindings(dm: resolve3::DefMap, pat: @pat,
|
||||
it: fn(node_id, span, @path)) {
|
||||
do walk_pat(pat) |p| {
|
||||
alt p.node {
|
||||
pat_ident(pth, _) if !pat_is_variant(dm, p) {
|
||||
pat_ident(_, pth, _) if !pat_is_variant(dm, p) {
|
||||
it(p.id, p.span, pth);
|
||||
}
|
||||
_ {}
|
||||
|
||||
@@ -208,7 +208,7 @@ fn resolve_arm(arm: ast::arm, cx: ctxt, visitor: visit::vt<ctxt>) {
|
||||
|
||||
fn resolve_pat(pat: @ast::pat, cx: ctxt, visitor: visit::vt<ctxt>) {
|
||||
alt pat.node {
|
||||
ast::pat_ident(path, _) {
|
||||
ast::pat_ident(_, path, _) {
|
||||
let defn_opt = cx.def_map.find(pat.id);
|
||||
alt defn_opt {
|
||||
some(ast::def_variant(_,_)) {
|
||||
|
||||
@@ -5,11 +5,11 @@ import metadata::cstore::find_use_stmt_cnum;
|
||||
import metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
|
||||
import middle::lang_items::LanguageItems;
|
||||
import middle::lint::{deny, allow, forbid, level, unused_imports, warn};
|
||||
import syntax::ast::{_mod, add, arm, bitand, bitor, bitxor, blk, bound_const};
|
||||
import syntax::ast::{bound_copy, bound_owned, bound_send, bound_trait};
|
||||
import syntax::ast::{capture_clause, class_ctor, class_dtor, class_member};
|
||||
import syntax::ast::{class_method, crate, crate_num, decl_item, def, def_arg};
|
||||
import syntax::ast::{def_binding, def_class, def_const, def_fn};
|
||||
import syntax::ast::{_mod, add, arm, bind_by_value, bitand, bitor, bitxor};
|
||||
import syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
|
||||
import syntax::ast::{bound_trait, capture_clause, class_ctor, class_dtor};
|
||||
import syntax::ast::{class_member, class_method, crate, crate_num, decl_item};
|
||||
import syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
|
||||
import syntax::ast::{def_foreign_mod, def_id, def_local, def_mod};
|
||||
import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param,
|
||||
def_typaram_binder};
|
||||
@@ -3734,8 +3734,8 @@ class Resolver {
|
||||
let pat_id = pattern.id;
|
||||
do walk_pat(pattern) |pattern| {
|
||||
alt pattern.node {
|
||||
pat_ident(path, _)
|
||||
if !path.global && path.idents.len() == 1u {
|
||||
pat_ident(_, path, _)
|
||||
if !path.global && path.idents.len() == 1u => {
|
||||
|
||||
// The meaning of pat_ident with no type parameters
|
||||
// depends on whether an enum variant with that name is in
|
||||
@@ -3748,14 +3748,14 @@ class Resolver {
|
||||
let atom = (*self.atom_table).intern(path.idents[0]);
|
||||
|
||||
alt self.resolve_enum_variant_or_const(atom) {
|
||||
FoundEnumVariant(def) if mode == RefutableMode {
|
||||
FoundEnumVariant(def) if mode == RefutableMode => {
|
||||
debug!{"(resolving pattern) resolving `%s` to \
|
||||
enum variant",
|
||||
*path.idents[0]};
|
||||
|
||||
self.record_def(pattern.id, def);
|
||||
}
|
||||
FoundEnumVariant(_) {
|
||||
FoundEnumVariant(_) => {
|
||||
self.session.span_err(pattern.span,
|
||||
fmt!{"declaration of `%s` \
|
||||
shadows an enum \
|
||||
@@ -3764,13 +3764,13 @@ class Resolver {
|
||||
atom_to_str
|
||||
(atom)});
|
||||
}
|
||||
FoundConst {
|
||||
FoundConst => {
|
||||
self.session.span_err(pattern.span,
|
||||
~"pattern variable \
|
||||
conflicts with a constant \
|
||||
in scope");
|
||||
}
|
||||
EnumVariantOrConstNotFound {
|
||||
EnumVariantOrConstNotFound => {
|
||||
debug!{"(resolving pattern) binding `%s`",
|
||||
*path.idents[0]};
|
||||
|
||||
@@ -3836,7 +3836,7 @@ class Resolver {
|
||||
}
|
||||
}
|
||||
|
||||
pat_ident(path, _) | pat_enum(path, _) {
|
||||
pat_ident(_, path, _) | pat_enum(path, _) => {
|
||||
// These two must be enum variants.
|
||||
alt self.resolve_path(path, ValueNS, false, visitor) {
|
||||
some(def @ def_variant(*)) {
|
||||
@@ -3860,16 +3860,16 @@ class Resolver {
|
||||
}
|
||||
}
|
||||
|
||||
pat_lit(expr) {
|
||||
pat_lit(expr) => {
|
||||
self.resolve_expr(expr, visitor);
|
||||
}
|
||||
|
||||
pat_range(first_expr, last_expr) {
|
||||
pat_range(first_expr, last_expr) => {
|
||||
self.resolve_expr(first_expr, visitor);
|
||||
self.resolve_expr(last_expr, visitor);
|
||||
}
|
||||
|
||||
_ {
|
||||
_ => {
|
||||
// Nothing to do.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,12 @@ fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> opt {
|
||||
core::unreachable();
|
||||
}
|
||||
|
||||
type bind_map = ~[{ident: ast::ident, val: ValueRef}];
|
||||
type bind_map = ~[{
|
||||
ident: ast::ident,
|
||||
val: ValueRef,
|
||||
mode: ast::binding_mode
|
||||
}];
|
||||
|
||||
fn assoc(key: ast::ident, list: bind_map) -> option<ValueRef> {
|
||||
for vec::each(list) |elt| {
|
||||
if str::eq(*elt.ident, *key) { ret some(elt.val); }
|
||||
@@ -98,7 +103,7 @@ type match_ = ~[match_branch];
|
||||
fn has_nested_bindings(m: match_, col: uint) -> bool {
|
||||
for vec::each(m) |br| {
|
||||
alt br.pats[col].node {
|
||||
ast::pat_ident(_, some(_)) { ret true; }
|
||||
ast::pat_ident(_, _, some(_)) { ret true; }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +114,7 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
|
||||
let mut result = ~[];
|
||||
for vec::each(m) |br| {
|
||||
alt br.pats[col].node {
|
||||
ast::pat_ident(name, some(inner)) {
|
||||
ast::pat_ident(mode, name, some(inner)) {
|
||||
let pats = vec::append(
|
||||
vec::slice(br.pats, 0u, col),
|
||||
vec::append(~[inner],
|
||||
@@ -118,7 +123,8 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
|
||||
@{pats: pats,
|
||||
bound: vec::append(
|
||||
br.bound, ~[{ident: path_to_ident(name),
|
||||
val: val}])
|
||||
val: val,
|
||||
mode: mode}])
|
||||
with *br});
|
||||
}
|
||||
_ { vec::push(result, br); }
|
||||
@@ -140,9 +146,11 @@ fn enter_match(dm: DefMap, m: match_, col: uint, val: ValueRef,
|
||||
vec::view(br.pats, col + 1u, br.pats.len()));
|
||||
let self = br.pats[col];
|
||||
let bound = alt self.node {
|
||||
ast::pat_ident(name, none) if !pat_is_variant(dm, self) {
|
||||
ast::pat_ident(mode, name, none) if !pat_is_variant(dm, self) {
|
||||
vec::append(br.bound,
|
||||
~[{ident: path_to_ident(name), val: val}])
|
||||
~[{ident: path_to_ident(name),
|
||||
val: val,
|
||||
mode: mode}])
|
||||
}
|
||||
_ { br.bound }
|
||||
};
|
||||
@@ -158,7 +166,7 @@ fn enter_default(dm: DefMap, m: match_, col: uint, val: ValueRef) -> match_ {
|
||||
do enter_match(dm, m, col, val) |p| {
|
||||
alt p.node {
|
||||
ast::pat_wild | ast::pat_rec(_, _) | ast::pat_tup(_) { some(~[]) }
|
||||
ast::pat_ident(_, none) if !pat_is_variant(dm, p) {
|
||||
ast::pat_ident(_, _, none) if !pat_is_variant(dm, p) {
|
||||
some(~[])
|
||||
}
|
||||
_ { none }
|
||||
@@ -177,7 +185,7 @@ fn enter_opt(tcx: ty::ctxt, m: match_, opt: opt, col: uint,
|
||||
vec::from_elem(variant_size, dummy))) }
|
||||
else { none }
|
||||
}
|
||||
ast::pat_ident(_, none) if pat_is_variant(tcx.def_map, p) {
|
||||
ast::pat_ident(_, _, none) if pat_is_variant(tcx.def_map, p) {
|
||||
if opt_eq(tcx, variant_opt(tcx, p.id), opt) { some(~[]) }
|
||||
else { none }
|
||||
}
|
||||
@@ -359,7 +367,7 @@ fn pick_col(m: match_) -> uint {
|
||||
fn score(p: @ast::pat) -> uint {
|
||||
alt p.node {
|
||||
ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) { 1u }
|
||||
ast::pat_ident(_, some(p)) { score(p) }
|
||||
ast::pat_ident(_, _, some(p)) { score(p) }
|
||||
_ { 0u }
|
||||
}
|
||||
}
|
||||
@@ -725,7 +733,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
||||
|
||||
// Necessary since bind_irrefutable_pat is called outside trans_alt
|
||||
alt pat.node {
|
||||
ast::pat_ident(_,inner) {
|
||||
ast::pat_ident(_, _,inner) {
|
||||
if pat_is_variant(bcx.tcx().def_map, pat) { ret bcx; }
|
||||
if make_copy {
|
||||
let ty = node_id_type(bcx, pat.id);
|
||||
|
||||
@@ -4380,7 +4380,7 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
|
||||
let _icx = cx.insn_ctxt(~"alloc_local");
|
||||
let t = node_id_type(cx, local.node.id);
|
||||
let simple_name = alt local.node.pat.node {
|
||||
ast::pat_ident(pth, none) { some(path_to_ident(pth)) }
|
||||
ast::pat_ident(_, pth, none) { some(path_to_ident(pth)) }
|
||||
_ { none }
|
||||
};
|
||||
let val = alloc_ty(cx, t);
|
||||
|
||||
@@ -646,7 +646,7 @@ fn create_local_var(bcx: block, local: @ast::local)
|
||||
}
|
||||
|
||||
let name = alt local.node.pat.node {
|
||||
ast::pat_ident(pth, _) { ast_util::path_to_ident(pth) }
|
||||
ast::pat_ident(_, pth, _) { ast_util::path_to_ident(pth) }
|
||||
// FIXME this should be handled (#2533)
|
||||
_ { fail ~"no single variable name for local"; }
|
||||
};
|
||||
|
||||
@@ -320,14 +320,14 @@ fn check_fn(ccx: @crate_ctxt,
|
||||
// Add pattern bindings.
|
||||
let visit_pat = fn@(p: @ast::pat, &&e: (), v: visit::vt<()>) {
|
||||
alt p.node {
|
||||
ast::pat_ident(path, _)
|
||||
if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) {
|
||||
ast::pat_ident(_, path, _)
|
||||
if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) => {
|
||||
assign(p.id, none);
|
||||
debug!{"Pattern binding %s is assigned to %s",
|
||||
*path.idents[0],
|
||||
fcx.locals.get(p.id).to_str()};
|
||||
}
|
||||
_ {}
|
||||
_ => {}
|
||||
}
|
||||
visit::visit_pat(p, e, v);
|
||||
};
|
||||
|
||||
@@ -155,7 +155,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
||||
}
|
||||
fcx.write_ty(pat.id, b_ty);
|
||||
}
|
||||
ast::pat_ident(name, sub) if !pat_is_variant(tcx.def_map, pat) {
|
||||
ast::pat_ident(_, name, sub) if !pat_is_variant(tcx.def_map, pat) {
|
||||
let vid = lookup_local(fcx, pat.span, pat.id);
|
||||
let mut typ = ty::mk_var(tcx, vid);
|
||||
demand::suptype(fcx, pat.span, expected, typ);
|
||||
@@ -171,7 +171,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_ident(path, c) {
|
||||
ast::pat_ident(_, path, c) {
|
||||
check_pat_variant(pcx, pat, path, some(~[]), expected);
|
||||
}
|
||||
ast::pat_enum(path, subpats) {
|
||||
|
||||
@@ -105,7 +105,7 @@ fn visit_local(l: @ast::local, &&rcx: @rcx, v: rvt) {
|
||||
fn visit_pat(p: @ast::pat, &&rcx: @rcx, v: rvt) {
|
||||
let fcx = rcx.fcx;
|
||||
alt p.node {
|
||||
ast::pat_ident(path, _)
|
||||
ast::pat_ident(_, path, _)
|
||||
if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) {
|
||||
debug!{"visit_pat binding=%s", *path.idents[0]};
|
||||
visit_node(p.id, p.span, rcx);
|
||||
|
||||
Reference in New Issue
Block a user