rustc: Support irrefutable patterns in function arguments. r=nmatsakis
This commit is contained in:
parent
b223c9c465
commit
0fc952372a
31 changed files with 392 additions and 159 deletions
|
@ -85,7 +85,7 @@ pub mod ct {
|
|||
pub enum Piece { PieceString(~str), PieceConv(Conv), }
|
||||
pub type ErrorFn = fn@(&str) -> ! ;
|
||||
|
||||
pub fn parse_fmt_string(s: &str, error: ErrorFn) -> ~[Piece] {
|
||||
pub fn parse_fmt_string(s: &str, err: ErrorFn) -> ~[Piece] {
|
||||
let mut pieces: ~[Piece] = ~[];
|
||||
let lim = str::len(s);
|
||||
let mut buf = ~"";
|
||||
|
@ -103,7 +103,7 @@ pub mod ct {
|
|||
if curr == ~"%" {
|
||||
i += 1;
|
||||
if i >= lim {
|
||||
error(~"unterminated conversion at end of string");
|
||||
err(~"unterminated conversion at end of string");
|
||||
}
|
||||
let curr2 = str::slice(s, i, i+1);
|
||||
if curr2 == ~"%" {
|
||||
|
@ -111,7 +111,7 @@ pub mod ct {
|
|||
i += 1;
|
||||
} else {
|
||||
buf = flush_buf(move buf, &mut pieces);
|
||||
let rs = parse_conversion(s, i, lim, error);
|
||||
let rs = parse_conversion(s, i, lim, err);
|
||||
pieces.push(copy rs.piece);
|
||||
i = rs.next;
|
||||
}
|
||||
|
@ -143,13 +143,13 @@ pub mod ct {
|
|||
}
|
||||
}
|
||||
pub fn parse_conversion(s: &str, i: uint, lim: uint,
|
||||
error: ErrorFn) ->
|
||||
err: ErrorFn) ->
|
||||
{piece: Piece, next: uint} {
|
||||
let parm = parse_parameter(s, i, lim);
|
||||
let flags = parse_flags(s, parm.next, lim);
|
||||
let width = parse_count(s, flags.next, lim);
|
||||
let prec = parse_precision(s, width.next, lim);
|
||||
let ty = parse_type(s, prec.next, lim, error);
|
||||
let ty = parse_type(s, prec.next, lim, err);
|
||||
return {piece:
|
||||
PieceConv({param: parm.param,
|
||||
flags: copy flags.flags,
|
||||
|
@ -239,9 +239,9 @@ pub mod ct {
|
|||
}
|
||||
} else { {count: CountImplied, next: i} };
|
||||
}
|
||||
pub fn parse_type(s: &str, i: uint, lim: uint, error: ErrorFn) ->
|
||||
pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) ->
|
||||
{ty: Ty, next: uint} {
|
||||
if i >= lim { error(~"missing type in conversion"); }
|
||||
if i >= lim { err(~"missing type in conversion"); }
|
||||
let tstr = str::slice(s, i, i+1u);
|
||||
// FIXME (#2249): Do we really want two signed types here?
|
||||
// How important is it to be printf compatible?
|
||||
|
@ -268,7 +268,7 @@ pub mod ct {
|
|||
TyFloat
|
||||
} else if tstr == ~"?" {
|
||||
TyPoly
|
||||
} else { error(~"unknown type in conversion: " + tstr) };
|
||||
} else { err(~"unknown type in conversion: " + tstr) };
|
||||
return {ty: t, next: i + 1u};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ pub trait SendMap<K:Eq Hash, V: Copy> {
|
|||
|
||||
/// Open addressing with linear probing.
|
||||
pub mod linear {
|
||||
const initial_capacity: uint = 32u; // 2^5
|
||||
const INITIAL_CAPACITY: uint = 32u; // 2^5
|
||||
|
||||
struct Bucket<K:Eq Hash,V> {
|
||||
hash: uint,
|
||||
|
@ -62,7 +62,7 @@ pub mod linear {
|
|||
}
|
||||
|
||||
pub fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
|
||||
linear_map_with_capacity(32)
|
||||
linear_map_with_capacity(INITIAL_CAPACITY)
|
||||
}
|
||||
|
||||
pub fn linear_map_with_capacity<K:Eq Hash,V>(
|
||||
|
|
|
@ -959,15 +959,15 @@ extern mod llvm {
|
|||
/** Opens an object file. */
|
||||
fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
|
||||
/** Closes an object file. */
|
||||
fn LLVMDisposeObjectFile(ObjectFile: ObjectFileRef);
|
||||
fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
|
||||
|
||||
/** Enumerates the sections in an object file. */
|
||||
fn LLVMGetSections(ObjectFile: ObjectFileRef) -> SectionIteratorRef;
|
||||
fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
|
||||
/** Destroys a section iterator. */
|
||||
fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
|
||||
/** Returns true if the section iterator is at the end of the section
|
||||
list: */
|
||||
fn LLVMIsSectionIteratorAtEnd(ObjectFile: ObjectFileRef,
|
||||
fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
|
||||
SI: SectionIteratorRef) -> Bool;
|
||||
/** Moves the section iterator to point to the next section. */
|
||||
fn LLVMMoveToNextSection(SI: SectionIteratorRef);
|
||||
|
@ -1228,9 +1228,9 @@ struct object_file_res {
|
|||
drop { llvm::LLVMDisposeObjectFile(self.ObjectFile); }
|
||||
}
|
||||
|
||||
fn object_file_res(ObjectFile: ObjectFileRef) -> object_file_res{
|
||||
fn object_file_res(ObjFile: ObjectFileRef) -> object_file_res {
|
||||
object_file_res {
|
||||
ObjectFile: ObjectFile
|
||||
ObjectFile: ObjFile
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -570,7 +570,20 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
|
|||
visit::fk_anon(*) | visit::fk_fn_block(*) |
|
||||
visit::fk_method(*) | visit::fk_item_fn(*) |
|
||||
visit::fk_dtor(*) => {
|
||||
self.fn_args = @decl.inputs.map(|i| i.id );
|
||||
let mut fn_args = ~[];
|
||||
for decl.inputs.each |input| {
|
||||
// For the purposes of purity, only consider function-
|
||||
// typed bindings in trivial patterns to be function
|
||||
// arguments. For example, do not allow `f` and `g` in
|
||||
// (f, g): (&fn(), &fn()) to be called.
|
||||
match input.pat.node {
|
||||
ast::pat_ident(_, _, None) => {
|
||||
fn_args.push(input.pat.id);
|
||||
}
|
||||
_ => {} // Ignore this argument.
|
||||
}
|
||||
}
|
||||
self.fn_args = @move fn_args;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
|||
visit::visit_crate(*crate, (), visit::mk_vt(@{
|
||||
visit_expr: |a,b,c| check_expr(tcx, a, b, c),
|
||||
visit_local: |a,b,c| check_local(tcx, a, b, c),
|
||||
visit_fn: |kind, decl, body, sp, id, e, v|
|
||||
check_fn(tcx, kind, decl, body, sp, id, e, v),
|
||||
.. *visit::default_visitor::<()>()
|
||||
}));
|
||||
tcx.sess.abort_if_errors();
|
||||
|
@ -372,8 +374,8 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
|
|||
ty::ty_rec(flds) => flds,
|
||||
_ => fail ~"bad type for pat_rec"
|
||||
};
|
||||
let args = vec::map(ty_flds, |ty_f| {
|
||||
match vec::find(flds, |f| f.ident == ty_f.ident ) {
|
||||
let args = vec::map(ty_flds, |ty_fld| {
|
||||
match vec::find(flds, |f| f.ident == ty_fld.ident ) {
|
||||
Some(f) => f.pat,
|
||||
_ => wild()
|
||||
}
|
||||
|
@ -386,8 +388,8 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
|
|||
def_variant(_, variant_id) => {
|
||||
if variant(variant_id) == ctor_id {
|
||||
// XXX: Is this right? --pcw
|
||||
let args = flds.map(|ty_f| {
|
||||
match vec::find(flds, |f| f.ident == ty_f.ident) {
|
||||
let args = flds.map(|ty_field| {
|
||||
match vec::find(flds, |f| f.ident == ty_field.ident) {
|
||||
Some(f) => f.pat,
|
||||
_ => wild()
|
||||
}
|
||||
|
@ -465,6 +467,23 @@ fn check_local(tcx: ty::ctxt, loc: @local, &&s: (), v: visit::vt<()>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_fn(tcx: ty::ctxt,
|
||||
kind: visit::fn_kind,
|
||||
decl: fn_decl,
|
||||
body: blk,
|
||||
sp: span,
|
||||
id: node_id,
|
||||
&&s: (),
|
||||
v: visit::vt<()>) {
|
||||
visit::visit_fn(kind, decl, body, sp, id, s, v);
|
||||
for decl.inputs.each |input| {
|
||||
if is_refutable(tcx, input.pat) {
|
||||
tcx.sess.span_err(input.pat.span,
|
||||
~"refutable pattern in function argument");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_refutable(tcx: ty::ctxt, pat: &pat) -> bool {
|
||||
match tcx.def_map.find(pat.id) {
|
||||
Some(def_variant(enum_id, _)) => {
|
||||
|
|
|
@ -414,9 +414,13 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
|
|||
debug!("creating fn_maps: %x", ptr::addr_of(&(*fn_maps)) as uint);
|
||||
|
||||
for decl.inputs.each |arg| {
|
||||
debug!("adding argument %d", arg.id);
|
||||
let mode = ty::resolved_mode(self.tcx, arg.mode);
|
||||
(*fn_maps).add_variable(Arg(arg.id, arg.ident, mode));
|
||||
do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
|
||||
|_bm, arg_id, _x, path| {
|
||||
debug!("adding argument %d", arg_id);
|
||||
let ident = ast_util::path_to_ident(path);
|
||||
(*fn_maps).add_variable(Arg(arg_id, ident, mode));
|
||||
}
|
||||
};
|
||||
|
||||
// gather up the various local variables, significant expressions,
|
||||
|
@ -447,7 +451,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
|
|||
});
|
||||
check_vt.visit_block(body, lsets, check_vt);
|
||||
lsets.check_ret(id, sp, fk, entry_ln);
|
||||
lsets.warn_about_unused_args(sp, decl, entry_ln);
|
||||
lsets.warn_about_unused_args(decl, entry_ln);
|
||||
}
|
||||
|
||||
fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) {
|
||||
|
@ -937,8 +941,11 @@ impl Liveness {
|
|||
// the end. This will prevent us from moving out of
|
||||
// such variables but also prevent us from registering
|
||||
// last uses and so forth.
|
||||
let var = self.variable(arg.id, blk.span);
|
||||
self.acc(self.s.exit_ln, var, ACC_READ);
|
||||
do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
|
||||
|_bm, arg_id, _sp, _path| {
|
||||
let var = self.variable(arg_id, blk.span);
|
||||
self.acc(self.s.exit_ln, var, ACC_READ);
|
||||
}
|
||||
}
|
||||
by_move | by_copy => {
|
||||
// These are owned modes. If we don't use the
|
||||
|
@ -1791,10 +1798,13 @@ impl @Liveness {
|
|||
if name[0] == ('_' as u8) {None} else {Some(name)}
|
||||
}
|
||||
|
||||
fn warn_about_unused_args(sp: span, decl: fn_decl, entry_ln: LiveNode) {
|
||||
fn warn_about_unused_args(decl: fn_decl, entry_ln: LiveNode) {
|
||||
for decl.inputs.each |arg| {
|
||||
let var = self.variable(arg.id, arg.ty.span);
|
||||
self.warn_about_unused(sp, entry_ln, var);
|
||||
do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
|
||||
|_bm, p_id, sp, _n| {
|
||||
let var = self.variable(p_id, sp);
|
||||
self.warn_about_unused(sp, entry_ln, var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge};
|
|||
use syntax::ast::{gt, ident, impure_fn, inherited, item, item_class};
|
||||
use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod};
|
||||
use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le};
|
||||
use syntax::ast::{local, local_crate, lt, method, module_ns, mul, ne, neg};
|
||||
use syntax::ast::{node_id, pat, pat_enum, pat_ident, path, prim_ty};
|
||||
use syntax::ast::{local, local_crate, lt, method, mode, module_ns, mul, ne};
|
||||
use syntax::ast::{neg, node_id, pat, pat_enum, pat_ident, path, prim_ty};
|
||||
use syntax::ast::{pat_box, pat_lit, pat_range, pat_rec, pat_struct};
|
||||
use syntax::ast::{pat_tup, pat_uniq, pat_wild, private, provided, public};
|
||||
use syntax::ast::{required, rem, self_ty_, shl, shr, stmt_decl};
|
||||
|
@ -103,12 +103,32 @@ struct Export2 {
|
|||
|
||||
enum PatternBindingMode {
|
||||
RefutableMode,
|
||||
IrrefutableMode
|
||||
LocalIrrefutableMode,
|
||||
ArgumentIrrefutableMode(mode)
|
||||
}
|
||||
|
||||
impl PatternBindingMode : cmp::Eq {
|
||||
pure fn eq(other: &PatternBindingMode) -> bool {
|
||||
(self as uint) == ((*other) as uint)
|
||||
match self {
|
||||
RefutableMode => {
|
||||
match *other {
|
||||
RefutableMode => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
LocalIrrefutableMode => {
|
||||
match *other {
|
||||
LocalIrrefutableMode => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
ArgumentIrrefutableMode(mode_a) => {
|
||||
match *other {
|
||||
ArgumentIrrefutableMode(mode_b) => mode_a == mode_b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pure fn ne(other: &PatternBindingMode) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
@ -3770,15 +3790,17 @@ impl Resolver {
|
|||
}
|
||||
Some(declaration) => {
|
||||
for declaration.inputs.each |argument| {
|
||||
let name = argument.ident;
|
||||
let def_like = dl_def(def_arg(argument.id,
|
||||
argument.mode));
|
||||
(*function_value_rib).bindings.insert(name, def_like);
|
||||
let binding_mode =
|
||||
ArgumentIrrefutableMode(argument.mode);
|
||||
self.resolve_pattern(argument.pat,
|
||||
binding_mode,
|
||||
Immutable,
|
||||
None,
|
||||
visitor);
|
||||
|
||||
self.resolve_type(argument.ty, visitor);
|
||||
|
||||
debug!("(resolving function) recorded argument `%s`",
|
||||
self.session.str_of(name));
|
||||
debug!("(resolving function) recorded argument");
|
||||
}
|
||||
|
||||
self.resolve_type(declaration.output, visitor);
|
||||
|
@ -4013,7 +4035,7 @@ impl Resolver {
|
|||
}
|
||||
|
||||
// Resolve the pattern.
|
||||
self.resolve_pattern(local.node.pat, IrrefutableMode, mutability,
|
||||
self.resolve_pattern(local.node.pat, LocalIrrefutableMode, mutability,
|
||||
None, visitor);
|
||||
}
|
||||
|
||||
|
@ -4249,10 +4271,14 @@ impl Resolver {
|
|||
|
||||
def_binding(pattern.id, binding_mode)
|
||||
}
|
||||
IrrefutableMode => {
|
||||
LocalIrrefutableMode => {
|
||||
// But for locals, we use `def_local`.
|
||||
def_local(pattern.id, is_mutable)
|
||||
}
|
||||
ArgumentIrrefutableMode(argument_mode) => {
|
||||
// And for function arguments, `def_arg`.
|
||||
def_arg(pattern.id, argument_mode)
|
||||
}
|
||||
};
|
||||
|
||||
// Record the definition so that later passes
|
||||
|
|
|
@ -1410,18 +1410,29 @@ fn trans_alt_inner(scope_cx: block,
|
|||
return controlflow::join_blocks(scope_cx, dvec::unwrap(move arm_cxs));
|
||||
|
||||
fn mk_fail(bcx: block, sp: span, msg: ~str,
|
||||
done: @mut Option<BasicBlockRef>) -> BasicBlockRef {
|
||||
match *done { Some(bb) => return bb, _ => () }
|
||||
finished: @mut Option<BasicBlockRef>) -> BasicBlockRef {
|
||||
match *finished { Some(bb) => return bb, _ => () }
|
||||
let fail_cx = sub_block(bcx, ~"case_fallthrough");
|
||||
controlflow::trans_fail(fail_cx, Some(sp), msg);
|
||||
*done = Some(fail_cx.llbb);
|
||||
*finished = Some(fail_cx.llbb);
|
||||
return fail_cx.llbb;
|
||||
}
|
||||
}
|
||||
|
||||
enum IrrefutablePatternBindingMode {
|
||||
// Stores the association between node ID and LLVM value in `lllocals`.
|
||||
BindLocal,
|
||||
// Stores the association between node ID and LLVM value in `llargs`.
|
||||
BindArgument
|
||||
}
|
||||
|
||||
// Not alt-related, but similar to the pattern-munging code above
|
||||
fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
||||
make_copy: bool) -> block {
|
||||
fn bind_irrefutable_pat(bcx: block,
|
||||
pat: @ast::pat,
|
||||
val: ValueRef,
|
||||
make_copy: bool,
|
||||
binding_mode: IrrefutablePatternBindingMode)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("alt::bind_irrefutable_pat");
|
||||
let ccx = bcx.fcx.ccx;
|
||||
let mut bcx = bcx;
|
||||
|
@ -1439,14 +1450,31 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
|||
mode: ByRef, source: FromRvalue};
|
||||
let scratch = scratch_datum(bcx, binding_ty, false);
|
||||
datum.copy_to_datum(bcx, INIT, scratch);
|
||||
bcx.fcx.lllocals.insert(pat.id, local_mem(scratch.val));
|
||||
match binding_mode {
|
||||
BindLocal => {
|
||||
bcx.fcx.lllocals.insert(pat.id,
|
||||
local_mem(scratch.val));
|
||||
}
|
||||
BindArgument => {
|
||||
bcx.fcx.llargs.insert(pat.id,
|
||||
local_mem(scratch.val));
|
||||
}
|
||||
}
|
||||
add_clean(bcx, scratch.val, binding_ty);
|
||||
} else {
|
||||
bcx.fcx.lllocals.insert(pat.id, local_mem(val));
|
||||
match binding_mode {
|
||||
BindLocal => {
|
||||
bcx.fcx.lllocals.insert(pat.id, local_mem(val));
|
||||
}
|
||||
BindArgument => {
|
||||
bcx.fcx.llargs.insert(pat.id, local_mem(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for inner.each |inner_pat| {
|
||||
bcx = bind_irrefutable_pat(bcx, *inner_pat, val, true);
|
||||
bcx = bind_irrefutable_pat(
|
||||
bcx, *inner_pat, val, true, binding_mode);
|
||||
}
|
||||
}
|
||||
ast::pat_enum(_, sub_pats) => {
|
||||
|
@ -1460,7 +1488,8 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
|||
bcx = bind_irrefutable_pat(bcx,
|
||||
sub_pat[i],
|
||||
*argval,
|
||||
make_copy);
|
||||
make_copy,
|
||||
binding_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1473,8 +1502,11 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
|||
// This is the tuple variant case.
|
||||
for vec::eachi(elems) |i, elem| {
|
||||
let fldptr = GEPi(bcx, val, struct_field(i));
|
||||
bcx = bind_irrefutable_pat(bcx, *elem, fldptr,
|
||||
make_copy);
|
||||
bcx = bind_irrefutable_pat(bcx,
|
||||
*elem,
|
||||
fldptr,
|
||||
make_copy,
|
||||
binding_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1491,24 +1523,40 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
|
|||
for vec::each(fields) |f| {
|
||||
let ix = ty::field_idx_strict(tcx, f.ident, field_tys);
|
||||
let fldptr = GEPi(bcx, val, struct_field(ix));
|
||||
bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, make_copy);
|
||||
bcx = bind_irrefutable_pat(bcx,
|
||||
f.pat,
|
||||
fldptr,
|
||||
make_copy,
|
||||
binding_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::pat_tup(elems) => {
|
||||
for vec::eachi(elems) |i, elem| {
|
||||
let fldptr = GEPi(bcx, val, [0u, i]);
|
||||
bcx = bind_irrefutable_pat(bcx, *elem, fldptr, make_copy);
|
||||
bcx = bind_irrefutable_pat(bcx,
|
||||
*elem,
|
||||
fldptr,
|
||||
make_copy,
|
||||
binding_mode);
|
||||
}
|
||||
}
|
||||
ast::pat_box(inner) | ast::pat_uniq(inner) => {
|
||||
let llbox = Load(bcx, val);
|
||||
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||
bcx = bind_irrefutable_pat(bcx, inner, unboxed, true);
|
||||
bcx = bind_irrefutable_pat(bcx,
|
||||
inner,
|
||||
unboxed,
|
||||
true,
|
||||
binding_mode);
|
||||
}
|
||||
ast::pat_region(inner) => {
|
||||
let loaded_val = Load(bcx, val);
|
||||
bcx = bind_irrefutable_pat(bcx, inner, loaded_val, true);
|
||||
bcx = bind_irrefutable_pat(bcx,
|
||||
inner,
|
||||
loaded_val,
|
||||
true,
|
||||
binding_mode);
|
||||
}
|
||||
ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) => ()
|
||||
}
|
||||
|
|
|
@ -991,7 +991,11 @@ fn init_local(bcx: block, local: @ast::local) -> block {
|
|||
bcx.to_str());
|
||||
add_clean(bcx, llptr, ty);
|
||||
|
||||
return alt::bind_irrefutable_pat(bcx, local.node.pat, llptr, false);
|
||||
return alt::bind_irrefutable_pat(bcx,
|
||||
local.node.pat,
|
||||
llptr,
|
||||
false,
|
||||
alt::BindLocal);
|
||||
}
|
||||
|
||||
fn trans_stmt(cx: block, s: ast::stmt) -> block {
|
||||
|
@ -1529,6 +1533,12 @@ fn copy_args_to_allocas(fcx: fn_ctxt,
|
|||
}
|
||||
}
|
||||
|
||||
bcx = alt::bind_irrefutable_pat(bcx,
|
||||
args[arg_n].pat,
|
||||
llarg,
|
||||
false,
|
||||
alt::BindArgument);
|
||||
|
||||
fcx.llargs.insert(arg_id, local_mem(llarg));
|
||||
|
||||
if fcx.ccx.sess.opts.extra_debuginfo {
|
||||
|
@ -1658,7 +1668,9 @@ fn trans_enum_variant(ccx: @crate_ctxt,
|
|||
let fn_args = vec::map(args, |varg|
|
||||
{mode: ast::expl(ast::by_copy),
|
||||
ty: varg.ty,
|
||||
ident: special_idents::arg,
|
||||
pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
|
||||
ast_util::dummy_sp(),
|
||||
special_idents::arg),
|
||||
id: varg.id});
|
||||
let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None,
|
||||
param_substs, None);
|
||||
|
@ -1714,7 +1726,9 @@ fn trans_tuple_struct(ccx: @crate_ctxt,
|
|||
{
|
||||
mode: ast::expl(ast::by_copy),
|
||||
ty: field.node.ty,
|
||||
ident: special_idents::arg,
|
||||
pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
|
||||
ast_util::dummy_sp(),
|
||||
special_idents::arg),
|
||||
id: field.node.id
|
||||
}
|
||||
};
|
||||
|
|
|
@ -320,9 +320,9 @@ impl cleantype : cmp::Eq {
|
|||
type cleanup_path = {target: Option<BasicBlockRef>,
|
||||
dest: BasicBlockRef};
|
||||
|
||||
fn scope_clean_changed(info: scope_info) {
|
||||
if info.cleanup_paths.len() > 0u { info.cleanup_paths = ~[]; }
|
||||
info.landing_pad = None;
|
||||
fn scope_clean_changed(scope_info: scope_info) {
|
||||
if scope_info.cleanup_paths.len() > 0u { scope_info.cleanup_paths = ~[]; }
|
||||
scope_info.landing_pad = None;
|
||||
}
|
||||
|
||||
fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
|
||||
|
@ -361,11 +361,11 @@ fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
|
|||
ty_to_str(bcx.ccx().tcx, t));
|
||||
let {root, rooted} = root_for_cleanup(bcx, val, t);
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||
do in_scope_cx(bcx) |info| {
|
||||
info.cleanups.push(
|
||||
do in_scope_cx(bcx) |scope_info| {
|
||||
scope_info.cleanups.push(
|
||||
clean(|a| glue::drop_ty_root(a, root, rooted, t),
|
||||
cleanup_type));
|
||||
scope_clean_changed(info);
|
||||
scope_clean_changed(scope_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,11 +375,11 @@ fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
|
|||
cx.to_str(), val_str(cx.ccx().tn, val),
|
||||
ty_to_str(cx.ccx().tcx, ty));
|
||||
let cleanup_type = cleanup_type(cx.tcx(), ty);
|
||||
do in_scope_cx(cx) |info| {
|
||||
info.cleanups.push(
|
||||
do in_scope_cx(cx) |scope_info| {
|
||||
scope_info.cleanups.push(
|
||||
clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
|
||||
cleanup_type));
|
||||
scope_clean_changed(info);
|
||||
scope_clean_changed(scope_info);
|
||||
}
|
||||
}
|
||||
fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
|
||||
|
@ -389,11 +389,11 @@ fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
|
|||
ty_to_str(bcx.ccx().tcx, t));
|
||||
let {root, rooted} = root_for_cleanup(bcx, val, t);
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||
do in_scope_cx(bcx) |info| {
|
||||
info.cleanups.push(
|
||||
do in_scope_cx(bcx) |scope_info| {
|
||||
scope_info.cleanups.push(
|
||||
clean_temp(val, |a| glue::drop_ty_root(a, root, rooted, t),
|
||||
cleanup_type));
|
||||
scope_clean_changed(info);
|
||||
scope_clean_changed(scope_info);
|
||||
}
|
||||
}
|
||||
fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
|
||||
|
@ -401,10 +401,10 @@ fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
|
|||
heap_shared => |a| glue::trans_free(a, ptr),
|
||||
heap_exchange => |a| glue::trans_unique_free(a, ptr)
|
||||
};
|
||||
do in_scope_cx(cx) |info| {
|
||||
info.cleanups.push(clean_temp(ptr, free_fn,
|
||||
do in_scope_cx(cx) |scope_info| {
|
||||
scope_info.cleanups.push(clean_temp(ptr, free_fn,
|
||||
normal_exit_and_unwind));
|
||||
scope_clean_changed(info);
|
||||
scope_clean_changed(scope_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,20 +413,20 @@ fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
|
|||
// this will be more involved. For now, we simply zero out the local, and the
|
||||
// drop glue checks whether it is zero.
|
||||
fn revoke_clean(cx: block, val: ValueRef) {
|
||||
do in_scope_cx(cx) |info| {
|
||||
do in_scope_cx(cx) |scope_info| {
|
||||
let cleanup_pos = vec::position(
|
||||
info.cleanups,
|
||||
scope_info.cleanups,
|
||||
|cu| match *cu {
|
||||
clean_temp(v, _, _) if v == val => true,
|
||||
_ => false
|
||||
});
|
||||
for cleanup_pos.each |i| {
|
||||
info.cleanups =
|
||||
vec::append(vec::slice(info.cleanups, 0u, *i),
|
||||
vec::view(info.cleanups,
|
||||
scope_info.cleanups =
|
||||
vec::append(vec::slice(scope_info.cleanups, 0u, *i),
|
||||
vec::view(scope_info.cleanups,
|
||||
*i + 1u,
|
||||
info.cleanups.len()));
|
||||
scope_clean_changed(info);
|
||||
scope_info.cleanups.len()));
|
||||
scope_clean_changed(scope_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -664,13 +664,13 @@ fn create_local_var(bcx: block, local: @ast::local)
|
|||
}
|
||||
|
||||
fn create_arg(bcx: block, arg: ast::arg, sp: span)
|
||||
-> @metadata<argument_md> unsafe {
|
||||
-> Option<@metadata<argument_md>> unsafe {
|
||||
let fcx = bcx.fcx, cx = fcx.ccx;
|
||||
let cache = get_cache(cx);
|
||||
let tg = ArgVariableTag;
|
||||
match cached_metadata::<@metadata<argument_md>>(
|
||||
cache, ArgVariableTag, |md| md.data.id == arg.id) {
|
||||
option::Some(md) => return md,
|
||||
option::Some(md) => return Some(md),
|
||||
option::None => ()
|
||||
}
|
||||
|
||||
|
@ -680,18 +680,32 @@ fn create_arg(bcx: block, arg: ast::arg, sp: span)
|
|||
let tymd = create_ty(cx, ty, arg.ty);
|
||||
let filemd = create_file(cx, loc.file.name);
|
||||
let context = create_function(bcx.fcx);
|
||||
let mdnode = create_var(tg, context.node, cx.sess.str_of(arg.ident),
|
||||
filemd.node, loc.line as int, tymd.node);
|
||||
let mdval = @{node: mdnode, data: {id: arg.id}};
|
||||
update_cache(cache, tg, argument_metadata(mdval));
|
||||
|
||||
let llptr = match fcx.llargs.get(arg.id) {
|
||||
local_mem(v) | local_imm(v) => v,
|
||||
};
|
||||
let declargs = ~[llmdnode(~[llptr]), mdnode];
|
||||
trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"),
|
||||
declargs);
|
||||
return mdval;
|
||||
match arg.pat.node {
|
||||
ast::pat_ident(_, path, _) => {
|
||||
// XXX: This is wrong; it should work for multiple bindings.
|
||||
let mdnode = create_var(tg,
|
||||
context.node,
|
||||
cx.sess.str_of(path.idents.last()),
|
||||
filemd.node,
|
||||
loc.line as int,
|
||||
tymd.node);
|
||||
|
||||
let mdval = @{node: mdnode, data: {id: arg.id}};
|
||||
update_cache(cache, tg, argument_metadata(mdval));
|
||||
|
||||
let llptr = match fcx.llargs.get(arg.id) {
|
||||
local_mem(v) | local_imm(v) => v,
|
||||
};
|
||||
let declargs = ~[llmdnode(~[llptr]), mdnode];
|
||||
trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"),
|
||||
declargs);
|
||||
return Some(mdval);
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_source_pos(cx: block, s: span) {
|
||||
|
|
|
@ -261,9 +261,9 @@ fn call_substructure_method(bcx: block,
|
|||
vtable_result);
|
||||
let llfn = fn_data.llfn;
|
||||
|
||||
let cb: &fn(block) -> Callee = |block| {
|
||||
let cb: &fn(block) -> Callee = |bloc| {
|
||||
Callee {
|
||||
bcx: block,
|
||||
bcx: bloc,
|
||||
data: Method(MethodData {
|
||||
llfn: llfn,
|
||||
llself: llselfval,
|
||||
|
|
|
@ -2532,18 +2532,19 @@ fn type_param(ty: t) -> Option<uint> {
|
|||
|
||||
// Returns the type and mutability of *t.
|
||||
//
|
||||
// The parameter `expl` indicates if this is an *explicit* dereference. Some
|
||||
// types---notably unsafe ptrs---can only be dereferenced explicitly.
|
||||
fn deref(cx: ctxt, t: t, expl: bool) -> Option<mt> {
|
||||
deref_sty(cx, &get(t).sty, expl)
|
||||
// The parameter `explicit` indicates if this is an *explicit* dereference.
|
||||
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
|
||||
fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
|
||||
deref_sty(cx, &get(t).sty, explicit)
|
||||
}
|
||||
fn deref_sty(cx: ctxt, sty: &sty, expl: bool) -> Option<mt> {
|
||||
|
||||
fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
|
||||
match *sty {
|
||||
ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
|
||||
Some(mt)
|
||||
}
|
||||
|
||||
ty_ptr(mt) if expl => {
|
||||
ty_ptr(mt) if explicit => {
|
||||
Some(mt)
|
||||
}
|
||||
|
||||
|
@ -3443,7 +3444,7 @@ fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
|
|||
id))
|
||||
}
|
||||
} else {
|
||||
csearch::get_provided_trait_methods(cx, id).map(|info| info.ty.ident)
|
||||
csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ fn check_fn(ccx: @crate_ctxt,
|
|||
} else { None };
|
||||
|
||||
@fn_ctxt {
|
||||
self_impl_def_id: self_info.map(|info| info.def_id),
|
||||
self_impl_def_id: self_info.map(|self_info| self_info.def_id),
|
||||
ret_ty: ret_ty,
|
||||
indirect_ret_ty: indirect_ret_ty,
|
||||
purity: purity,
|
||||
|
@ -280,16 +280,16 @@ fn check_fn(ccx: @crate_ctxt,
|
|||
|
||||
// Update the self_info to contain an accurate self type (taking
|
||||
// into account explicit self).
|
||||
let self_info = do self_info.chain_ref |info| {
|
||||
let self_info = do self_info.chain_ref |self_info| {
|
||||
// If the self type is sty_static, we don't have a self ty.
|
||||
if info.explicit_self.node == ast::sty_static {
|
||||
if self_info.explicit_self.node == ast::sty_static {
|
||||
None
|
||||
} else {
|
||||
let self_region = fcx.in_scope_regions.find(ty::br_self);
|
||||
let ty = method::transform_self_type_for_method(
|
||||
fcx.tcx(), self_region,
|
||||
info.self_ty, info.explicit_self.node);
|
||||
Some({self_ty: ty,.. *info})
|
||||
self_info.self_ty, self_info.explicit_self.node);
|
||||
Some({self_ty: ty,.. *self_info})
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -306,8 +306,8 @@ fn check_fn(ccx: @crate_ctxt,
|
|||
None => ()
|
||||
}
|
||||
|
||||
for self_info.each |info| {
|
||||
fcx.write_ty(info.self_id, info.self_ty);
|
||||
for self_info.each |self_info| {
|
||||
fcx.write_ty(self_info.self_id, self_info.self_ty);
|
||||
}
|
||||
for vec::each2(decl.inputs, arg_tys) |input, arg| {
|
||||
fcx.write_ty(input.id, *arg);
|
||||
|
@ -344,19 +344,31 @@ fn check_fn(ccx: @crate_ctxt,
|
|||
};
|
||||
|
||||
// Add the self parameter
|
||||
for self_info.each |info| {
|
||||
assign(info.explicit_self.span,
|
||||
info.self_id, Some(info.self_ty));
|
||||
for self_info.each |self_info| {
|
||||
assign(self_info.explicit_self.span,
|
||||
self_info.self_id,
|
||||
Some(self_info.self_ty));
|
||||
debug!("self is assigned to %s",
|
||||
fcx.inh.locals.get(info.self_id).to_str());
|
||||
fcx.inh.locals.get(self_info.self_id).to_str());
|
||||
}
|
||||
|
||||
// Add formal parameters.
|
||||
for vec::each2(arg_tys, decl.inputs) |arg_ty, input| {
|
||||
assign(input.ty.span, input.id, Some(*arg_ty));
|
||||
debug!("Argument %s is assigned to %s",
|
||||
tcx.sess.str_of(input.ident),
|
||||
fcx.inh.locals.get(input.id).to_str());
|
||||
// Create type variables for each argument.
|
||||
do pat_util::pat_bindings(tcx.def_map, input.pat)
|
||||
|_bm, pat_id, _sp, _path| {
|
||||
assign(input.ty.span, pat_id, None);
|
||||
}
|
||||
|
||||
// Check the pattern.
|
||||
let region = fcx.block_region();
|
||||
let pcx = {
|
||||
fcx: fcx,
|
||||
map: pat_id_map(tcx.def_map, input.pat),
|
||||
alt_region: region,
|
||||
block_region: region,
|
||||
};
|
||||
alt::check_pat(pcx, input.pat, *arg_ty);
|
||||
}
|
||||
|
||||
// Add explicitly-declared locals.
|
||||
|
|
|
@ -428,6 +428,9 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
|||
demand::eqtype(fcx, pat.span, ct, typ);
|
||||
}
|
||||
fcx.write_ty(pat.id, typ);
|
||||
|
||||
debug!("(checking alt) writing type for pat id %d", pat.id);
|
||||
|
||||
match sub {
|
||||
Some(p) => check_pat(pcx, p, expected),
|
||||
_ => ()
|
||||
|
|
|
@ -234,7 +234,10 @@ fn resolve_type_vars_in_fn(fcx: @fn_ctxt,
|
|||
self_info.self_id);
|
||||
}
|
||||
for decl.inputs.each |arg| {
|
||||
resolve_type_vars_for_node(wbcx, arg.ty.span, arg.id);
|
||||
do pat_util::pat_bindings(fcx.tcx().def_map, arg.pat)
|
||||
|_bm, pat_id, span, _path| {
|
||||
resolve_type_vars_for_node(wbcx, span, pat_id);
|
||||
}
|
||||
}
|
||||
return wbcx.success;
|
||||
}
|
||||
|
|
|
@ -856,8 +856,8 @@ impl CoherenceChecker {
|
|||
|
||||
debug!("(adding default methods for trait) processing trait");
|
||||
|
||||
for csearch::get_provided_trait_methods(tcx,
|
||||
trait_def_id).each |info| {
|
||||
for csearch::get_provided_trait_methods(tcx, trait_def_id).each
|
||||
|trait_method_info| {
|
||||
debug!("(adding default methods for trait) found default method");
|
||||
|
||||
// Create a new def ID for this provided method.
|
||||
|
@ -868,11 +868,11 @@ impl CoherenceChecker {
|
|||
@ProvidedMethodInfo {
|
||||
method_info: @{
|
||||
did: new_did,
|
||||
n_tps: info.ty.tps.len(),
|
||||
ident: info.ty.ident,
|
||||
self_type: info.ty.self_ty
|
||||
n_tps: trait_method_info.ty.tps.len(),
|
||||
ident: trait_method_info.ty.ident,
|
||||
self_type: trait_method_info.ty.self_ty
|
||||
},
|
||||
trait_method_def_id: info.def_id
|
||||
trait_method_def_id: trait_method_info.def_id
|
||||
};
|
||||
|
||||
let method_infos = @DVec();
|
||||
|
|
|
@ -662,8 +662,8 @@ type expr = {id: node_id, callee_id: node_id, node: expr_, span: span};
|
|||
|
||||
#[auto_serialize]
|
||||
#[auto_deserialize]
|
||||
enum log_level { error, debug, other }
|
||||
// 0 = error, 1 = debug, 2 = other
|
||||
enum log_level { error, debug, log_other }
|
||||
// 0 = error, 1 = debug, 2 = log_other
|
||||
|
||||
#[auto_serialize]
|
||||
#[auto_deserialize]
|
||||
|
@ -1137,7 +1137,7 @@ impl Ty : to_bytes::IterBytes {
|
|||
|
||||
#[auto_serialize]
|
||||
#[auto_deserialize]
|
||||
type arg = {mode: mode, ty: @Ty, ident: ident, id: node_id};
|
||||
type arg = {mode: mode, ty: @Ty, pat: @pat, id: node_id};
|
||||
|
||||
#[auto_serialize]
|
||||
#[auto_deserialize]
|
||||
|
|
|
@ -274,6 +274,12 @@ fn ident_to_path(s: span, +i: ident) -> @path {
|
|||
rp: None, types: ~[]}
|
||||
}
|
||||
|
||||
fn ident_to_pat(id: node_id, s: span, +i: ident) -> @pat {
|
||||
@{id: id,
|
||||
node: pat_ident(bind_by_value, ident_to_path(s, i), None),
|
||||
span: s}
|
||||
}
|
||||
|
||||
pure fn is_unguarded(a: &arm) -> bool {
|
||||
match a.guard {
|
||||
None => true,
|
||||
|
|
|
@ -515,7 +515,12 @@ fn mk_ser_method(
|
|||
let ser_inputs = ~[{
|
||||
mode: ast::infer(cx.next_id()),
|
||||
ty: ty_s,
|
||||
ident: cx.ident_of(~"__s"),
|
||||
pat: @{id: cx.next_id(),
|
||||
node: ast::pat_ident(
|
||||
ast::bind_by_value,
|
||||
ast_util::ident_to_path(span, cx.ident_of(~"__s")),
|
||||
None),
|
||||
span: span},
|
||||
id: cx.next_id(),
|
||||
}];
|
||||
|
||||
|
@ -570,7 +575,12 @@ fn mk_deser_method(
|
|||
let deser_inputs = ~[{
|
||||
mode: ast::infer(cx.next_id()),
|
||||
ty: ty_d,
|
||||
ident: cx.ident_of(~"__d"),
|
||||
pat: @{id: cx.next_id(),
|
||||
node: ast::pat_ident(
|
||||
ast::bind_by_value,
|
||||
ast_util::ident_to_path(span, cx.ident_of(~"__d")),
|
||||
None),
|
||||
span: span},
|
||||
id: cx.next_id(),
|
||||
}];
|
||||
|
||||
|
@ -1087,7 +1097,13 @@ fn mk_enum_deser_body(
|
|||
node: ast::ty_infer,
|
||||
span: span
|
||||
},
|
||||
ident: cx.ident_of(~"i"),
|
||||
pat: @{id: cx.next_id(),
|
||||
node: ast::pat_ident(
|
||||
ast::bind_by_value,
|
||||
ast_util::ident_to_path(span,
|
||||
cx.ident_of(~"i")),
|
||||
None),
|
||||
span: span},
|
||||
id: cx.next_id(),
|
||||
}],
|
||||
output: @{
|
||||
|
|
|
@ -234,24 +234,27 @@ fn mk_ctxt(parse_sess: parse::parse_sess,
|
|||
move ((move imp) as ext_ctxt)
|
||||
}
|
||||
|
||||
fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: ~str) -> ~str {
|
||||
fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, err_msg: ~str) -> ~str {
|
||||
match expr.node {
|
||||
ast::expr_lit(l) => match l.node {
|
||||
ast::lit_str(s) => return *s,
|
||||
_ => cx.span_fatal(l.span, error)
|
||||
_ => cx.span_fatal(l.span, err_msg)
|
||||
},
|
||||
_ => cx.span_fatal(expr.span, error)
|
||||
_ => cx.span_fatal(expr.span, err_msg)
|
||||
}
|
||||
}
|
||||
|
||||
fn expr_to_ident(cx: ext_ctxt, expr: @ast::expr, error: ~str) -> ast::ident {
|
||||
fn expr_to_ident(cx: ext_ctxt,
|
||||
expr: @ast::expr,
|
||||
err_msg: ~str) -> ast::ident {
|
||||
match expr.node {
|
||||
ast::expr_path(p) => {
|
||||
if vec::len(p.types) > 0u || vec::len(p.idents) != 1u {
|
||||
cx.span_fatal(expr.span, error);
|
||||
} else { return p.idents[0]; }
|
||||
cx.span_fatal(expr.span, err_msg);
|
||||
}
|
||||
return p.idents[0];
|
||||
}
|
||||
_ => cx.span_fatal(expr.span, error)
|
||||
_ => cx.span_fatal(expr.span, err_msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// something smarter.
|
||||
|
||||
use ast::{ident, node_id};
|
||||
use ast_util::respan;
|
||||
use ast_util::{ident_to_path, respan};
|
||||
use codemap::span;
|
||||
use ext::base::mk_ctxt;
|
||||
|
||||
|
@ -178,7 +178,12 @@ impl ext_ctxt: ext_ctxt_ast_builder {
|
|||
fn arg(name: ident, ty: @ast::Ty) -> ast::arg {
|
||||
{mode: ast::infer(self.next_id()),
|
||||
ty: ty,
|
||||
ident: name,
|
||||
pat: @{id: self.next_id(),
|
||||
node: ast::pat_ident(
|
||||
ast::bind_by_value,
|
||||
ast_util::ident_to_path(self.empty_span(), name),
|
||||
None),
|
||||
span: self.empty_span()},
|
||||
id: self.next_id()}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,9 +105,9 @@ fn fold_attribute_(at: attribute, fld: ast_fold) ->
|
|||
//used in noop_fold_foreign_item and noop_fold_fn_decl
|
||||
fn fold_arg_(a: arg, fld: ast_fold) -> arg {
|
||||
return {mode: a.mode,
|
||||
ty: fld.fold_ty(a.ty),
|
||||
ident: fld.fold_ident(a.ident),
|
||||
id: fld.new_id(a.id)};
|
||||
ty: fld.fold_ty(a.ty),
|
||||
pat: fld.fold_pat(a.pat),
|
||||
id: fld.new_id(a.id)};
|
||||
}
|
||||
//used in noop_fold_expr, and possibly elsewhere in the future
|
||||
fn fold_mac_(m: mac, fld: ast_fold) -> mac {
|
||||
|
|
|
@ -696,19 +696,21 @@ impl Parser {
|
|||
// identifier names.
|
||||
fn parse_arg_general(require_name: bool) -> arg {
|
||||
let mut m;
|
||||
let i = if require_name || self.is_named_argument() {
|
||||
let pat = if require_name || self.is_named_argument() {
|
||||
m = self.parse_arg_mode();
|
||||
let name = self.parse_value_ident();
|
||||
let pat = self.parse_pat(false);
|
||||
self.expect(token::COLON);
|
||||
name
|
||||
pat
|
||||
} else {
|
||||
m = infer(self.get_id());
|
||||
special_idents::invalid
|
||||
ast_util::ident_to_pat(self.get_id(),
|
||||
copy self.last_span,
|
||||
special_idents::invalid)
|
||||
};
|
||||
|
||||
let t = self.parse_ty(false);
|
||||
|
||||
{mode: m, ty: t, ident: i, id: self.get_id()}
|
||||
{mode: m, ty: t, pat: pat, id: self.get_id()}
|
||||
}
|
||||
|
||||
fn parse_arg() -> arg_or_capture_item {
|
||||
|
@ -722,7 +724,7 @@ impl Parser {
|
|||
fn parse_fn_block_arg() -> arg_or_capture_item {
|
||||
do self.parse_capture_item_or |p| {
|
||||
let m = p.parse_arg_mode();
|
||||
let i = p.parse_value_ident();
|
||||
let pat = p.parse_pat(false);
|
||||
let t = if p.eat(token::COLON) {
|
||||
p.parse_ty(false)
|
||||
} else {
|
||||
|
@ -730,7 +732,7 @@ impl Parser {
|
|||
node: ty_infer,
|
||||
span: mk_sp(p.span.lo, p.span.hi)}
|
||||
};
|
||||
either::Left({mode: m, ty: t, ident: i, id: p.get_id()})
|
||||
either::Left({mode: m, ty: t, pat: pat, id: p.get_id()})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1042,7 +1044,7 @@ impl Parser {
|
|||
let lvl = self.parse_expr();
|
||||
self.expect(token::COMMA);
|
||||
let e = self.parse_expr();
|
||||
ex = expr_log(ast::other, lvl, e);
|
||||
ex = expr_log(ast::log_other, lvl, e);
|
||||
hi = self.span.hi;
|
||||
self.expect(token::RPAREN);
|
||||
} else if self.eat_keyword(~"assert") {
|
||||
|
@ -2708,6 +2710,11 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn ident_to_path(i: ident) -> @path {
|
||||
@{span: self.last_span, global: false, idents: ~[i],
|
||||
rp: None, types: ~[]}
|
||||
}
|
||||
|
||||
fn parse_trait_ref() -> @trait_ref {
|
||||
@{path: self.parse_path_with_tps(false),
|
||||
ref_id: self.get_id(), impl_id: self.get_id()}
|
||||
|
|
|
@ -1386,7 +1386,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
match lvl {
|
||||
ast::debug => { word_nbsp(s, ~"log"); print_expr(s, expr); }
|
||||
ast::error => { word_nbsp(s, ~"log_err"); print_expr(s, expr); }
|
||||
ast::other => {
|
||||
ast::log_other => {
|
||||
word_nbsp(s, ~"log");
|
||||
popen(s);
|
||||
print_expr(s, lexp);
|
||||
|
@ -1820,12 +1820,19 @@ fn print_arg(s: ps, input: ast::arg) {
|
|||
ibox(s, indent_unit);
|
||||
print_arg_mode(s, input.mode);
|
||||
match input.ty.node {
|
||||
ast::ty_infer => print_ident(s, input.ident),
|
||||
ast::ty_infer => print_pat(s, input.pat),
|
||||
_ => {
|
||||
if input.ident != parse::token::special_idents::invalid {
|
||||
print_ident(s, input.ident);
|
||||
word(s.s, ~":");
|
||||
space(s.s);
|
||||
match input.pat.node {
|
||||
ast::pat_ident(_, path, _) if
|
||||
path.idents.len() == 1 &&
|
||||
path.idents[0] == parse::token::special_idents::invalid => {
|
||||
// Do nothing.
|
||||
}
|
||||
_ => {
|
||||
print_pat(s, input.pat);
|
||||
word(s.s, ~":");
|
||||
space(s.s);
|
||||
}
|
||||
}
|
||||
print_type(s, input.ty);
|
||||
}
|
||||
|
|
|
@ -277,7 +277,10 @@ fn visit_ty_params<E>(tps: ~[ty_param], e: E, v: vt<E>) {
|
|||
}
|
||||
|
||||
fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
|
||||
for fd.inputs.each |a| { v.visit_ty(a.ty, e, v); }
|
||||
for fd.inputs.each |a| {
|
||||
v.visit_pat(a.pat, e, v);
|
||||
v.visit_ty(a.ty, e, v);
|
||||
}
|
||||
v.visit_ty(fd.output, e, v);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//error-pattern:is an expr, expected an identifier
|
||||
//error-pattern:is an expr, expected a path
|
||||
fn main() {
|
||||
#macro[[#mylambda[x, body],
|
||||
{
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
pure fn call_first((x, _y): (&fn(), &fn())) {
|
||||
x(); //~ ERROR access to impure function prohibited in pure context
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
5
src/test/compile-fail/refutable-pattern-in-fn-arg.rs
Normal file
5
src/test/compile-fail/refutable-pattern-in-fn-arg.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
let f = |3: int| io::println("hello"); //~ ERROR refutable pattern
|
||||
f(4);
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ mod argparse {
|
|||
fn set_desc(self, s: &str) -> Flag {
|
||||
Flag { //~ ERROR cannot infer an appropriate lifetime
|
||||
name: self.name,
|
||||
desc: s, //~ ERROR cannot infer an appropriate lifetime
|
||||
desc: s,
|
||||
max_count: self.max_count,
|
||||
value: self.value
|
||||
}
|
||||
|
|
12
src/test/run-pass/pattern-in-closure.rs
Normal file
12
src/test/run-pass/pattern-in-closure.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
struct Foo {
|
||||
x: int,
|
||||
y: int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let f = |(x, _): (int, int)| io::println((x + 1).to_str());
|
||||
let g = |Foo { x: x, y: y }: Foo| io::println((x + 1).to_str());
|
||||
f((2, 3));
|
||||
g(Foo { x: 1, y: 2 });
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue