Require alts to be exhaustive
middle::check_alt does the work. Lots of changes to add default cases into alts that were previously inexhaustive.
This commit is contained in:
parent
813a55d891
commit
fba35e1a3c
50 changed files with 766 additions and 367 deletions
|
|
@ -93,6 +93,7 @@ fn load_link(mis: [@ast::meta_item]) -> (option::t<str>,
|
|||
_ { }
|
||||
}
|
||||
}
|
||||
_ { fail "load_link: meta items must be name-values"; }
|
||||
}
|
||||
}
|
||||
(name, vers, uuid)
|
||||
|
|
@ -135,6 +136,7 @@ fn load_pkg(filename: str) -> option::t<pkg> {
|
|||
uuid = u;
|
||||
}
|
||||
}
|
||||
_ { fail "load_pkg: pkg attributes may not contain meta_words"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ import util::filesearch;
|
|||
|
||||
export get_rpath_flags;
|
||||
|
||||
pure fn not_win32(os: session::os) -> bool {
|
||||
alt os {
|
||||
session::os_win32 { false }
|
||||
_ { true }
|
||||
}
|
||||
}
|
||||
|
||||
fn get_rpath_flags(sess: session::session, out_filename: str) -> [str] {
|
||||
let os = sess.targ_cfg.os;
|
||||
|
||||
|
|
@ -99,12 +106,13 @@ fn get_rpaths_relative_to_output(os: session::os,
|
|||
fn get_rpath_relative_to_output(os: session::os,
|
||||
cwd: fs::path,
|
||||
output: fs::path,
|
||||
&&lib: fs::path) -> str {
|
||||
&&lib: fs::path) : not_win32(os) -> str {
|
||||
// Mac doesn't appear to support $ORIGIN
|
||||
let prefix = alt os {
|
||||
session::os_linux { "$ORIGIN" + fs::path_sep() }
|
||||
session::os_freebsd { "$ORIGIN" + fs::path_sep() }
|
||||
session::os_macos { "@executable_path" + fs::path_sep() }
|
||||
session::os_win32 { std::util::unreachable(); }
|
||||
};
|
||||
|
||||
prefix + get_relative_to(
|
||||
|
|
@ -309,24 +317,31 @@ mod test {
|
|||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_rpath_relative() {
|
||||
let res = get_rpath_relative_to_output(session::os_linux,
|
||||
let o = session::os_linux;
|
||||
check not_win32(o);
|
||||
let res = get_rpath_relative_to_output(o,
|
||||
"/usr", "bin/rustc", "lib/libstd.so");
|
||||
assert res == "$ORIGIN/../lib";
|
||||
assert res == "$ORIGIN/../lib";
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn test_rpath_relative() {
|
||||
let res = get_rpath_relative_to_output(session::os_freebsd,
|
||||
let o = session::os_freebsd;
|
||||
check not_win32(o);
|
||||
let res = get_rpath_relative_to_output(o,
|
||||
"/usr", "bin/rustc", "lib/libstd.so");
|
||||
assert res == "$ORIGIN/../lib";
|
||||
assert res == "$ORIGIN/../lib";
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn test_rpath_relative() {
|
||||
let res = get_rpath_relative_to_output(session::os_macos,
|
||||
"/usr", "bin/rustc", "lib/libstd.so");
|
||||
// this is why refinements would be nice
|
||||
let o = session::os_macos;
|
||||
check not_win32(o);
|
||||
let res = get_rpath_relative_to_output(o, "/usr", "bin/rustc",
|
||||
"lib/libstd.so");
|
||||
assert res == "@executable_path/../lib";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -608,6 +608,8 @@ mod test {
|
|||
let match =
|
||||
alt getopts::getopts(["--test"], opts()) {
|
||||
ok(m) { m }
|
||||
err(f) { fail "test_switch_implies_cfg_test: " +
|
||||
getopts::fail_str(f); }
|
||||
};
|
||||
let sessopts = build_session_options(match, diagnostic::emit);
|
||||
let sess = build_session(sessopts, "", diagnostic::emit);
|
||||
|
|
@ -622,6 +624,8 @@ mod test {
|
|||
let match =
|
||||
alt getopts::getopts(["--test", "--cfg=test"], opts()) {
|
||||
ok(m) { m }
|
||||
err(f) { fail "test_switch_implies_cfg_test_unless_cfg_test: " +
|
||||
getopts::fail_str(f); }
|
||||
};
|
||||
let sessopts = build_session_options(match, diagnostic::emit);
|
||||
let sess = build_session(sessopts, "", diagnostic::emit);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ type session = @{targ_cfg: @config,
|
|||
parse_sess: parse_sess,
|
||||
codemap: codemap::codemap,
|
||||
// For a library crate, this is always none
|
||||
mutable main_fn: option::t<node_id>,
|
||||
mutable main_fn: option::t<(node_id, codemap::span)>,
|
||||
span_diagnostic: diagnostic::span_handler,
|
||||
filesearch: filesearch::filesearch,
|
||||
mutable building_library: bool,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import std::{ebml, map, io};
|
||||
import io::writer_util;
|
||||
import syntax::{ast, ast_util};
|
||||
import driver::session::session;
|
||||
import front::attr;
|
||||
import middle::ty;
|
||||
import common::*;
|
||||
|
|
@ -302,7 +303,9 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
|
|||
let bounds = item_ty_param_bounds(mth, tcx, cdata);
|
||||
let name = item_name(mth);
|
||||
let ty = doc_type(mth, tcx, cdata);
|
||||
let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f } };
|
||||
let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f }
|
||||
_ { tcx.sess.bug("get_iface_methods: id has non-function type");
|
||||
} };
|
||||
result += [{ident: name, tps: bounds, fty: fty}];
|
||||
}
|
||||
@result
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import middle::trans::common::crate_ctxt;
|
|||
import middle::ty;
|
||||
import middle::ty::node_id_to_type;
|
||||
import front::attr;
|
||||
import driver::session::session;
|
||||
|
||||
export encode_metadata;
|
||||
export encoded_ty;
|
||||
|
|
@ -275,6 +276,8 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
|
|||
}
|
||||
}
|
||||
}
|
||||
_ { ecx.ccx.tcx.sess.bug("encode_info_for_mod: \
|
||||
undocumented invariant"); }
|
||||
}
|
||||
ebml::end_tag(ebml_w);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import io::writer_util;
|
|||
import std::map::hashmap;
|
||||
import option::{some, none};
|
||||
import syntax::ast::*;
|
||||
import driver::session::session;
|
||||
import middle::ty;
|
||||
import syntax::print::pprust::*;
|
||||
|
||||
|
|
@ -213,6 +214,10 @@ fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
|
|||
by_copy { w.write_char('+'); }
|
||||
by_ref { w.write_char('='); }
|
||||
by_val { w.write_char('#'); }
|
||||
// tediously, this has to be there until there's a way
|
||||
// to constraint post-typeck types not to contain a mode_infer
|
||||
mode_infer { cx.tcx.sess.bug("enc_ty_fn: shouldn't see \
|
||||
mode_infer"); }
|
||||
}
|
||||
enc_ty(w, cx, arg.ty);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import syntax::visit;
|
|||
import visit::vt;
|
||||
import core::{vec, option};
|
||||
import std::list;
|
||||
import std::util::unreachable;
|
||||
import option::{some, none, is_none};
|
||||
import list::list;
|
||||
import driver::session::session;
|
||||
import pat_util::*;
|
||||
import util::ppaux::ty_to_str;
|
||||
|
||||
// This is not an alias-analyser (though it would merit from becoming one, or
|
||||
// getting input from one, to be more precise). It is a pass that checks
|
||||
|
|
@ -575,6 +577,11 @@ fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool {
|
|||
for f in fs { sum += score_ty(tcx, f.mt.ty); }
|
||||
sum
|
||||
}
|
||||
_ {
|
||||
tcx.sess.warn(#fmt("score_ty: unexpected type %s",
|
||||
ty_to_str(tcx, ty)));
|
||||
1u // ???
|
||||
}
|
||||
};
|
||||
}
|
||||
ret score_ty(tcx, ty) > 8u;
|
||||
|
|
@ -611,6 +618,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
|
|||
let ty = ty::node_id_to_type(tcx, pat.id);
|
||||
let m = alt ty::struct(tcx, ty) {
|
||||
ty::ty_box(mt) { mt.mut != ast::imm }
|
||||
_ { tcx.sess.span_bug(pat.span, "box pat has non-box type"); }
|
||||
},
|
||||
c = if m {some(contains(ty)) } else { mut };
|
||||
walk(tcx, c, p, set);
|
||||
|
|
@ -619,6 +627,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
|
|||
let ty = ty::node_id_to_type(tcx, pat.id);
|
||||
let m = alt ty::struct(tcx, ty) {
|
||||
ty::ty_uniq(mt) { mt.mut != ast::imm }
|
||||
_ { tcx.sess.span_bug(pat.span, "uniq pat has non-uniq type"); }
|
||||
},
|
||||
c = if m { some(contains(ty)) } else { mut };
|
||||
walk(tcx, c, p, set);
|
||||
|
|
@ -672,6 +681,10 @@ fn append_invalid(dest: list<@invalid>, src: list<@invalid>,
|
|||
}
|
||||
cur = *tail;
|
||||
}
|
||||
list::nil {
|
||||
fail "append_invalid: stop doesn't appear to be \
|
||||
a postfix of src";
|
||||
}
|
||||
}
|
||||
}
|
||||
ret dest;
|
||||
|
|
@ -686,6 +699,10 @@ fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> {
|
|||
if !is_none(p) { out = list::cons(head, @out); }
|
||||
cur = *tail;
|
||||
}
|
||||
list::nil {
|
||||
// typestate would help...
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
ret out;
|
||||
|
|
|
|||
|
|
@ -44,15 +44,15 @@ fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk,
|
|||
}
|
||||
|
||||
fn map_local(cx: ctx, loc: @local) {
|
||||
pat_util::pat_bindings(loc.node.pat) {|p|
|
||||
cx.map.insert(p.id, node_local(cx.local_id));
|
||||
pat_util::pat_bindings(loc.node.pat) {|p_id, _s, _p|
|
||||
cx.map.insert(p_id, node_local(cx.local_id));
|
||||
cx.local_id += 1u;
|
||||
};
|
||||
}
|
||||
|
||||
fn map_arm(cx: ctx, arm: arm) {
|
||||
pat_util::pat_bindings(arm.pats[0]) {|p|
|
||||
cx.map.insert(p.id, node_local(cx.local_id));
|
||||
pat_util::pat_bindings(arm.pats[0]) {|p_id, _s, _p|
|
||||
cx.map.insert(p_id, node_local(cx.local_id));
|
||||
cx.local_id += 1u;
|
||||
};
|
||||
}
|
||||
|
|
@ -79,50 +79,6 @@ fn map_expr(cx: ctx, ex: @expr) {
|
|||
cx.map.insert(ex.id, node_expr(ex));
|
||||
}
|
||||
|
||||
fn node_span(node: ast_node) -> codemap::span {
|
||||
alt node {
|
||||
node_item(item) { item.span }
|
||||
node_native_item(nitem) { nitem.span }
|
||||
node_expr(expr) { expr.span }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
import syntax::ast_util;
|
||||
|
||||
#[test]
|
||||
fn test_node_span_item() {
|
||||
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
||||
let node =
|
||||
node_item(@{ident: "test",
|
||||
attrs: [],
|
||||
id: 0,
|
||||
node: item_mod({view_items: [], items: []}),
|
||||
span: expected});
|
||||
assert (node_span(node) == expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_span_native_item() {
|
||||
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
||||
let node =
|
||||
node_native_item(@{ident: "test",
|
||||
attrs: [],
|
||||
node: native_item_ty,
|
||||
id: 0,
|
||||
span: expected});
|
||||
assert (node_span(node) == expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_span_expr() {
|
||||
let expected: codemap::span = ast_util::mk_sp(20u, 30u);
|
||||
let node = node_expr(@{id: 0, node: expr_break, span: expected});
|
||||
assert (node_span(node) == expected);
|
||||
}
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
|
||||
import syntax::ast::*;
|
||||
import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
|
||||
lit_expr_eq};
|
||||
lit_expr_eq, unguarded_pat};
|
||||
import syntax::codemap::span;
|
||||
import pat_util::*;
|
||||
import syntax::visit;
|
||||
import option::{some, none};
|
||||
import driver::session::session;
|
||||
import middle::ty;
|
||||
import middle::ty::*;
|
||||
|
||||
fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
||||
let v =
|
||||
|
|
@ -18,15 +22,20 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
|||
fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
|
||||
visit::visit_expr(ex, s, v);
|
||||
alt ex.node {
|
||||
expr_alt(_, arms) {
|
||||
check_arms(tcx, pat_util::normalize_arms(tcx, arms));
|
||||
expr_alt(scrut, arms) {
|
||||
check_arms(tcx, ex.span, scrut,
|
||||
pat_util::normalize_arms(tcx, arms));
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
|
||||
fn check_arms(tcx: ty::ctxt, arms: [arm]) {
|
||||
fn check_arms(tcx: ty::ctxt, sp:span, scrut: @expr, arms: [arm]) {
|
||||
let i = 0;
|
||||
let scrut_ty = expr_ty(tcx, scrut);
|
||||
/* (Could both checks be done in a single pass?) */
|
||||
|
||||
/* Check for unreachable patterns */
|
||||
for arm: arm in arms {
|
||||
for arm_pat: @pat in arm.pats {
|
||||
let reachable = true;
|
||||
|
|
@ -47,6 +56,97 @@ fn check_arms(tcx: ty::ctxt, arms: [arm]) {
|
|||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
/* Check for exhaustiveness */
|
||||
|
||||
check_exhaustive(tcx, sp, scrut_ty,
|
||||
vec::concat(vec::filter_map(arms, unguarded_pat)));
|
||||
}
|
||||
|
||||
// Precondition: patterns have been normalized
|
||||
// (not checked statically yet)
|
||||
fn check_exhaustive(tcx: ty::ctxt, sp:span, scrut_ty:ty::t, pats:[@pat]) {
|
||||
let represented : [def_id] = [];
|
||||
/* Determine the type of the scrutinee */
|
||||
/* If it's not an enum, exit (bailing out on checking non-enum alts
|
||||
for now) */
|
||||
/* Otherwise, get the list of variants and make sure each one is
|
||||
represented. Then recurse on the columns. */
|
||||
|
||||
let ty_def_id = alt ty::struct(tcx, scrut_ty) {
|
||||
ty_enum(id, _) { id }
|
||||
_ { ret; } };
|
||||
|
||||
let variants = *enum_variants(tcx, ty_def_id);
|
||||
for pat in pats {
|
||||
if !is_refutable(tcx, pat) {
|
||||
/* automatically makes this alt complete */ ret;
|
||||
}
|
||||
alt pat.node {
|
||||
// want the def_id for the constructor
|
||||
pat_enum(id,_) {
|
||||
alt tcx.def_map.find(pat.id) {
|
||||
some(def_variant(_, variant_def_id)) {
|
||||
represented += [variant_def_id];
|
||||
}
|
||||
_ { tcx.sess.span_bug(pat.span, "check_exhaustive:
|
||||
pat_tag not bound to a variant"); }
|
||||
}
|
||||
}
|
||||
_ { tcx.sess.span_bug(pat.span, "check_exhaustive: ill-typed \
|
||||
pattern"); // we know this has enum type,
|
||||
} // so anything else should be impossible
|
||||
}
|
||||
}
|
||||
fn not_represented(v: [def_id], &&vinfo: variant_info) -> bool {
|
||||
!vec::member(vinfo.id, v)
|
||||
}
|
||||
// Could be more efficient (bitvectors?)
|
||||
alt vec::find(variants, bind not_represented(represented,_)) {
|
||||
some(bad) {
|
||||
// complain
|
||||
// TODO: give examples of cases that aren't covered
|
||||
tcx.sess.note("Patterns not covered include:");
|
||||
tcx.sess.note(bad.name);
|
||||
tcx.sess.span_err(sp, "Non-exhaustive pattern");
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
// Otherwise, check subpatterns
|
||||
// inefficient
|
||||
for variant in variants {
|
||||
// rows consists of the argument list for each pat that's an enum
|
||||
let rows : [[@pat]] = [];
|
||||
for pat in pats {
|
||||
alt pat.node {
|
||||
pat_enum(id, args) {
|
||||
alt tcx.def_map.find(pat.id) {
|
||||
some(def_variant(_,variant_id))
|
||||
if variant_id == variant.id { rows += [args]; }
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
if check vec::is_not_empty(rows) {
|
||||
let i = 0u;
|
||||
for it in rows[0] {
|
||||
let column = [it];
|
||||
// Annoying -- see comment in
|
||||
// tstate::states::find_pre_post_state_loop
|
||||
check vec::is_not_empty(rows);
|
||||
for row in vec::tail(rows) {
|
||||
column += [row[i]];
|
||||
}
|
||||
check_exhaustive(tcx, sp, pat_ty(tcx, it), column);
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
// This shouldn't actually happen, since there were no
|
||||
// irrefutable patterns if we got here.
|
||||
else { cont; }
|
||||
}
|
||||
}
|
||||
|
||||
fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
|
||||
|
|
@ -145,8 +245,8 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
|||
pat_wild | pat_ident(_, none) { false }
|
||||
pat_lit(_) { true }
|
||||
pat_rec(fields, _) {
|
||||
for field: field_pat in fields {
|
||||
if is_refutable(tcx, field.pat) { ret true; }
|
||||
for it: field_pat in fields {
|
||||
if is_refutable(tcx, it.pat) { ret true; }
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
@ -156,10 +256,11 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
|||
}
|
||||
pat_enum(_, args) {
|
||||
let vdef = variant_def_ids(tcx.def_map.get(pat.id));
|
||||
if vec::len(*ty::enum_variants(tcx, vdef.tg)) != 1u { ret true; }
|
||||
if vec::len(*ty::enum_variants(tcx, vdef.enm)) != 1u { ret true; }
|
||||
for p: @pat in args { if is_refutable(tcx, p) { ret true; } }
|
||||
false
|
||||
}
|
||||
pat_range(_, _) { true }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import codemap::span;
|
|||
import ast::ty;
|
||||
import pat_util::*;
|
||||
import util::ppaux::ty_to_str;
|
||||
import driver::session::session;
|
||||
|
||||
export create_local_var;
|
||||
export create_function;
|
||||
|
|
@ -249,8 +250,8 @@ fn create_block(cx: @block_ctxt) -> @metadata<block_md> {
|
|||
}*/
|
||||
|
||||
let parent = alt cx.parent {
|
||||
parent_none { create_function(cx.fcx).node }
|
||||
parent_some(bcx) { create_block(bcx).node }
|
||||
parent_none { create_function(cx.fcx).node }
|
||||
parent_some(bcx) { create_block(bcx).node }
|
||||
};
|
||||
let file_node = create_file(bcx_ccx(cx), fname);
|
||||
let unique_id = alt cache.find(LexicalBlockTag) {
|
||||
|
|
@ -306,6 +307,8 @@ fn create_basic_type(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
ast::ty_f32 {("f32", size_and_align_of::<f32>(), DW_ATE_float)}
|
||||
ast::ty_f64 {("f64", size_and_align_of::<f64>(), DW_ATE_float)}
|
||||
}}
|
||||
_ { cx.tcx.sess.span_bug(ty.span,
|
||||
"create_basic_type: unhandled type"); }
|
||||
};
|
||||
|
||||
let fname = filename_from_span(cx, ty.span);
|
||||
|
|
@ -481,15 +484,15 @@ fn create_composite_type(type_tag: int, name: str, file: ValueRef, line: int,
|
|||
ret llmdnode(lldata);
|
||||
}
|
||||
|
||||
fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, vec_ty: @ast::ty)
|
||||
fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t,
|
||||
vec_ty_span: codemap::span, elem_ty: @ast::ty)
|
||||
-> @metadata<tydesc_md> {
|
||||
let fname = filename_from_span(cx, vec_ty.span);
|
||||
let fname = filename_from_span(cx, vec_ty_span);
|
||||
let file_node = create_file(cx, fname);
|
||||
let elem_ty = alt vec_ty.node { ast::ty_vec(mt) { mt.ty } };
|
||||
let elem_ty_md = create_ty(cx, elem_t, elem_ty);
|
||||
let tcx = ccx_tcx(cx);
|
||||
let scx = create_structure(file_node, ty_to_str(tcx, vec_t), 0);
|
||||
let uint_ty = @{node: ast::ty_uint(ast::ty_u), span: vec_ty.span};
|
||||
let uint_ty = @{node: ast::ty_uint(ast::ty_u), span: vec_ty_span};
|
||||
let size_t_type = create_basic_type(cx, ty::mk_uint(tcx), uint_ty);
|
||||
add_member(scx, "fill", 0, sys::size_of::<ctypes::size_t>() as int,
|
||||
sys::align_of::<ctypes::size_t>() as int, size_t_type.node);
|
||||
|
|
@ -516,12 +519,14 @@ fn member_size_and_align(ty: @ast::ty) -> (int, int) {
|
|||
ast::ty_i8 { size_and_align_of::<i8>() }
|
||||
ast::ty_i16 { size_and_align_of::<i16>() }
|
||||
ast::ty_i32 { size_and_align_of::<i32>() }
|
||||
ast::ty_i64 { size_and_align_of::<i64>() }
|
||||
}}
|
||||
ast::ty_uint(m) { alt m {
|
||||
ast::ty_u { size_and_align_of::<uint>() }
|
||||
ast::ty_u8 { size_and_align_of::<i8>() }
|
||||
ast::ty_u16 { size_and_align_of::<u16>() }
|
||||
ast::ty_u32 { size_and_align_of::<u32>() }
|
||||
ast::ty_u64 { size_and_align_of::<u64>() }
|
||||
}}
|
||||
ast::ty_float(m) { alt m {
|
||||
ast::ty_f { size_and_align_of::<float>() }
|
||||
|
|
@ -542,6 +547,7 @@ fn member_size_and_align(ty: @ast::ty) -> (int, int) {
|
|||
ast::ty_vec(_) {
|
||||
size_and_align_of::<ctypes::uintptr_t>()
|
||||
}
|
||||
_ { fail "member_size_and_align: can't handle this type"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -578,6 +584,9 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
}
|
||||
ty::ty_vec(mt) { ast::ty_vec({ty: t_to_ty(cx, mt.ty, span),
|
||||
mut: mt.mut}) }
|
||||
_ {
|
||||
cx.tcx.sess.span_bug(span, "t_to_ty: Can't handle this type");
|
||||
}
|
||||
};
|
||||
ret @{node: ty, span: span};
|
||||
}
|
||||
|
|
@ -586,6 +595,7 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
ast::ty_box(mt) {
|
||||
let inner_t = alt ty::struct(ccx_tcx(cx), t) {
|
||||
ty::ty_box(boxed) { boxed.ty }
|
||||
_ { cx.tcx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
|
||||
};
|
||||
let md = create_ty(cx, inner_t, mt.ty);
|
||||
let box = create_boxed_type(cx, t, inner_t, ty.span, md);
|
||||
|
|
@ -595,6 +605,8 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
ast::ty_uniq(mt) {
|
||||
let inner_t = alt ty::struct(ccx_tcx(cx), t) {
|
||||
ty::ty_uniq(boxed) { boxed.ty }
|
||||
// Hoping we'll have a way to eliminate this check soon.
|
||||
_ { cx.tcx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
|
||||
};
|
||||
let md = create_ty(cx, inner_t, mt.ty);
|
||||
ret create_pointer_type(cx, t, ty.span, md);
|
||||
|
|
@ -611,7 +623,8 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
|
|||
|
||||
ast::ty_vec(mt) {
|
||||
let inner_t = ty::sequence_element_type(ccx_tcx(cx), t);
|
||||
let v = create_vec(cx, t, inner_t, ty);
|
||||
let inner_ast_t = t_to_ty(cx, inner_t, mt.ty.span);
|
||||
let v = create_vec(cx, t, inner_t, ty.span, inner_ast_t);
|
||||
ret create_pointer_type(cx, t, ty.span, v);
|
||||
}
|
||||
|
||||
|
|
@ -650,15 +663,17 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
|
|||
let name = path_to_ident(alt pat_util::normalize_pat(bcx_tcx(bcx),
|
||||
local.node.pat).node {
|
||||
ast::pat_ident(ident, _) { ident /*XXX deal w/ optional node binding*/ }
|
||||
});
|
||||
_ { bcx_tcx(bcx).sess.span_bug(local.span, "create_local_var: \
|
||||
weird pattern in local"); }
|
||||
});
|
||||
let loc = codemap::lookup_char_pos(cx.sess.codemap,
|
||||
local.span.lo);
|
||||
let ty = base::node_id_type(cx, local.node.id);
|
||||
let tymd = create_ty(cx, ty, local.node.ty);
|
||||
let filemd = create_file(cx, loc.filename);
|
||||
let context = alt bcx.parent {
|
||||
parent_none { create_function(bcx.fcx).node }
|
||||
parent_some(_) { create_block(bcx).node }
|
||||
parent_none { create_function(bcx.fcx).node }
|
||||
parent_some(_) { create_block(bcx).node }
|
||||
};
|
||||
let mdnode = create_var(tg, context, name, filemd.node,
|
||||
loc.line as int, tymd.node);
|
||||
|
|
@ -667,9 +682,15 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
|
|||
|
||||
let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
|
||||
option::some(local_mem(v)) { v }
|
||||
option::some(_) {
|
||||
bcx_tcx(bcx).sess.span_bug(local.span, "local is bound to \
|
||||
something weird");
|
||||
}
|
||||
option::none {
|
||||
alt bcx.fcx.lllocals.get(local.node.pat.id) {
|
||||
local_imm(v) { v }
|
||||
_ { bcx_tcx(bcx).sess.span_bug(local.span, "local is bound to \
|
||||
something weird"); }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -745,15 +766,21 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
|
|||
ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _) {
|
||||
(item.ident, decl.output, item.id)
|
||||
}
|
||||
_ { fcx_tcx(fcx).sess.span_bug(item.span, "create_function: item \
|
||||
bound to non-function"); }
|
||||
}
|
||||
}
|
||||
ast_map::node_method(method) {
|
||||
(method.ident, method.decl.output, method.id)
|
||||
}
|
||||
ast_map::node_res_ctor(item) {
|
||||
alt item.node { ast::item_res(decl, _, _, _, ctor_id) {
|
||||
(item.ident, decl.output, ctor_id)
|
||||
}}
|
||||
alt item.node {
|
||||
ast::item_res(decl, _, _, _, ctor_id) {
|
||||
(item.ident, decl.output, ctor_id)
|
||||
}
|
||||
_ { fcx_tcx(fcx).sess.span_bug(item.span, "create_function: \
|
||||
expected an item_res here"); }
|
||||
}
|
||||
}
|
||||
ast_map::node_expr(expr) {
|
||||
alt expr.node {
|
||||
|
|
@ -763,8 +790,12 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
|
|||
ast::expr_fn_block(decl, _) {
|
||||
(dbg_cx.names("fn"), decl.output, expr.id)
|
||||
}
|
||||
_ { fcx_tcx(fcx).sess.span_bug(expr.span, "create_function: \
|
||||
expected an expr_fn or fn_block here"); }
|
||||
}
|
||||
}
|
||||
_ { fcx_tcx(fcx).sess.bug("create_function: unexpected \
|
||||
sort of node"); }
|
||||
};
|
||||
|
||||
log(debug, ident);
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ fn type_is_gc_relevant(cx: ty::ctxt, ty: ty::t) -> bool {
|
|||
alt ty::struct(cx, ty) {
|
||||
ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) |
|
||||
ty::ty_float(_) | ty::ty_uint(_) | ty::ty_str |
|
||||
ty::ty_type | ty::ty_ptr(_) | ty::ty_native(_) {
|
||||
ty::ty_type | ty::ty_send_type | ty::ty_ptr(_) | ty::ty_native(_) {
|
||||
ret false;
|
||||
}
|
||||
ty::ty_rec(fields) {
|
||||
|
|
@ -131,9 +131,19 @@ fn type_is_gc_relevant(cx: ty::ctxt, ty: ty::t) -> bool {
|
|||
ty::ty_constr(sub, _) { ret type_is_gc_relevant(cx, sub); }
|
||||
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_fn(_) |
|
||||
ty::ty_param(_, _) | ty::ty_res(_, _, _) { ret true; }
|
||||
ty::ty_opaque_closure_ptr(_) {
|
||||
ret false; // I guess?
|
||||
}
|
||||
// A precondition to rule out these cases would be nice
|
||||
ty::ty_var(_) {
|
||||
fail "ty_var in type_is_gc_relevant";
|
||||
}
|
||||
ty::ty_iface(_, _) {
|
||||
fail "ty_iface in type_is_gc_relevant";
|
||||
}
|
||||
ty::ty_named(_,_) {
|
||||
fail "ty_named in type_is_gc_relevant";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
|
|||
some(ex) {
|
||||
// All noncopyable fields must be overridden
|
||||
let t = ty::expr_ty(cx.tcx, ex);
|
||||
let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } };
|
||||
let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f }
|
||||
_ { cx.tcx.sess.span_bug(ex.span,
|
||||
"Bad expr type in record"); } };
|
||||
for tf in ty_fields {
|
||||
if !vec::any(fields, {|f| f.node.ident == tf.ident}) &&
|
||||
!ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import syntax::{visit, ast_util};
|
|||
import syntax::ast::*;
|
||||
import syntax::codemap::span;
|
||||
import std::list::{is_not_empty, list, nil, cons, tail};
|
||||
import std::util::unreachable;
|
||||
import core::{vec, option};
|
||||
import std::list;
|
||||
|
||||
|
|
@ -223,6 +224,11 @@ fn add_block_exit(cx: ctx, tp: block_type) -> bool {
|
|||
}
|
||||
cur = *tail;
|
||||
}
|
||||
nil {
|
||||
// typestate can't use the while loop condition --
|
||||
// *sigh*
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
ret false;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ fn merge_opts(attrs: [ast::attribute], cmd_opts: [(option, bool)]) ->
|
|||
ast::meta_word(name) {
|
||||
str_to_option(name)
|
||||
}
|
||||
_ { fail "meta_to_option: meta_list contains a non-meta-word"; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
|
|||
ty::ty_str {
|
||||
ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_bug(base.span, "Ill-typed base expression in \
|
||||
index");
|
||||
}
|
||||
}
|
||||
ds += auto_unbox.ds;
|
||||
ex = base;
|
||||
|
|
@ -92,6 +96,8 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
|
|||
ty::ty_res(_, _, _) { }
|
||||
ty::ty_enum(_, _) { }
|
||||
ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
|
||||
_ { tcx.sess.span_bug(base.span, "Ill-typed base \
|
||||
expression in deref"); }
|
||||
}
|
||||
ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
|
||||
outer_t: base_t}];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import syntax::ast_util;
|
|||
import syntax::ast_util::respan;
|
||||
import syntax::fold;
|
||||
import syntax::fold::*;
|
||||
import syntax::codemap::span;
|
||||
|
||||
export normalize_arms;
|
||||
export normalize_pat;
|
||||
|
|
@ -80,10 +81,8 @@ type pat_id_map = std::map::hashmap<str, node_id>;
|
|||
// use the node_id of their namesake in the first pattern.
|
||||
fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
|
||||
let map = std::map::new_str_hash::<node_id>();
|
||||
pat_bindings(normalize_pat(tcx, pat)) {|bound|
|
||||
let name = path_to_ident(alt bound.node
|
||||
{ pat_ident(n, _) { n } });
|
||||
map.insert(name, bound.id);
|
||||
pat_bindings(normalize_pat(tcx, pat)) {|p_id, _s, n|
|
||||
map.insert(path_to_ident(n), p_id);
|
||||
};
|
||||
ret map;
|
||||
}
|
||||
|
|
@ -91,10 +90,11 @@ fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
|
|||
// This does *not* normalize. The pattern should be already normalized
|
||||
// if you want to get a normalized pattern out of it.
|
||||
// Could return a constrained type in order to express that (future work)
|
||||
fn pat_bindings(pat: @pat, it: fn(@pat)) {
|
||||
fn pat_bindings(pat: @pat, it: fn(node_id, span, @path)) {
|
||||
alt pat.node {
|
||||
pat_ident(_, option::none) { it(pat); }
|
||||
pat_ident(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
|
||||
pat_ident(pth, option::none) { it(pat.id, pat.span, pth); }
|
||||
pat_ident(pth, option::some(sub)) { it(pat.id, pat.span, pth);
|
||||
pat_bindings(sub, it); }
|
||||
pat_enum(_, sub) { for p in sub { pat_bindings(p, it); } }
|
||||
pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
|
||||
pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
|
||||
|
|
@ -106,7 +106,7 @@ fn pat_bindings(pat: @pat, it: fn(@pat)) {
|
|||
|
||||
fn pat_binding_ids(pat: @pat) -> [node_id] {
|
||||
let found = [];
|
||||
pat_bindings(pat) {|b| found += [b.id]; };
|
||||
pat_bindings(pat) {|b_id, _sp, _pt| found += [b_id]; };
|
||||
ret found;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,15 +45,15 @@ enum scope {
|
|||
type scopes = list<scope>;
|
||||
|
||||
enum import_state {
|
||||
todo(ast::node_id, ast::ident, @[ast::ident], codemap::span, scopes),
|
||||
is_glob(@[ast::ident], scopes, codemap::span),
|
||||
todo(ast::node_id, ast::ident, @[ast::ident], span, scopes),
|
||||
is_glob(@[ast::ident], scopes, span),
|
||||
resolving(span),
|
||||
resolved(option::t<def>, /* value */
|
||||
option::t<def>, /* type */
|
||||
option::t<def>, /* module */
|
||||
@[@_impl], /* impls */
|
||||
/* used for reporting unused import warning */
|
||||
ast::ident, codemap::span),
|
||||
ast::ident, span),
|
||||
}
|
||||
|
||||
enum glob_import_state {
|
||||
|
|
@ -83,11 +83,13 @@ fn new_ext_hash() -> ext_hash {
|
|||
}
|
||||
|
||||
enum mod_index_entry {
|
||||
mie_view_item(@ast::view_item),
|
||||
mie_import_ident(node_id, codemap::span),
|
||||
mie_view_item(ident, node_id, span),
|
||||
mie_import_ident(node_id, span),
|
||||
mie_item(@ast::item),
|
||||
mie_native_item(@ast::native_item),
|
||||
mie_enum_variant(/* enum item */@ast::item, /* variant index */uint),
|
||||
mie_enum_variant(/* variant index */uint,
|
||||
/*parts of enum item*/ [variant],
|
||||
node_id, span),
|
||||
}
|
||||
|
||||
type mod_index = hashmap<ident, list<mod_index_entry>>;
|
||||
|
|
@ -278,6 +280,8 @@ fn map_crate(e: @env, c: @ast::crate) {
|
|||
scope_crate {
|
||||
e.mod_map.get(ast::crate_node_id).glob_imports += [glob];
|
||||
}
|
||||
_ { e.sess.span_bug(vi.span, "Unexpected scope in a glob \
|
||||
import"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -294,6 +298,7 @@ fn resolve_imports(e: env) {
|
|||
resolve_import(e, local_def(node_id), name, *path, span, scopes);
|
||||
}
|
||||
resolved(_, _, _, _, _, _) | is_glob(_, _, _) { }
|
||||
_ { e.sess.bug("Shouldn't see a resolving in resolve_imports"); }
|
||||
}
|
||||
};
|
||||
e.used_imports.track = false;
|
||||
|
|
@ -478,7 +483,7 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
|
|||
if is_main_name([nm]) && !e.sess.building_library {
|
||||
// This is a main function -- set it in the session
|
||||
// as the main ID
|
||||
e.sess.main_fn = some(id);
|
||||
e.sess.main_fn = some((id, sp));
|
||||
}
|
||||
}
|
||||
_ { /* fallthrough */ }
|
||||
|
|
@ -665,6 +670,9 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
|
|||
lst(id,
|
||||
option::get(e.mod_map.get(ast::crate_node_id).m).view_items)
|
||||
}
|
||||
_ {
|
||||
e.sess.bug("find_imports_after: nil or unexpected scope");
|
||||
}
|
||||
}
|
||||
}
|
||||
// This function has cleanup code at the end. Do not return without going
|
||||
|
|
@ -904,6 +912,10 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
|||
ast::native_item_fn(decl, ty_params) {
|
||||
ret lookup_in_fn(e, name, decl, ty_params, ns);
|
||||
}
|
||||
_ {
|
||||
e.sess.span_bug(it.span, "lookup_in_scope: \
|
||||
scope_native_item doesn't refer to a native item");
|
||||
}
|
||||
}
|
||||
}
|
||||
scope_bare_fn(decl, _, ty_params) |
|
||||
|
|
@ -1005,10 +1017,10 @@ fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
|
|||
fn lookup_in_pat(e: env, name: ident, pat: @ast::pat) -> option::t<def_id> {
|
||||
let found = none;
|
||||
|
||||
pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat)) {|bound|
|
||||
let p_name = alt bound.node { ast::pat_ident(n, _) { n } };
|
||||
if str::eq(path_to_ident(p_name), name)
|
||||
{ found = some(local_def(bound.id)); }
|
||||
pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat))
|
||||
{|p_id, _sp, n|
|
||||
if str::eq(path_to_ident(n), name)
|
||||
{ found = some(local_def(p_id)); }
|
||||
};
|
||||
ret found;
|
||||
}
|
||||
|
|
@ -1114,6 +1126,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
|
|||
_ {}
|
||||
}
|
||||
}
|
||||
_ { e.sess.span_bug(vi.span, "Unexpected view_item in block"); }
|
||||
}
|
||||
}
|
||||
ret none;
|
||||
|
|
@ -1189,16 +1202,16 @@ fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace,
|
|||
ast::def_native_mod(defid) {
|
||||
ret lookup_in_local_native_mod(e, defid.node, sp, name, ns);
|
||||
}
|
||||
_ {
|
||||
// Precondition
|
||||
e.sess.span_bug(sp, "lookup_in_mod was passed a non-mod def");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn found_view_item(e: env, vi: @ast::view_item) -> option::t<def> {
|
||||
alt vi.node {
|
||||
ast::view_item_use(_, _, id) {
|
||||
let cnum = cstore::get_use_stmt_cnum(e.cstore, id);
|
||||
ret some(ast::def_mod({crate: cnum, node: ast::crate_node_id}));
|
||||
}
|
||||
}
|
||||
fn found_view_item(e: env, id: node_id) -> def {
|
||||
let cnum = cstore::get_use_stmt_cnum(e.cstore, id);
|
||||
ret ast::def_mod({crate: cnum, node: ast::crate_node_id});
|
||||
}
|
||||
|
||||
fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
|
||||
|
|
@ -1220,6 +1233,9 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
|
|||
ret alt ns { ns_val(_) { val } ns_type { typ }
|
||||
ns_module { md } };
|
||||
}
|
||||
is_glob(_,_,_) {
|
||||
e.sess.bug("lookup_import: can't handle is_glob");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1267,6 +1283,9 @@ fn lookup_in_globs(e: env, globs: [glob_imp_def], sp: span, id: ident,
|
|||
ast::view_item_import_glob(_, id) {
|
||||
if vec::member(id, e.ignored_imports) { ret none; }
|
||||
}
|
||||
_ {
|
||||
e.sess.span_bug(sp, "lookup_in_globs: not a glob");
|
||||
}
|
||||
}
|
||||
alt lookup_in_mod(e, def.def, sp, name, ns, dr) {
|
||||
some(d) { option::some({def: d, item: def.item}) }
|
||||
|
|
@ -1322,24 +1341,20 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
|
|||
fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
|
||||
option::t<def> {
|
||||
alt mie {
|
||||
mie_view_item(view_item) {
|
||||
if ns == ns_module { ret found_view_item(e, view_item); }
|
||||
mie_view_item(_, id, _) {
|
||||
if ns == ns_module { ret some(found_view_item(e, id)); }
|
||||
}
|
||||
mie_import_ident(id, _) { ret lookup_import(e, local_def(id), ns); }
|
||||
mie_item(item) { ret found_def_item(item, ns); }
|
||||
mie_enum_variant(item, variant_idx) {
|
||||
alt item.node {
|
||||
ast::item_enum(variants, _) {
|
||||
alt ns {
|
||||
ns_val(_) {
|
||||
let vid = variants[variant_idx].node.id;
|
||||
ret some(ast::def_variant(local_def(item.id),
|
||||
mie_enum_variant(variant_idx, variants, parent_id, parent_span) {
|
||||
alt ns {
|
||||
ns_val(_) {
|
||||
let vid = variants[variant_idx].node.id;
|
||||
ret some(ast::def_variant(local_def(parent_id),
|
||||
local_def(vid)));
|
||||
}
|
||||
_ { ret none::<def>; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { ret none::<def>; }
|
||||
}
|
||||
}
|
||||
mie_native_item(native_item) {
|
||||
alt native_item.node {
|
||||
|
|
@ -1374,8 +1389,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
|||
let index = new_str_hash::<list<mod_index_entry>>();
|
||||
for it: @ast::view_item in md.view_items {
|
||||
alt it.node {
|
||||
ast::view_item_use(ident, _, _) {
|
||||
add_to_index(index, ident, mie_view_item(it));
|
||||
ast::view_item_use(ident, _, id) {
|
||||
add_to_index(index, ident, mie_view_item(ident, id, it.span));
|
||||
}
|
||||
ast::view_item_import(ident, _, id) {
|
||||
add_to_index(index, ident, mie_import_ident(id, it.span));
|
||||
|
|
@ -1405,7 +1420,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
|||
let variant_idx: uint = 0u;
|
||||
for v: ast::variant in variants {
|
||||
add_to_index(index, v.node.name,
|
||||
mie_enum_variant(it, variant_idx));
|
||||
mie_enum_variant(variant_idx, variants,
|
||||
it.id, it.span));
|
||||
variant_idx += 1u;
|
||||
}
|
||||
}
|
||||
|
|
@ -1418,8 +1434,9 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
|
|||
let index = new_str_hash::<list<mod_index_entry>>();
|
||||
for it: @ast::view_item in md.view_items {
|
||||
alt it.node {
|
||||
ast::view_item_use(ident, _, _) {
|
||||
add_to_index(index, ident, mie_view_item(it));
|
||||
ast::view_item_use(ident, _, id) {
|
||||
add_to_index(index, ident, mie_view_item(ident, id,
|
||||
it.span));
|
||||
}
|
||||
ast::view_item_import(ident, _, id) {
|
||||
add_to_index(index, ident, mie_import_ident(id, it.span));
|
||||
|
|
@ -1431,6 +1448,7 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
|
|||
}
|
||||
}
|
||||
ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) { }
|
||||
_ { /* tag exports */ }
|
||||
}
|
||||
}
|
||||
for it: @ast::native_item in md.items {
|
||||
|
|
@ -1450,6 +1468,7 @@ fn ns_for_def(d: def) -> namespace {
|
|||
ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
|
||||
ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
|
||||
ast::def_native_ty(_) { ns_type }
|
||||
ast::def_ty_param(_, _) { ns_type }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1529,10 +1548,10 @@ fn check_mod_name(e: env, name: ident, entries: list<mod_index_entry>) {
|
|||
|
||||
fn mie_span(mie: mod_index_entry) -> span {
|
||||
ret alt mie {
|
||||
mie_view_item(item) { item.span }
|
||||
mie_view_item(_, _, span) { span }
|
||||
mie_import_ident(_, span) { span }
|
||||
mie_item(item) { item.span }
|
||||
mie_enum_variant(item, _) { item.span }
|
||||
mie_enum_variant(_, _, _, span) { span }
|
||||
mie_native_item(item) { item.span }
|
||||
};
|
||||
}
|
||||
|
|
@ -1559,9 +1578,8 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
|
|||
}
|
||||
|
||||
fn check_pat(e: @env, ch: checker, p: @ast::pat) {
|
||||
pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|p|
|
||||
let ident = path_to_ident(alt p.node { pat_ident(n, _) { n } });
|
||||
add_name(ch, p.span, ident);
|
||||
pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|_i, p_sp, n|
|
||||
add_name(ch, p_sp, path_to_ident(n));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1607,14 +1625,13 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
|
|||
ast::decl_local(locs) {
|
||||
let local_values = checker(*e, "value");
|
||||
for (_, loc) in locs {
|
||||
pat_util::pat_bindings
|
||||
(normalize_pat_def_map(e.def_map, loc.node.pat))
|
||||
{|p|
|
||||
let ident = path_to_ident(alt p.node
|
||||
{ pat_ident(n, _) { n } });
|
||||
add_name(local_values, p.span, ident);
|
||||
check_name(values, p.span, ident);
|
||||
};
|
||||
pat_util::pat_bindings
|
||||
(normalize_pat_def_map(e.def_map, loc.node.pat))
|
||||
{|_i, p_sp, n|
|
||||
let ident = path_to_ident(n);
|
||||
add_name(local_values, p_sp, ident);
|
||||
check_name(values, p_sp, ident);
|
||||
};
|
||||
}
|
||||
}
|
||||
ast::decl_item(it) {
|
||||
|
|
@ -1807,8 +1824,9 @@ fn check_exports(e: @env) {
|
|||
some(ms) {
|
||||
list::iter(ms) {|m|
|
||||
alt m {
|
||||
mie_enum_variant(parent_item,_) {
|
||||
if parent_item.id != parent_id {
|
||||
mie_enum_variant(_, _, actual_parent_id,
|
||||
_) {
|
||||
if actual_parent_id != parent_id {
|
||||
e.sess.span_err(vi.span,
|
||||
#fmt("variant %s \
|
||||
doesn't belong to enum %s",
|
||||
|
|
@ -1860,6 +1878,10 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
|
|||
scopes);
|
||||
alt e.imports.get(id) {
|
||||
resolved(_, _, _, is, _, _) { act(is); }
|
||||
_ {
|
||||
e.sess.bug("Undocumented invariant in \
|
||||
lookup_imported_impls");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
|
|
@ -1899,6 +1921,8 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
|
|||
_ {}
|
||||
}
|
||||
}
|
||||
_ { e.sess.span_bug(vi.span, "Undocumented invariant in \
|
||||
find_impls_in_view_item"); }
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
|
|
|
|||
|
|
@ -451,6 +451,12 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
|
|||
ty::ty_opaque_closure_ptr(_) {
|
||||
s += [shape_opaque_closure_ptr];
|
||||
}
|
||||
ty::ty_constr(inner_t, _) {
|
||||
s += shape_of(ccx, inner_t, ty_param_map);
|
||||
}
|
||||
ty::ty_named(_, _) {
|
||||
ccx.tcx.sess.bug("shape_of: shouldn't see a ty_named");
|
||||
}
|
||||
}
|
||||
|
||||
ret s;
|
||||
|
|
@ -699,6 +705,7 @@ fn static_size_of_enum(cx: @crate_ctxt, t: ty::t)
|
|||
cx.enum_sizes.insert(t, max_size);
|
||||
ret max_size;
|
||||
}
|
||||
_ { cx.tcx.sess.bug("static_size_of_enum called on non-enum"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -779,6 +786,11 @@ fn dynamic_metrics(cx: @block_ctxt, t: ty::t) -> metrics {
|
|||
|
||||
{ bcx: bcx, sz: sz, align: C_int(ccx, 1) }
|
||||
}
|
||||
_ {
|
||||
// Precondition?
|
||||
bcx_tcx(cx).sess.bug("dynamic_metrics: type has static \
|
||||
size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import common::*;
|
|||
// range)
|
||||
enum opt {
|
||||
lit(@ast::expr),
|
||||
var(/* disr val */int, /* variant dids */{tg: def_id, var: def_id}),
|
||||
var(/* disr val */int, /* variant dids */{enm: def_id, var: def_id}),
|
||||
range(@ast::expr, @ast::expr)
|
||||
}
|
||||
fn opt_eq(a: opt, b: opt) -> bool {
|
||||
|
|
@ -69,7 +69,7 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result {
|
|||
// FIXME: invariant -- pat_id is bound in the def_map?
|
||||
fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt {
|
||||
let vdef = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat_id));
|
||||
let variants = ty::enum_variants(ccx.tcx, vdef.tg);
|
||||
let variants = ty::enum_variants(ccx.tcx, vdef.enm);
|
||||
for v: ty::variant_info in *variants {
|
||||
if vdef.var == v.id { ret var(v.disr_val, vdef); }
|
||||
}
|
||||
|
|
@ -262,24 +262,24 @@ fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] {
|
|||
}
|
||||
|
||||
fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
|
||||
vdefs: {tg: def_id, var: def_id}, val: ValueRef) ->
|
||||
vdefs: {enm: def_id, var: def_id}, val: ValueRef) ->
|
||||
{vals: [ValueRef], bcx: @block_ctxt} {
|
||||
let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
|
||||
// invariant:
|
||||
// pat_id must have the same length ty_param_substs as vdefs?
|
||||
let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
|
||||
let blobptr = val;
|
||||
let variants = ty::enum_variants(ccx.tcx, vdefs.tg);
|
||||
let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
|
||||
let args = [];
|
||||
let size =
|
||||
vec::len(ty::enum_variant_with_id(ccx.tcx, vdefs.tg, vdefs.var).args);
|
||||
vec::len(ty::enum_variant_with_id(ccx.tcx, vdefs.enm, vdefs.var).args);
|
||||
if size > 0u && vec::len(*variants) != 1u {
|
||||
let enumptr =
|
||||
PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
|
||||
blobptr = GEPi(bcx, enumptr, [0, 1]);
|
||||
}
|
||||
let i = 0u;
|
||||
let vdefs_tg = vdefs.tg;
|
||||
let vdefs_tg = vdefs.enm;
|
||||
let vdefs_var = vdefs.var;
|
||||
while i < size {
|
||||
check (valid_variant_index(i, bcx, vdefs_tg, vdefs_var));
|
||||
|
|
@ -423,8 +423,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
|||
// Separate path for extracting and binding record fields
|
||||
if vec::len(rec_fields) > 0u {
|
||||
let rec_ty = ty::node_id_to_type(ccx.tcx, pat_id);
|
||||
let fields =
|
||||
alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
|
||||
let fields = ty::get_fields(ccx.tcx, rec_ty);
|
||||
let rec_vals = [];
|
||||
for field_name: ast::ident in rec_fields {
|
||||
let ix = option::get(ty::field_idx(field_name, fields));
|
||||
|
|
@ -444,6 +443,10 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
|||
let n_tup_elts =
|
||||
alt ty::struct(ccx.tcx, tup_ty) {
|
||||
ty::ty_tup(elts) { vec::len(elts) }
|
||||
_ {
|
||||
ccx.sess.bug("Non-tuple type in tuple\
|
||||
pattern");
|
||||
}
|
||||
};
|
||||
let tup_vals = [], i = 0u;
|
||||
while i < n_tup_elts {
|
||||
|
|
@ -483,7 +486,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
|||
if vec::len(opts) > 0u {
|
||||
alt opts[0] {
|
||||
var(_, vdef) {
|
||||
if vec::len(*ty::enum_variants(ccx.tcx, vdef.tg)) == 1u {
|
||||
if vec::len(*ty::enum_variants(ccx.tcx, vdef.enm)) == 1u {
|
||||
kind = single;
|
||||
} else {
|
||||
let enumptr =
|
||||
|
|
@ -541,6 +544,8 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
|||
llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
|
||||
bcx = r.bcx;
|
||||
}
|
||||
_ { bcx_tcx(bcx).sess.bug("Someone forgot to\
|
||||
document an invariant in compile_submatch"); }
|
||||
}
|
||||
}
|
||||
compare {
|
||||
|
|
@ -624,8 +629,11 @@ fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
|
|||
// Copy references that the alias analysis considered unsafe
|
||||
ids.values {|node_id|
|
||||
if bcx_ccx(bcx).copy_map.contains_key(node_id) {
|
||||
let local = alt bcx.fcx.lllocals.get(node_id) {
|
||||
local_mem(x) { x }
|
||||
let local = alt bcx.fcx.lllocals.find(node_id) {
|
||||
some(local_mem(x)) { x }
|
||||
_ { bcx_tcx(bcx).sess.bug("Someone \
|
||||
forgot to document an invariant in \
|
||||
make_phi_bindings"); }
|
||||
};
|
||||
let e_ty = ty::node_id_to_type(bcx_tcx(bcx), node_id);
|
||||
let {bcx: abcx, val: alloc} = base::alloc_ty(bcx, e_ty);
|
||||
|
|
@ -745,8 +753,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
|
|||
}
|
||||
ast::pat_rec(fields, _) {
|
||||
let rec_ty = ty::node_id_to_type(ccx.tcx, pat.id);
|
||||
let rec_fields =
|
||||
alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
|
||||
let rec_fields = ty::get_fields(ccx.tcx, rec_ty);
|
||||
for f: ast::field_pat in fields {
|
||||
let ix = option::get(ty::field_idx(f.ident, rec_fields));
|
||||
// how to get rid of this check?
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import link::{mangle_internal_name_by_type_only,
|
|||
import metadata::{csearch, cstore};
|
||||
import util::ppaux::{ty_to_str, ty_to_short_str};
|
||||
|
||||
import shape::static_size_of_enum;
|
||||
import common::*;
|
||||
import build::*;
|
||||
|
||||
|
|
@ -489,37 +490,6 @@ fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
|
|||
ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
|
||||
}
|
||||
|
||||
|
||||
// Computes the size of the data part of a non-dynamically-sized enum.
|
||||
fn static_size_of_enum(cx: @crate_ctxt, t: ty::t)
|
||||
: type_has_static_size(cx, t) -> uint {
|
||||
if cx.enum_sizes.contains_key(t) { ret cx.enum_sizes.get(t); }
|
||||
alt ty::struct(cx.tcx, t) {
|
||||
ty::ty_enum(tid, subtys) {
|
||||
// Compute max(variant sizes).
|
||||
|
||||
let max_size = 0u;
|
||||
let variants = ty::enum_variants(cx.tcx, tid);
|
||||
for variant: ty::variant_info in *variants {
|
||||
let tup_ty = simplify_type(cx, ty::mk_tup(cx.tcx, variant.args));
|
||||
// Perform any type parameter substitutions.
|
||||
|
||||
tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
|
||||
// Here we possibly do a recursive call.
|
||||
|
||||
// FIXME: Avoid this check. Since the parent has static
|
||||
// size, any field must as well. There should be a way to
|
||||
// express that with constrained types.
|
||||
check (type_has_static_size(cx, tup_ty));
|
||||
let this_size = llsize_of_real(cx, type_of(cx, tup_ty));
|
||||
if max_size < this_size { max_size = this_size; }
|
||||
}
|
||||
cx.enum_sizes.insert(t, max_size);
|
||||
ret max_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
|
||||
fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
|
||||
//
|
||||
|
|
@ -600,6 +570,9 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
|
|||
} else { max_size_val };
|
||||
ret rslt(bcx, total_size);
|
||||
}
|
||||
// Precondition?
|
||||
_ { bcx_tcx(cx).sess.fatal("trans::dynamic_size_of alled on something \
|
||||
with static size"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -634,6 +607,8 @@ fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result {
|
|||
}
|
||||
ret rslt(bcx, a);
|
||||
}
|
||||
_ { bcx_tcx(cx).sess.bug("trans::dynamic_align_of called on \
|
||||
something with static size"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1457,16 +1432,16 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
|||
ty::ty_int(_) { ret rslt(cx, f(signed_int)); }
|
||||
ty::ty_uint(_) { ret rslt(cx, f(unsigned_int)); }
|
||||
ty::ty_float(_) { ret rslt(cx, f(floating_point)); }
|
||||
ty::ty_native(_) {
|
||||
let cx = trans_fail(cx, none::<span>,
|
||||
"attempt to compare values of type native");
|
||||
ret rslt(cx, C_nil());
|
||||
}
|
||||
ty::ty_type {
|
||||
ret rslt(trans_fail(cx, none,
|
||||
"attempt to compare values of type type"),
|
||||
C_nil());
|
||||
}
|
||||
ty::ty_native(_) {
|
||||
let cx = trans_fail(cx, none,
|
||||
"attempt to compare values of type native");
|
||||
ret rslt(cx, C_nil());
|
||||
}
|
||||
_ {
|
||||
// Should never get here, because t is scalar.
|
||||
bcx_ccx(cx).sess.bug("non-scalar type passed to \
|
||||
|
|
@ -1479,6 +1454,11 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
|||
// A helper function to do the actual comparison of scalar values.
|
||||
fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
||||
nt: scalar_type, op: ast::binop) -> ValueRef {
|
||||
fn die_(cx: @block_ctxt) -> ! {
|
||||
bcx_tcx(cx).sess.bug("compare_scalar_values: must be a\
|
||||
comparison operator");
|
||||
}
|
||||
let die = bind die_(cx);
|
||||
alt nt {
|
||||
nil_type {
|
||||
// We don't need to do actual comparisons for nil.
|
||||
|
|
@ -1486,6 +1466,8 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
|||
alt op {
|
||||
ast::eq | ast::le | ast::ge { ret C_bool(true); }
|
||||
ast::ne | ast::lt | ast::gt { ret C_bool(false); }
|
||||
// refinements would be nice
|
||||
_ { die(); }
|
||||
}
|
||||
}
|
||||
floating_point {
|
||||
|
|
@ -1496,6 +1478,7 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
|||
ast::le { lib::llvm::LLVMRealOLE }
|
||||
ast::gt { lib::llvm::LLVMRealOGT }
|
||||
ast::ge { lib::llvm::LLVMRealOGE }
|
||||
_ { die(); }
|
||||
};
|
||||
ret FCmp(cx, cmp, lhs, rhs);
|
||||
}
|
||||
|
|
@ -1507,6 +1490,7 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
|||
ast::le { lib::llvm::LLVMIntSLE }
|
||||
ast::gt { lib::llvm::LLVMIntSGT }
|
||||
ast::ge { lib::llvm::LLVMIntSGE }
|
||||
_ { die(); }
|
||||
};
|
||||
ret ICmp(cx, cmp, lhs, rhs);
|
||||
}
|
||||
|
|
@ -1518,6 +1502,7 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
|
|||
ast::le { lib::llvm::LLVMIntULE }
|
||||
ast::gt { lib::llvm::LLVMIntUGT }
|
||||
ast::ge { lib::llvm::LLVMIntUGE }
|
||||
_ { die(); }
|
||||
};
|
||||
ret ICmp(cx, cmp, lhs, rhs);
|
||||
}
|
||||
|
|
@ -1574,6 +1559,8 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t,
|
|||
j += 1u;
|
||||
}
|
||||
}
|
||||
// Precondition?
|
||||
_ { bcx_tcx(cx).sess.bug("iter_variant: not a function type"); }
|
||||
}
|
||||
ret cx;
|
||||
}
|
||||
|
|
@ -1846,6 +1833,8 @@ fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
|
|||
alt ty::struct(bcx_tcx(bcx), t) {
|
||||
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { free_ty(bcx, v, t) }
|
||||
ty::ty_box(_) | ty::ty_iface(_, _) { decr_refcnt_maybe_free(bcx, v, t) }
|
||||
// Precondition?
|
||||
_ { bcx_tcx(bcx).sess.bug("drop_ty_immediate: non-box ty"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2112,6 +2101,9 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
|
|||
ast::eq | ast::ne { llop = C_u8(abi::cmp_glue_op_eq); }
|
||||
ast::lt | ast::ge { llop = C_u8(abi::cmp_glue_op_lt); }
|
||||
ast::le | ast::gt { llop = C_u8(abi::cmp_glue_op_le); }
|
||||
// Precondition?
|
||||
_ { bcx_tcx(cx).sess.bug("trans_compare got\
|
||||
non-comparison-op"); }
|
||||
}
|
||||
|
||||
let rs = call_cmp_glue(cx, lhs, rhs, rhs_t, llop);
|
||||
|
|
@ -2122,6 +2114,8 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
|
|||
ast::ne | ast::ge | ast::gt {
|
||||
ret rslt(rs.bcx, Not(rs.bcx, rs.val));
|
||||
}
|
||||
_ { bcx_tcx(cx).sess.bug("trans_compare got\
|
||||
non-comparison-op"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2272,9 +2266,12 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
|
|||
ret {bcx: cx, val: v1, ty: t1};
|
||||
}
|
||||
|
||||
fn trans_lazy_binop(bcx: @block_ctxt, op: ast::binop, a: @ast::expr,
|
||||
// refinement types would obviate the need for this
|
||||
enum lazy_binop_ty { lazy_and, lazy_or }
|
||||
|
||||
fn trans_lazy_binop(bcx: @block_ctxt, op: lazy_binop_ty, a: @ast::expr,
|
||||
b: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
let is_and = alt op { ast::and { true } ast::or { false } };
|
||||
let is_and = alt op { lazy_and { true } lazy_or { false } };
|
||||
let lhs_res = trans_temp_expr(bcx, a);
|
||||
if lhs_res.bcx.unreachable { ret lhs_res.bcx; }
|
||||
let rhs_cx = new_scope_block_ctxt(lhs_res.bcx, "rhs");
|
||||
|
|
@ -2321,8 +2318,11 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr,
|
|||
|
||||
// First couple cases are lazy:
|
||||
alt op {
|
||||
ast::and | ast::or {
|
||||
ret trans_lazy_binop(bcx, op, lhs, rhs, dest);
|
||||
ast::and {
|
||||
ret trans_lazy_binop(bcx, lazy_and, lhs, rhs, dest);
|
||||
}
|
||||
ast::or {
|
||||
ret trans_lazy_binop(bcx, lazy_or, lhs, rhs, dest);
|
||||
}
|
||||
_ {
|
||||
// Remaining cases are eager:
|
||||
|
|
@ -2394,7 +2394,11 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt {
|
|||
}
|
||||
|
||||
fn get_dest_addr(dest: dest) -> ValueRef {
|
||||
alt dest { save_in(a) { a } }
|
||||
alt dest {
|
||||
save_in(a) { a }
|
||||
// Precondition?
|
||||
_ { fail "get_dest_addr: not a save_in"; }
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
|
||||
|
|
@ -2425,6 +2429,9 @@ fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
|
|||
ast::expr_block(blk) {
|
||||
else_cx = trans_block_dps(else_cx, blk, else_dest);
|
||||
}
|
||||
// would be nice to have a constraint on ifs
|
||||
_ { bcx_tcx(cx).sess.bug("Strange alternative\
|
||||
in if"); }
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
|
|
@ -2691,7 +2698,12 @@ fn trans_rec_field(bcx: @block_ctxt, base: @ast::expr,
|
|||
field: ast::ident) -> lval_result {
|
||||
let {bcx, val} = trans_temp_expr(bcx, base);
|
||||
let {bcx, val, ty} = autoderef(bcx, val, ty::expr_ty(bcx_tcx(bcx), base));
|
||||
let fields = alt ty::struct(bcx_tcx(bcx), ty) { ty::ty_rec(fs) { fs } };
|
||||
let fields = alt ty::struct(bcx_tcx(bcx), ty) {
|
||||
ty::ty_rec(fs) { fs }
|
||||
// Constraint?
|
||||
_ { bcx_tcx(bcx).sess.span_bug(base.span, "trans_rec_field:\
|
||||
base expr has non-record type"); }
|
||||
};
|
||||
let ix = option::get(ty::field_idx(field, fields));
|
||||
// Silly check
|
||||
check type_is_tup_like(bcx, ty);
|
||||
|
|
@ -2763,6 +2775,9 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
|
|||
some(origin) { // An impl method
|
||||
ret impl::trans_method_callee(bcx, e.id, base, origin);
|
||||
}
|
||||
// Precondition?
|
||||
_ { bcx_tcx(bcx).sess.span_bug(e.span, "trans_callee: weird\
|
||||
expr"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2809,6 +2824,11 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
|
|||
PointerCast(sub.bcx, sub.val, ellty)
|
||||
}
|
||||
ty::ty_ptr(_) | ty::ty_uniq(_) { sub.val }
|
||||
// Precondition?
|
||||
_ {
|
||||
bcx_tcx(cx).sess.span_bug(e.span, "trans_lval:\
|
||||
Weird argument in deref");
|
||||
}
|
||||
};
|
||||
ret lval_owned(sub.bcx, val);
|
||||
}
|
||||
|
|
@ -2949,6 +2969,7 @@ fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
|
|||
integral {int_cast(e_res.bcx, ll_t_out,
|
||||
val_ty(lldiscrim_a), lldiscrim_a, true)}
|
||||
float {SIToFP(e_res.bcx, lldiscrim_a, ll_t_out)}
|
||||
_ { ccx.sess.bug("Translating unsupported cast.") }
|
||||
}
|
||||
}
|
||||
_ { ccx.sess.bug("Translating unsupported cast.") }
|
||||
|
|
@ -2990,7 +3011,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
|
|||
if arg.mode == ast::by_val && (lv.kind == owned || !imm) {
|
||||
val = Load(bcx, val);
|
||||
}
|
||||
} else if arg.mode == ast::by_copy {
|
||||
} else if arg.mode == ast::by_copy {
|
||||
let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
|
||||
let last_use = ccx.last_uses.contains_key(e.id);
|
||||
bcx = cx;
|
||||
|
|
@ -3341,6 +3362,7 @@ fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
|
|||
ret bcx;
|
||||
}
|
||||
save_in(pos) { pos }
|
||||
_ { bcx_tcx(bcx).sess.bug("trans_tup: weird dest"); }
|
||||
};
|
||||
let temp_cleanups = [], i = 0;
|
||||
for e in elts {
|
||||
|
|
@ -3368,9 +3390,12 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
|
|||
ret bcx;
|
||||
}
|
||||
save_in(pos) { pos }
|
||||
_ { bcx_tcx(bcx).sess.bug("trans_rec: weird dest"); }
|
||||
};
|
||||
|
||||
let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f } };
|
||||
let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f }
|
||||
_ { bcx_tcx(bcx).sess.bug("trans_rec: id doesn't\
|
||||
have a record type") } };
|
||||
let temp_cleanups = [];
|
||||
for fld in fields {
|
||||
let ix = option::get(vec::position_pred(ty_fields, {|ft|
|
||||
|
|
@ -3644,6 +3669,9 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||
assert dest == ignore;
|
||||
ret trans_assign_op(bcx, e, op, dst, src);
|
||||
}
|
||||
_ { bcx_tcx(bcx).sess.span_bug(e.span, "trans_expr reached\
|
||||
fall-through case"); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3914,9 +3942,18 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
|||
let ty = node_id_type(bcx_ccx(bcx), local.node.id);
|
||||
let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
|
||||
some(local_mem(v)) { v }
|
||||
some(_) { bcx_tcx(bcx).sess.span_bug(local.span,
|
||||
"init_local: Someone forgot to document why it's\
|
||||
safe to assume local.node.init must be local_mem!");
|
||||
}
|
||||
// This is a local that is kept immediate
|
||||
none {
|
||||
let initexpr = alt local.node.init { some({expr, _}) { expr } };
|
||||
let initexpr = alt local.node.init {
|
||||
some({expr, _}) { expr }
|
||||
none { bcx_tcx(bcx).sess.span_bug(local.span,
|
||||
"init_local: Someone forgot to document why it's\
|
||||
safe to assume local.node.init isn't none!"); }
|
||||
};
|
||||
let {bcx, val, kind} = trans_temp_lval(bcx, initexpr);
|
||||
if kind != temporary {
|
||||
if kind == owned { val = Load(bcx, val); }
|
||||
|
|
@ -3952,6 +3989,8 @@ fn init_ref_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
|||
alt kind {
|
||||
owned_imm { val = do_spill_noroot(bcx, val); }
|
||||
owned {}
|
||||
_ { bcx_tcx(bcx).sess.span_bug(local.span,
|
||||
"Someone forgot to document an invariant in init_ref_local!"); }
|
||||
}
|
||||
ret alt::bind_irrefutable_pat(bcx, local.node.pat, val, false);
|
||||
}
|
||||
|
|
@ -4388,9 +4427,15 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
|
|||
fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
|
||||
arg_tys: [ty::arg]) -> @block_ctxt {
|
||||
let arg_n: uint = 0u, bcx = bcx;
|
||||
fn epic_fail_(bcx: @block_ctxt) -> ! {
|
||||
bcx_tcx(bcx).sess.bug("Someone forgot\
|
||||
to document an invariant in copy_args_to_allocas!");
|
||||
}
|
||||
let epic_fail = bind epic_fail_(bcx);
|
||||
for arg in arg_tys {
|
||||
let id = args[arg_n].id;
|
||||
let argval = alt fcx.llargs.get(id) { local_mem(v) { v } };
|
||||
let argval = alt fcx.llargs.get(id) { local_mem(v) { v }
|
||||
_ { epic_fail() } };
|
||||
alt arg.mode {
|
||||
ast::by_mut_ref { }
|
||||
ast::by_move | ast::by_copy { add_clean(bcx, argval, arg.ty); }
|
||||
|
|
@ -4405,6 +4450,7 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
|
|||
}
|
||||
}
|
||||
ast::by_ref {}
|
||||
_ { epic_fail(); }
|
||||
}
|
||||
if fcx_ccx(fcx).sess.opts.extra_debuginfo {
|
||||
debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
|
||||
|
|
@ -4414,9 +4460,13 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
|
|||
ret bcx;
|
||||
}
|
||||
|
||||
// cries out for a precondition
|
||||
fn arg_tys_of_fn(ccx: @crate_ctxt, id: ast::node_id) -> [ty::arg] {
|
||||
alt ty::struct(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)) {
|
||||
let tt = ty::node_id_to_type(ccx.tcx, id);
|
||||
alt ty::struct(ccx.tcx, tt) {
|
||||
ty::ty_fn({inputs, _}) { inputs }
|
||||
_ { ccx.sess.bug(#fmt("arg_tys_of_fn called on non-function\
|
||||
type %s", ty_to_str(ccx.tcx, tt)));}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4438,14 +4488,14 @@ enum self_arg { impl_self(ty::t), no_self, }
|
|||
// trans_closure: Builds an LLVM function out of a source function.
|
||||
// If the function closes over its environment a closure will be
|
||||
// returned.
|
||||
fn trans_closure(cx: @local_ctxt, sp: span, decl: ast::fn_decl,
|
||||
fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
|
||||
body: ast::blk, llfndecl: ValueRef,
|
||||
ty_self: self_arg, ty_params: [ast::ty_param],
|
||||
id: ast::node_id, maybe_load_env: fn(@fn_ctxt)) {
|
||||
set_uwtable(llfndecl);
|
||||
|
||||
// Set up arguments to the function.
|
||||
let fcx = new_fn_ctxt_w_id(cx, llfndecl, id, decl.cf, some(sp));
|
||||
let fcx = new_fn_ctxt_w_id(cx, llfndecl, id, decl.cf, some(body.span));
|
||||
create_llargs_for_fn_args(fcx, ty_self, decl.inputs, ty_params);
|
||||
|
||||
// Create the first basic block in the function and keep a handle on it to
|
||||
|
|
@ -4480,7 +4530,7 @@ fn trans_closure(cx: @local_ctxt, sp: span, decl: ast::fn_decl,
|
|||
|
||||
// trans_fn: creates an LLVM function corresponding to a source language
|
||||
// function.
|
||||
fn trans_fn(cx: @local_ctxt, sp: span, decl: ast::fn_decl, body: ast::blk,
|
||||
fn trans_fn(cx: @local_ctxt, decl: ast::fn_decl, body: ast::blk,
|
||||
llfndecl: ValueRef, ty_self: self_arg, ty_params: [ast::ty_param],
|
||||
id: ast::node_id) {
|
||||
let do_time = cx.ccx.sess.opts.stats;
|
||||
|
|
@ -4490,7 +4540,7 @@ fn trans_fn(cx: @local_ctxt, sp: span, decl: ast::fn_decl, body: ast::blk,
|
|||
{sec: 0u32, usec: 0u32}
|
||||
};
|
||||
let fcx = option::none;
|
||||
trans_closure(cx, sp, decl, body, llfndecl, ty_self, ty_params, id,
|
||||
trans_closure(cx, decl, body, llfndecl, ty_self, ty_params, id,
|
||||
{|new_fcx| fcx = option::some(new_fcx);});
|
||||
if cx.ccx.sess.opts.extra_debuginfo {
|
||||
debuginfo::create_function(option::get(fcx));
|
||||
|
|
@ -4516,6 +4566,8 @@ fn trans_res_ctor(cx: @local_ctxt, dtor: ast::fn_decl,
|
|||
let tup_t = ty::mk_tup(ccx.tcx, [ty::mk_int(ccx.tcx), arg_t]);
|
||||
let arg = alt fcx.llargs.find(dtor.inputs[0].id) {
|
||||
some(local_mem(x)) { x }
|
||||
_ { ccx.sess.bug("Someone forgot to document an invariant \
|
||||
in trans_res_ctor"); }
|
||||
};
|
||||
let llretptr = fcx.llretptr;
|
||||
if ty::type_has_dynamic_size(ccx.tcx, ret_t) {
|
||||
|
|
@ -4603,7 +4655,9 @@ fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
|
|||
// If this argument to this function is a enum, it'll have come in to
|
||||
// this function as an opaque blob due to the way that type_of()
|
||||
// works. So we have to cast to the destination's view of the type.
|
||||
let llarg = alt fcx.llargs.find(va.id) { some(local_mem(x)) { x } };
|
||||
let llarg = alt fcx.llargs.find(va.id) { some(local_mem(x)) { x }
|
||||
_ { bcx_tcx(bcx).sess.span_fatal(variant.span, "Someone forgot\
|
||||
to document an invariant in trans_tag_variant"); } };
|
||||
let arg_ty = arg_tys[i].ty;
|
||||
if ty::type_contains_params(bcx_tcx(bcx), arg_ty) {
|
||||
lldestptr = PointerCast(bcx, lldestptr, val_ty(llarg));
|
||||
|
|
@ -4733,6 +4787,10 @@ fn c_stack_tys(ccx: @crate_ctxt,
|
|||
shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void())
|
||||
};
|
||||
}
|
||||
_ {
|
||||
// Precondition?
|
||||
ccx.tcx.sess.bug("c_stack_tys called on non-function type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4889,7 +4947,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
|
|||
let sub_cx = extend_path(cx, item.ident);
|
||||
alt cx.ccx.item_ids.find(item.id) {
|
||||
some(llfndecl) {
|
||||
trans_fn(sub_cx, item.span, decl, body, llfndecl, no_self, tps,
|
||||
trans_fn(sub_cx, decl, body, llfndecl, no_self, tps,
|
||||
item.id);
|
||||
}
|
||||
_ {
|
||||
|
|
@ -4907,7 +4965,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
|
|||
// Create a function for the destructor
|
||||
alt cx.ccx.item_ids.find(item.id) {
|
||||
some(lldtor_decl) {
|
||||
trans_fn(cx, item.span, decl, body, lldtor_decl, no_self,
|
||||
trans_fn(cx, decl, body, lldtor_decl, no_self,
|
||||
tps, dtor_id);
|
||||
}
|
||||
_ {
|
||||
|
|
@ -4998,8 +5056,10 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
|
|||
}
|
||||
|
||||
let main_takes_argv =
|
||||
// invariant!
|
||||
alt ty::struct(ccx.tcx, main_node_type) {
|
||||
ty::ty_fn({inputs, _}) { vec::len(inputs) != 0u }
|
||||
_ { ccx.sess.span_fatal(sp, "main has a non-function type"); }
|
||||
};
|
||||
|
||||
let llfn = create_main(ccx, main_llfn, main_takes_argv);
|
||||
|
|
@ -5094,7 +5154,10 @@ fn fill_fn_pair(bcx: @block_ctxt, pair: ValueRef, llfn: ValueRef,
|
|||
fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
|
||||
let count;
|
||||
let native_item =
|
||||
alt cx.ast_map.find(id) { some(ast_map::node_native_item(i)) { i } };
|
||||
// invariant?!
|
||||
alt cx.ast_map.find(id) { some(ast_map::node_native_item(i)) { i }
|
||||
_ { cx.sess.bug("native_fn_ty_param_count\
|
||||
given a non-native item"); } };
|
||||
alt native_item.node {
|
||||
ast::native_item_ty {
|
||||
cx.sess.bug("register_native_fn(): native fn isn't \
|
||||
|
|
@ -5107,13 +5170,17 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
|
|||
ret count;
|
||||
}
|
||||
|
||||
fn native_fn_wrapper_type(cx: @crate_ctxt,
|
||||
|
||||
// TODO: precondition
|
||||
fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span,
|
||||
param_bounds: [ty::param_bounds],
|
||||
x: ty::t) -> TypeRef {
|
||||
alt ty::struct(cx.tcx, x) {
|
||||
ty::ty_fn({inputs: args, output: out, _}) {
|
||||
ret type_of_fn(cx, args, out, param_bounds);
|
||||
}
|
||||
_ { cx.sess.span_bug(sp, "native_fn_wrapper_type got ill-typed\
|
||||
thing"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
|
|||
let cap_vars = capture::compute_capture_vars(
|
||||
ccx.tcx, id, proto, cap_clause);
|
||||
let {llbox, cbox_ty, bcx} = build_closure(bcx, cap_vars, ck);
|
||||
trans_closure(sub_cx, sp, decl, body, llfn, no_self, [], id, {|fcx|
|
||||
trans_closure(sub_cx, decl, body, llfn, no_self, [], id, {|fcx|
|
||||
load_environment(bcx, fcx, cbox_ty, cap_vars, ck);
|
||||
});
|
||||
llbox
|
||||
|
|
@ -532,7 +532,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
|
|||
ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
|
||||
ast::proto_bare {
|
||||
let closure = C_null(T_opaque_cbox_ptr(ccx));
|
||||
trans_closure(sub_cx, sp, decl, body, llfn, no_self, [],
|
||||
trans_closure(sub_cx, decl, body, llfn, no_self, [],
|
||||
id, {|_fcx|});
|
||||
closure
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,6 +414,9 @@ fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
|
|||
if cx.kind != NON_SCOPE_BLOCK { ret cx; }
|
||||
alt cx.parent {
|
||||
parent_some(b) { ret find_scope_cx(b); }
|
||||
_ {
|
||||
bcx_tcx(cx).sess.bug("find_scope_cx: empty scope");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import core::ctypes::c_uint;
|
|||
import base::*;
|
||||
import common::*;
|
||||
import build::*;
|
||||
import driver::session::session;
|
||||
import option::{some, none};
|
||||
import syntax::{ast, ast_util};
|
||||
import metadata::csearch;
|
||||
|
|
@ -45,10 +46,13 @@ fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
|
|||
for m in methods {
|
||||
alt cx.ccx.item_ids.find(m.id) {
|
||||
some(llfn) {
|
||||
trans_fn(extend_path(sub_cx, m.ident), m.span, m.decl, m.body,
|
||||
trans_fn(extend_path(sub_cx, m.ident), m.decl, m.body,
|
||||
llfn, impl_self(ty::node_id_to_type(cx.ccx.tcx, id)),
|
||||
tps + m.tps, m.id);
|
||||
}
|
||||
_ {
|
||||
cx.ccx.tcx.sess.bug("Unbound id in trans_impl");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -148,6 +152,9 @@ fn trans_iface_callee(bcx: @block_ctxt, callee_id: ast::node_id,
|
|||
T_opaque_cbox_ptr(bcx_ccx(bcx)));
|
||||
let iface_id = alt ty::struct(tcx, ty::expr_ty(tcx, base)) {
|
||||
ty::ty_iface(did, _) { did }
|
||||
// precondition
|
||||
_ { bcx_tcx(bcx).sess.span_bug(base.span, "base has non-iface type \
|
||||
in trans_iface_callee"); }
|
||||
};
|
||||
trans_vtable_callee(bcx, self, dict, callee_id, iface_id, n_method)
|
||||
}
|
||||
|
|
@ -241,6 +248,10 @@ fn trans_impl_vtable(ccx: @crate_ctxt, pt: [ast::ident],
|
|||
let target = ccx.item_ids.get(m.id);
|
||||
trans_impl_wrapper(ccx, new_pt + [m.ident], extra_tps, target)
|
||||
}
|
||||
_ {
|
||||
ccx.tcx.sess.span_bug(it.span, "No matching method \
|
||||
in trans_impl_vtable");
|
||||
}
|
||||
}
|
||||
});
|
||||
let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
|
||||
|
|
@ -340,6 +351,10 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
|
|||
d_params += [dict_param_dict(dict_id(tcx, origs[orig]))];
|
||||
orig += 1u;
|
||||
}
|
||||
_ {
|
||||
tcx.sess.bug("Someone forgot to document an invariant in \
|
||||
dict_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -348,6 +363,9 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
|
|||
typeck::dict_iface(did) {
|
||||
@{def: did, params: []}
|
||||
}
|
||||
_ {
|
||||
tcx.sess.bug("Unexpected dict_param in dict_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,6 +428,9 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
|
|||
typeck::dict_iface(did) {
|
||||
{bcx: bcx, ptrs: [get_vtable(ccx, did)]}
|
||||
}
|
||||
_ {
|
||||
bcx_tcx(bcx).sess.bug("Unexpected dict_param in get_dict_ptrs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import vec;
|
||||
import option::none;
|
||||
import syntax::ast;
|
||||
import driver::session::session;
|
||||
import lib::llvm::llvm::{ValueRef, TypeRef};
|
||||
import back::abi;
|
||||
import base::{call_memmove, trans_shared_malloc, type_of_or_i8,
|
||||
|
|
@ -159,6 +160,10 @@ fn trans_append(cx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
|
|||
let strings = alt ty::struct(bcx_tcx(cx), vec_ty) {
|
||||
ty::ty_str { true }
|
||||
ty::ty_vec(_) { false }
|
||||
_ {
|
||||
// precondition?
|
||||
bcx_tcx(cx).sess.bug("Bad argument type in trans_append");
|
||||
}
|
||||
};
|
||||
|
||||
let {bcx: bcx, val: unit_sz} = size_of(cx, unit_ty);
|
||||
|
|
@ -230,7 +235,7 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhs: ValueRef,
|
|||
let ccx = bcx_ccx(bcx);
|
||||
let strings = alt ty::struct(bcx_tcx(bcx), vec_ty) {
|
||||
ty::ty_str { true }
|
||||
ty::ty_vec(_) { false }
|
||||
_ { false }
|
||||
};
|
||||
let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
|
||||
let llunitty = type_of_or_i8(bcx, unit_ty);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ fn content_ty(bcx: @block_ctxt, t: ty::t)
|
|||
|
||||
alt ty::struct(bcx_tcx(bcx), t) {
|
||||
ty::ty_uniq({ty: ct, _}) { ct }
|
||||
_ { std::util::unreachable(); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -582,12 +582,14 @@ fn expr_to_constr_arg(tcx: ty::ctxt, e: @expr) -> @constr_arg_use {
|
|||
ret @respan(p.span,
|
||||
carg_ident({ident: p.node.idents[0], node: id.node}));
|
||||
}
|
||||
some(_) {
|
||||
tcx.sess.bug("exprs_to_constr_args: non-local variable " +
|
||||
"as pred arg");
|
||||
some(what) {
|
||||
tcx.sess.span_bug(e.span,
|
||||
#fmt("exprs_to_constr_args: non-local variable %? \
|
||||
as pred arg", what));
|
||||
}
|
||||
none {
|
||||
tcx.sess.bug("exprs_to_constr_args: NONE " + "as pred arg");
|
||||
tcx.sess.span_bug(e.span,
|
||||
"exprs_to_constr_args: unbound id as pred arg");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1055,10 +1057,8 @@ type binding = {lhs: [inst], rhs: option::t<initializer>};
|
|||
|
||||
fn local_to_bindings(tcx: ty::ctxt, loc: @local) -> binding {
|
||||
let lhs = [];
|
||||
pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p|
|
||||
let ident = alt p.node
|
||||
{ pat_ident(name, _) { path_to_ident(name) } };
|
||||
lhs += [{ident: ident, node: p.id}];
|
||||
pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p_id, _s, name|
|
||||
lhs += [{ident: path_to_ident(name), node: p_id}];
|
||||
};
|
||||
{lhs: lhs, rhs: loc.node.init}
|
||||
}
|
||||
|
|
@ -1070,7 +1070,7 @@ fn locals_to_bindings(tcx: ty::ctxt,
|
|||
ret rslt;
|
||||
}
|
||||
|
||||
fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [ty::mode] {
|
||||
fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [mode] {
|
||||
let ty =
|
||||
ty::type_autoderef(fcx.ccx.tcx,
|
||||
ty::node_id_to_type(fcx.ccx.tcx, callee));
|
||||
|
|
@ -1089,7 +1089,7 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [ty::mode] {
|
|||
}
|
||||
|
||||
fn callee_arg_init_ops(fcx: fn_ctxt, callee: node_id) -> [init_op] {
|
||||
fn mode_to_op(m: ty::mode) -> init_op {
|
||||
fn mode_to_op(m: mode) -> init_op {
|
||||
alt m { by_move { init_move } _ { init_assign } }
|
||||
}
|
||||
vec::map(callee_modes(fcx, callee), mode_to_op)
|
||||
|
|
|
|||
|
|
@ -12,11 +12,9 @@ import aux::*;
|
|||
type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};
|
||||
|
||||
fn collect_local(loc: @local, cx: ctxt, v: visit::vt<ctxt>) {
|
||||
pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat)) {|p|
|
||||
let ident = alt p.node
|
||||
{ pat_ident(id, _) { path_to_ident(id) } };
|
||||
log(debug, "collect_local: pushing " + ident);;
|
||||
*cx.cs += [respan(loc.span, ninit(p.id, ident))];
|
||||
pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat))
|
||||
{|p_id, _s, id|
|
||||
*cx.cs += [respan(loc.span, ninit(p_id, path_to_ident(id)))];
|
||||
};
|
||||
visit::visit_local(loc, cx, v);
|
||||
}
|
||||
|
|
@ -26,10 +24,6 @@ fn collect_pred(e: @expr, cx: ctxt, v: visit::vt<ctxt>) {
|
|||
expr_check(_, ch) { *cx.cs += [expr_to_constr(cx.tcx, ch)]; }
|
||||
expr_if_check(ex, _, _) { *cx.cs += [expr_to_constr(cx.tcx, ex)]; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// If it's a call, generate appropriate instances of the
|
||||
// call's constraints.
|
||||
expr_call(operator, operands, _) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import util::common::{new_def_hash, log_expr, field_exprs,
|
|||
import syntax::codemap::span;
|
||||
import driver::session::session;
|
||||
|
||||
|
||||
fn find_pre_post_mod(_m: _mod) -> _mod {
|
||||
#debug("implement find_pre_post_mod!");
|
||||
fail;
|
||||
|
|
@ -106,14 +105,12 @@ fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk,
|
|||
id: node_id) {
|
||||
find_pre_post_expr(fcx, index);
|
||||
find_pre_post_block(fcx, body);
|
||||
pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
|
||||
let ident = alt p.node
|
||||
{ pat_ident(id, _) { path_to_ident(id) } };
|
||||
let v_init = ninit(p.id, ident);
|
||||
pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p_id, _s, n|
|
||||
let v_init = ninit(p_id, path_to_ident(n));
|
||||
relax_precond_block(fcx, bit_num(fcx, v_init) as node_id, body);
|
||||
// Hack: for-loop index variables are frequently ignored,
|
||||
// so we pretend they're used
|
||||
use_var(fcx, p.id);
|
||||
use_var(fcx, p_id);
|
||||
};
|
||||
|
||||
let loop_precond =
|
||||
|
|
@ -289,10 +286,10 @@ fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) {
|
|||
}
|
||||
}
|
||||
|
||||
fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [ty::mode],
|
||||
fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [mode],
|
||||
operands: [@expr]) {
|
||||
let i = 0u;
|
||||
for mode: ty::mode in modes {
|
||||
for mode: mode in modes {
|
||||
if mode == by_move {
|
||||
forget_in_postcond(fcx, parent.id, operands[i].id);
|
||||
}
|
||||
|
|
@ -571,8 +568,8 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||
/* LHS always becomes initialized,
|
||||
whether or not this is a move */
|
||||
find_pre_post_expr(fcx, an_init.expr);
|
||||
pat_bindings(alocal.node.pat) {|p|
|
||||
copy_pre_post(fcx.ccx, p.id, an_init.expr);
|
||||
pat_bindings(alocal.node.pat) {|p_id, _s, _n|
|
||||
copy_pre_post(fcx.ccx, p_id, an_init.expr);
|
||||
};
|
||||
/* Inherit ann from initializer, and add var being
|
||||
initialized to the postcondition */
|
||||
|
|
@ -585,16 +582,12 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||
}
|
||||
|
||||
pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
|
||||
{|pat|
|
||||
/* FIXME: This won't be necessary when typestate
|
||||
works well enough for pat_bindings to return a
|
||||
refinement-typed thing. */
|
||||
let ident = alt pat.node
|
||||
{ pat_ident(n, _) { path_to_ident(n) } };
|
||||
{|p_id, _s, n|
|
||||
let ident = path_to_ident(n);
|
||||
alt p {
|
||||
some(p) {
|
||||
copy_in_postcond(fcx, id,
|
||||
{ident: ident, node: pat.id},
|
||||
{ident: ident, node: p_id},
|
||||
{ident:
|
||||
path_to_ident(p),
|
||||
node: an_init.expr.id},
|
||||
|
|
@ -602,7 +595,7 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||
}
|
||||
none { }
|
||||
}
|
||||
gen(fcx, id, ninit(pat.id, ident));
|
||||
gen(fcx, id, ninit(p_id, ident));
|
||||
};
|
||||
|
||||
if an_init.op == init_move && is_path(an_init.expr) {
|
||||
|
|
@ -617,22 +610,16 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||
/* Include the LHSs too, since those aren't in the
|
||||
postconds of the RHSs themselves */
|
||||
pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
|
||||
{|pat|
|
||||
// FIXME
|
||||
// Generalize this pattern? map_if_ident...
|
||||
alt pat.node {
|
||||
pat_ident(n, _) {
|
||||
{|pat_id, _s, n|
|
||||
set_in_postcond(bit_num(fcx,
|
||||
ninit(pat.id, path_to_ident(n))), prev_pp);
|
||||
}
|
||||
}
|
||||
};
|
||||
ninit(pat_id, path_to_ident(n))), prev_pp);
|
||||
};
|
||||
copy_pre_post_(fcx.ccx, id, prev_pp.precondition,
|
||||
prev_pp.postcondition);
|
||||
}
|
||||
none {
|
||||
pat_bindings(alocal.node.pat) {|p|
|
||||
clear_pp(node_id_to_ts_ann(fcx.ccx, p.id).conditions);
|
||||
pat_bindings(alocal.node.pat) {|p_id, _s, _n|
|
||||
clear_pp(node_id_to_ts_ann(fcx.ccx, p_id).conditions);
|
||||
};
|
||||
clear_pp(node_id_to_ts_ann(fcx.ccx, id).conditions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,6 +215,8 @@ fn find_pre_post_state_exprs(fcx: fn_ctxt, pres: prestate, id: node_id,
|
|||
|
||||
fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
|
||||
index: @expr, body: blk, id: node_id) -> bool {
|
||||
// I'm confused about this -- how does the poststate for the body
|
||||
// ever grow larger? It seems like it can't?
|
||||
let loop_pres = intersect_states(pres, block_poststate(fcx.ccx, body));
|
||||
|
||||
let changed =
|
||||
|
|
@ -224,10 +226,9 @@ fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
|
|||
// Make sure the index vars are considered initialized
|
||||
// in the body
|
||||
let index_post = tritv_clone(expr_poststate(fcx.ccx, index));
|
||||
pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
|
||||
let ident = alt p.node
|
||||
{ pat_ident(name, _) { path_to_ident(name) } };
|
||||
set_in_poststate_ident(fcx, p.id, ident, index_post);
|
||||
pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat))
|
||||
{|p_id, _s, n|
|
||||
set_in_poststate_ident(fcx, p_id, path_to_ident(n), index_post);
|
||||
};
|
||||
|
||||
changed |= find_pre_post_state_block(fcx, index_post, body);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export fold_ty;
|
|||
export field;
|
||||
export field_idx;
|
||||
export get_field;
|
||||
export get_fields;
|
||||
export fm_general;
|
||||
export get_element_type;
|
||||
export idx_nil;
|
||||
|
|
@ -84,7 +85,6 @@ export mk_var;
|
|||
export mk_opaque_closure_ptr;
|
||||
export mk_named;
|
||||
export gen_ty;
|
||||
export mode;
|
||||
export mt;
|
||||
export node_type_table;
|
||||
export pat_ty;
|
||||
|
|
@ -125,7 +125,6 @@ export ty_ptr;
|
|||
export ty_rec;
|
||||
export ty_enum;
|
||||
export ty_tup;
|
||||
export ty_type;
|
||||
export ty_send_type;
|
||||
export ty_uint;
|
||||
export ty_uniq;
|
||||
|
|
@ -177,7 +176,6 @@ export variant_info;
|
|||
export walk_ty;
|
||||
export occurs_check_fails;
|
||||
export closure_kind;
|
||||
export ck_any;
|
||||
export ck_block;
|
||||
export ck_box;
|
||||
export ck_uniq;
|
||||
|
|
@ -186,7 +184,10 @@ export param_bounds_to_kind;
|
|||
|
||||
// Data types
|
||||
|
||||
type arg = {mode: mode, ty: t};
|
||||
// TODO: really should be a separate type, or a refinement,
|
||||
// so that we don't have to handle the mode_infer case after
|
||||
// typeck. but that's too hard right now.
|
||||
type arg = {mode: ast::mode, ty: t};
|
||||
|
||||
type field = {ident: ast::ident, mt: mt};
|
||||
|
||||
|
|
@ -232,7 +233,6 @@ type raw_t = {struct: sty,
|
|||
type t = uint;
|
||||
|
||||
enum closure_kind {
|
||||
ck_any,
|
||||
ck_block,
|
||||
ck_box,
|
||||
ck_uniq,
|
||||
|
|
@ -458,7 +458,7 @@ fn mk_raw_ty(cx: ctxt, st: sty) -> @raw_t {
|
|||
}
|
||||
alt st {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
|
||||
ty_str | ty_send_type | ty_type | ty_native(_) |
|
||||
ty_str | ty_type | ty_send_type | ty_native(_) |
|
||||
ty_opaque_closure_ptr(_) {
|
||||
/* no-op */
|
||||
}
|
||||
|
|
@ -629,7 +629,7 @@ pure fn struct_raw(cx: ctxt, typ: t) -> sty {
|
|||
interner::get(*cx.ts, typ).struct
|
||||
}
|
||||
|
||||
// Returns struact(cx, typ) but replaces all occurences of platform
|
||||
// Returns struct(cx, typ) but replaces all occurences of platform
|
||||
// dependent primitive types with their machine type equivalent
|
||||
pure fn mach_struct(cx: ctxt, cfg: @session::config, typ: t) -> sty {
|
||||
alt interner::get(*cx.ts, typ).struct {
|
||||
|
|
@ -678,6 +678,9 @@ fn walk_ty(cx: ctxt, ty: t, f: fn(t)) {
|
|||
}
|
||||
ty_constr(sub, _) { walk_ty(cx, sub, f); }
|
||||
ty_uniq(tm) { walk_ty(cx, tm.ty, f); }
|
||||
// precondition?
|
||||
ty_named(_,_) { cx.sess.bug("walk_ty: should not see a ty_named \
|
||||
here"); }
|
||||
}
|
||||
f(ty);
|
||||
}
|
||||
|
|
@ -699,7 +702,7 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
|
|||
}
|
||||
alt interner::get(*cx.ts, ty).struct {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_str | ty_send_type | ty_type | ty_native(_) |
|
||||
ty_str | ty_type | ty_send_type | ty_native(_) |
|
||||
ty_opaque_closure_ptr(_) {
|
||||
/* no-op */
|
||||
}
|
||||
|
|
@ -1033,6 +1036,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
|
|||
param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
|
||||
}
|
||||
ty_constr(t, _) { type_kind(cx, t) }
|
||||
_ { cx.sess.bug("Bad type in type_kind"); }
|
||||
};
|
||||
|
||||
cx.kind_cache.insert(ty, result);
|
||||
|
|
@ -1192,9 +1196,14 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
|
|||
}
|
||||
ty_constr(subt, _) { result = type_is_pod(cx, subt); }
|
||||
ty_var(_) {
|
||||
fail "ty_var in type_is_pod";
|
||||
cx.sess.bug("ty_var in type_is_pod");
|
||||
}
|
||||
ty_param(_, _) { result = false; }
|
||||
ty_opaque_closure_ptr(_) { result = true; }
|
||||
ty_named(_,_) {
|
||||
cx.sess.bug("ty_named in type_is_pod");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret result;
|
||||
|
|
@ -1577,12 +1586,17 @@ fn field_idx(id: ast::ident, fields: [field]) -> option::t<uint> {
|
|||
}
|
||||
|
||||
fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
|
||||
alt vec::find(get_fields(tcx, rec_ty), {|f| str::eq(f.ident, id) }) {
|
||||
some(f) { ret f; }
|
||||
_ { tcx.sess.bug(#fmt("get_field: bad field id %s", id)); }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: could have a precondition instead of failing
|
||||
fn get_fields(tcx:ctxt, rec_ty:t) -> [field] {
|
||||
alt struct(tcx, rec_ty) {
|
||||
ty_rec(fields) {
|
||||
alt vec::find(fields, {|f| str::eq(f.ident, id) }) {
|
||||
some(f) { ret f; }
|
||||
}
|
||||
}
|
||||
ty::ty_rec(fields) { fields }
|
||||
_ { tcx.sess.bug("get_fields called on non-record type"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1669,6 +1683,8 @@ mod unify {
|
|||
variance: variance) -> union_result {
|
||||
let vb = alt cx.st {
|
||||
in_bindings(vb) { vb }
|
||||
_ { cx.tcx.sess.bug("Someone forgot to document an invariant \
|
||||
in union"); }
|
||||
};
|
||||
ufind::grow(vb.sets, math::max(set_a, set_b) + 1u);
|
||||
let root_a = ufind::find(vb.sets, set_a);
|
||||
|
|
@ -1719,7 +1735,10 @@ mod unify {
|
|||
fn record_var_binding(
|
||||
cx: @ctxt, key: int, typ: t, variance: variance) -> result {
|
||||
|
||||
let vb = alt cx.st { in_bindings(vb) { vb } };
|
||||
let vb = alt cx.st { in_bindings(vb) { vb }
|
||||
_ { cx.tcx.sess.bug("Someone forgot to document an invariant \
|
||||
in record_var_binding"); }
|
||||
};
|
||||
ufind::grow(vb.sets, (key as uint) + 1u);
|
||||
let root = ufind::find(vb.sets, key as uint);
|
||||
let result_type = typ;
|
||||
|
|
@ -2060,7 +2079,7 @@ mod unify {
|
|||
ret ures_ok(actual);
|
||||
}
|
||||
ty::ty_bool | ty::ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty::ty_str | ty::ty_type | ty::ty_send_type {
|
||||
ty::ty_str | ty::ty_send_type {
|
||||
ret struct_cmp(cx, expected, actual);
|
||||
}
|
||||
ty::ty_native(ex_id) {
|
||||
|
|
@ -2333,6 +2352,7 @@ mod unify {
|
|||
}
|
||||
}
|
||||
}
|
||||
_ { cx.tcx.sess.bug("unify: unexpected type"); }
|
||||
}
|
||||
}
|
||||
fn unify(expected: t, actual: t, st: unify_style,
|
||||
|
|
@ -2497,6 +2517,7 @@ fn def_has_ty_params(def: ast::def) -> bool {
|
|||
ast::def_ty_param(_, _) | ast::def_binding(_) | ast::def_use(_) |
|
||||
ast::def_native_ty(_) | ast::def_self(_) | ast::def_ty(_) { false }
|
||||
ast::def_fn(_, _) | ast::def_variant(_, _) { true }
|
||||
_ { false } // ????
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2552,6 +2573,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
|
|||
// FIXME: issue #1417
|
||||
disr_val = alt syntax::ast_util::eval_const_expr(ex) {
|
||||
ast_util::const_int(val) {val as int}
|
||||
_ { cx.sess.bug("tag_variants: bad disr expr"); }
|
||||
}
|
||||
}
|
||||
_ {disr_val += 1;}
|
||||
|
|
@ -2564,6 +2586,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
|
|||
}
|
||||
})
|
||||
}
|
||||
_ { cx.sess.bug("tag_variants: id not bound to an enum"); }
|
||||
}
|
||||
};
|
||||
cx.enum_var_cache.insert(id, result);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
|
|||
some(self_impl(impl_t)) {
|
||||
ret {bounds: @[], ty: impl_t};
|
||||
}
|
||||
none {
|
||||
fcx.ccx.tcx.sess.span_bug(sp, "def_self with no self_info");
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::def_fn(id, _) | ast::def_const(id) |
|
||||
|
|
@ -248,16 +251,14 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
|||
some(ast_map::node_native_item(native_item)) {
|
||||
ty_of_native_item(tcx, mode, native_item)
|
||||
}
|
||||
_ {
|
||||
tcx.sess.bug("Unexpected sort of item in ast_ty_to_ty");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn ast_arg_to_arg(tcx: ty::ctxt, mode: mode, arg: ast::arg)
|
||||
-> {mode: ty::mode, ty: ty::t} {
|
||||
let ty = ast_ty_to_ty(tcx, mode, arg.ty);
|
||||
ret {mode: default_arg_mode_for_ty(tcx, arg.mode, ty), ty: ty};
|
||||
}
|
||||
alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
|
||||
some(some(ty)) { ret ty; }
|
||||
some(none) {
|
||||
|
|
@ -364,6 +365,10 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
|||
"found `ty_infer` in unexpected place"); }
|
||||
}
|
||||
}
|
||||
ast::ty_mac(_) {
|
||||
tcx.sess.span_bug(ast_ty.span,
|
||||
"found `ty_mac` in unexpected place");
|
||||
}
|
||||
}
|
||||
tcx.ast_ty_to_ty_cache.insert(ast_ty, some(typ));
|
||||
ret typ;
|
||||
|
|
@ -587,7 +592,13 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
|
|||
tcx.sess.span_err(sp, "method `" + if_m.ident +
|
||||
"` has an incompatible set of type parameters");
|
||||
} else {
|
||||
let impl_fty = ty::mk_fn(tcx, impl_m.fty);
|
||||
let auto_modes = vec::map2(impl_m.fty.inputs, if_m.fty.inputs, {|i, f|
|
||||
alt ty::struct(tcx, f.ty) {
|
||||
ty::ty_param(0u, _) { {mode: ast::by_ref with i} }
|
||||
_ { i }
|
||||
}
|
||||
});
|
||||
let impl_fty = ty::mk_fn(tcx, {inputs: auto_modes with impl_m.fty});
|
||||
// Add dummy substs for the parameters of the impl method
|
||||
let substs = substs + vec::init_fn(vec::len(*if_m.tps), {|i|
|
||||
ty::mk_param(tcx, i + impl_tps, {crate: 0, node: 0})
|
||||
|
|
@ -1209,7 +1220,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
|
|||
// Typecheck the path.
|
||||
let v_def = lookup_def(fcx, path.span, pat.id);
|
||||
let v_def_ids = ast_util::variant_def_ids(v_def);
|
||||
let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.tg);
|
||||
let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
|
||||
instantiate_path(fcx, path, ctor_tpt, pat.span, pat.id);
|
||||
|
||||
// Take the enum type params out of `expected`.
|
||||
|
|
@ -1422,6 +1433,9 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
|
|||
_}) {
|
||||
{n_tps: vec::len(ts), ty: ast_ty_to_ty(tcx, m_check, st)}
|
||||
}
|
||||
an_item {
|
||||
tcx.sess.bug("Undocumented invariant in impl_self_ty");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let tpt = csearch::get_type(tcx, did);
|
||||
|
|
@ -1444,6 +1458,10 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
|
|||
ty::bound_iface(t) {
|
||||
let (iid, tps) = alt ty::struct(tcx, t) {
|
||||
ty::ty_iface(i, tps) { (i, tps) }
|
||||
_ {
|
||||
tcx.sess.span_bug(sp, "Undocument invariant in \
|
||||
lookup_method");
|
||||
}
|
||||
};
|
||||
let ifce_methods = ty::iface_methods(tcx, iid);
|
||||
alt vec::position_pred(*ifce_methods, {|m| m.ident == name}) {
|
||||
|
|
@ -1485,6 +1503,9 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
|
|||
let mt = ty_of_method(tcx, m_check, m);
|
||||
ty::mk_fn(tcx, mt.fty)
|
||||
}
|
||||
_ {
|
||||
tcx.sess.bug("Undocumented invariant in ty_from_did");
|
||||
}
|
||||
}
|
||||
} else { csearch::get_type(tcx, did).ty }
|
||||
}
|
||||
|
|
@ -1793,7 +1814,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
|
||||
let rhs_bot = check_expr_with(fcx, rhs, lhs_t);
|
||||
if !ast_util::lazy_binop(binop) { bot |= rhs_bot; }
|
||||
|
||||
let result = check_binop(fcx, expr, lhs_t, binop, rhs);
|
||||
write_ty(tcx, id, result);
|
||||
}
|
||||
|
|
@ -2335,6 +2355,8 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
|
|||
let id_map = pat_util::pat_id_map(fcx.ccx.tcx, local.node.pat);
|
||||
check_pat(fcx, id_map, local.node.pat, t);
|
||||
}
|
||||
_ { fcx.ccx.tcx.sess.span_bug(local.span, "Undocumented invariant \
|
||||
in check_decl_local"); }
|
||||
}
|
||||
ret bot;
|
||||
}
|
||||
|
|
@ -2697,7 +2719,7 @@ fn arg_is_argv_ty(tcx: ty::ctxt, a: ty::arg) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
|
||||
fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id, main_span: span) {
|
||||
let main_t = ty::node_id_to_type(tcx, main_id);
|
||||
alt ty::struct(tcx, main_t) {
|
||||
ty::ty_fn({proto: ast::proto_bare, inputs, output,
|
||||
|
|
@ -2708,15 +2730,13 @@ fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
|
|||
ok &= num_args == 0u || num_args == 1u &&
|
||||
arg_is_argv_ty(tcx, inputs[0]);
|
||||
if !ok {
|
||||
let span = ast_map::node_span(tcx.items.get(main_id));
|
||||
tcx.sess.span_err(span,
|
||||
tcx.sess.span_err(main_span,
|
||||
"wrong type in main function: found `" +
|
||||
ty_to_str(tcx, main_t) + "`");
|
||||
}
|
||||
}
|
||||
_ {
|
||||
let span = ast_map::node_span(tcx.items.get(main_id));
|
||||
tcx.sess.span_bug(span,
|
||||
tcx.sess.span_bug(main_span,
|
||||
"main has a non-function type: found `" +
|
||||
ty_to_str(tcx, main_t) + "`");
|
||||
}
|
||||
|
|
@ -2726,7 +2746,7 @@ fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
|
|||
fn check_for_main_fn(tcx: ty::ctxt, crate: @ast::crate) {
|
||||
if !tcx.sess.building_library {
|
||||
alt tcx.sess.main_fn {
|
||||
some(id) { check_main_fn_ty(tcx, id); }
|
||||
some((id, sp)) { check_main_fn_ty(tcx, id, sp); }
|
||||
none { tcx.sess.span_err(crate.span, "main function not found"); }
|
||||
}
|
||||
}
|
||||
|
|
@ -2765,6 +2785,8 @@ mod dict {
|
|||
let tcx = fcx.ccx.tcx;
|
||||
let (iface_id, iface_tps) = alt ty::struct(tcx, iface_ty) {
|
||||
ty::ty_iface(did, tps) { (did, tps) }
|
||||
_ { tcx.sess.span_bug(sp, "Undocumented invariant in lookup\
|
||||
_dict"); }
|
||||
};
|
||||
let ty = fixup_ty(fcx, sp, ty);
|
||||
alt ty::struct(tcx, ty) {
|
||||
|
|
@ -2777,6 +2799,8 @@ mod dict {
|
|||
ty::ty_iface(idid, _) {
|
||||
if iface_id == idid { ret dict_param(n, n_bound); }
|
||||
}
|
||||
_ { tcx.sess.span_bug(sp, "Undocumented invariant in \
|
||||
lookup_dict"); }
|
||||
}
|
||||
n_bound += 1u;
|
||||
}
|
||||
|
|
@ -2796,6 +2820,9 @@ mod dict {
|
|||
some(ity) {
|
||||
alt ty::struct(tcx, ity) {
|
||||
ty::ty_iface(id, _) { id == iface_id }
|
||||
// Bleah, abstract this
|
||||
_ { tcx.sess.span_bug(sp, "Undocumented invariant \
|
||||
in lookup_dict"); }
|
||||
}
|
||||
}
|
||||
_ { false }
|
||||
|
|
@ -2862,6 +2889,10 @@ mod dict {
|
|||
vec::iter2(tps, iface_tys,
|
||||
{|a, b| demand::simple(fcx, sp, a, b);});
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_bug(sp, "Undocumented invariant in \
|
||||
connect_iface_tps");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -328,14 +328,10 @@ enum ty_ {
|
|||
ty_uniq(mt),
|
||||
ty_vec(mt),
|
||||
ty_ptr(mt),
|
||||
ty_task,
|
||||
ty_port(@ty),
|
||||
ty_chan(@ty),
|
||||
ty_rec([ty_field]),
|
||||
ty_fn(proto, fn_decl),
|
||||
ty_tup([@ty]),
|
||||
ty_path(@path, node_id),
|
||||
ty_type,
|
||||
ty_constr(@ty, [@ty_constr]),
|
||||
ty_mac(mac),
|
||||
// ty_infer means the type should be inferred instead of it having been
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
|
|||
|
||||
fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }
|
||||
|
||||
fn variant_def_ids(d: def) -> {tg: def_id, var: def_id} {
|
||||
alt d { def_variant(enum_id, var_id) { ret {tg: enum_id, var: var_id}; } }
|
||||
fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
|
||||
alt d { def_variant(enum_id, var_id) {
|
||||
ret {enm: enum_id, var: var_id}; }
|
||||
_ { fail "non-variant in variant_def_ids"; } }
|
||||
}
|
||||
|
||||
fn def_id_of_def(d: def) -> def_id {
|
||||
|
|
@ -77,6 +79,7 @@ fn is_path(e: @expr) -> bool {
|
|||
|
||||
fn int_ty_to_str(t: int_ty) -> str {
|
||||
alt t {
|
||||
ty_char { "u8" } // ???
|
||||
ty_i { "" } ty_i8 { "i8" } ty_i16 { "i16" }
|
||||
ty_i32 { "i32" } ty_i64 { "i64" }
|
||||
}
|
||||
|
|
@ -86,7 +89,7 @@ fn int_ty_max(t: int_ty) -> u64 {
|
|||
alt t {
|
||||
ty_i8 { 0x80u64 }
|
||||
ty_i16 { 0x800u64 }
|
||||
ty_char | ty_i32 { 0x80000000u64 }
|
||||
ty_i | ty_char | ty_i32 { 0x80000000u64 } // actually ni about ty_i
|
||||
ty_i64 { 0x8000000000000000u64 }
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +105,7 @@ fn uint_ty_max(t: uint_ty) -> u64 {
|
|||
alt t {
|
||||
ty_u8 { 0xffu64 }
|
||||
ty_u16 { 0xffffu64 }
|
||||
ty_u32 { 0xffffffffu64 }
|
||||
ty_u | ty_u32 { 0xffffffffu64 } // actually ni about ty_u
|
||||
ty_u64 { 0xffffffffffffffffu64 }
|
||||
}
|
||||
}
|
||||
|
|
@ -223,12 +226,14 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||
const_float(f) { const_float(-f) }
|
||||
const_int(i) { const_int(-i) }
|
||||
const_uint(i) { const_uint(-i) }
|
||||
_ { fail "eval_const_expr: bad neg argument"; }
|
||||
}
|
||||
}
|
||||
expr_unary(not, inner) {
|
||||
alt eval_const_expr(inner) {
|
||||
const_int(i) { const_int(!i) }
|
||||
const_uint(i) { const_uint(!i) }
|
||||
_ { fail "eval_const_expr: bad not argument"; }
|
||||
}
|
||||
}
|
||||
expr_binary(op, a, b) {
|
||||
|
|
@ -240,6 +245,7 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||
rem { const_float(a % b) } eq { fromb(a == b) }
|
||||
lt { fromb(a < b) } le { fromb(a <= b) } ne { fromb(a != b) }
|
||||
ge { fromb(a >= b) } gt { fromb(a > b) }
|
||||
_ { fail "eval_const_expr: can't apply this binop to floats"; }
|
||||
}
|
||||
}
|
||||
(const_int(a), const_int(b)) {
|
||||
|
|
@ -253,6 +259,7 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||
eq { fromb(a == b) } lt { fromb(a < b) }
|
||||
le { fromb(a <= b) } ne { fromb(a != b) }
|
||||
ge { fromb(a >= b) } gt { fromb(a > b) }
|
||||
_ { fail "eval_const_expr: can't apply this binop to ints"; }
|
||||
}
|
||||
}
|
||||
(const_uint(a), const_uint(b)) {
|
||||
|
|
@ -267,11 +274,17 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||
eq { fromb(a == b) } lt { fromb(a < b) }
|
||||
le { fromb(a <= b) } ne { fromb(a != b) }
|
||||
ge { fromb(a >= b) } gt { fromb(a > b) }
|
||||
_ { fail "eval_const_expr: can't apply this binop to uints"; }
|
||||
}
|
||||
}
|
||||
_ { fail "eval_constr_expr: bad binary arguments"; }
|
||||
}
|
||||
}
|
||||
expr_lit(lit) { lit_to_const(lit) }
|
||||
// Precondition?
|
||||
_ {
|
||||
fail "eval_const_expr: non-constant expression";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -324,6 +337,9 @@ fn compare_const_vals(a: const_val, b: const_val) -> int {
|
|||
1
|
||||
}
|
||||
}
|
||||
_ {
|
||||
fail "compare_const_vals: ill-typed comparison";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -341,6 +357,17 @@ fn ident_to_path(s: span, i: ident) -> @path {
|
|||
@respan(s, {global: false, idents: [i], types: []})
|
||||
}
|
||||
|
||||
pure fn is_unguarded(&&a: arm) -> bool {
|
||||
alt a.guard {
|
||||
none { true }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
pure fn unguarded_pat(a: arm) -> option::t<[@pat]> {
|
||||
if is_unguarded(a) { some(a.pats) } else { none }
|
||||
}
|
||||
|
||||
// Provides an extra node_id to hang callee information on, in case the
|
||||
// operator is deferred to a user-supplied method. The parser is responsible
|
||||
// for reserving this id.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import codemap::span;
|
|||
import core::{vec, option};
|
||||
import std::map::{hashmap, new_str_hash};
|
||||
import option::{some, none};
|
||||
import driver::session::session;
|
||||
|
||||
import base::{ext_ctxt, normal};
|
||||
|
||||
|
|
@ -460,11 +461,6 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: handle embedded types and blocks, at least */
|
||||
expr_mac(mac) {
|
||||
p_t_s_r_mac(cx, mac, s, b);
|
||||
|
|
@ -483,6 +479,9 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) {
|
|||
}
|
||||
}
|
||||
}
|
||||
_ {
|
||||
cx.session().bug("undocumented invariant in p_t_s_rec");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -718,6 +717,10 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: @expr,
|
|||
// FIXME: check duplicates (or just simplify
|
||||
// the macro arg situation)
|
||||
}
|
||||
_ {
|
||||
cx.span_bug(mac.span, "undocumented invariant in \
|
||||
add_extension");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ fn check_bad_word(p: parser) {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
|
||||
fn parse_ty_fn(p: parser) -> ast::fn_decl {
|
||||
fn parse_fn_input_ty(p: parser) -> ast::arg {
|
||||
let mode = parse_arg_mode(p);
|
||||
let name = if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
|
||||
|
|
@ -275,9 +275,9 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
|
|||
// auto constrs = parse_constrs(~[], p);
|
||||
let constrs: [@ast::constr] = [];
|
||||
let (ret_style, ret_ty) = parse_ret_ty(p);
|
||||
ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
|
||||
ret {inputs: inputs.node, output: ret_ty,
|
||||
purity: ast::impure_fn, cf: ret_style,
|
||||
constraints: constrs});
|
||||
constraints: constrs};
|
||||
}
|
||||
|
||||
fn parse_ty_methods(p: parser) -> [ast::ty_method] {
|
||||
|
|
@ -287,15 +287,10 @@ fn parse_ty_methods(p: parser) -> [ast::ty_method] {
|
|||
expect_word(p, "fn");
|
||||
let ident = parse_method_name(p);
|
||||
let tps = parse_ty_params(p);
|
||||
let f = parse_ty_fn(ast::proto_bare, p), fhi = p.last_span.hi;
|
||||
let d = parse_ty_fn(p), fhi = p.last_span.hi;
|
||||
expect(p, token::SEMI);
|
||||
alt f {
|
||||
ast::ty_fn(_, d) {
|
||||
{ident: ident, attrs: attrs, decl: d, tps: tps,
|
||||
span: ast_util::mk_sp(flo, fhi)}
|
||||
}
|
||||
}
|
||||
}, p).node
|
||||
span: ast_util::mk_sp(flo, fhi)}}, p).node
|
||||
}
|
||||
|
||||
fn parse_mt(p: parser) -> ast::mt {
|
||||
|
|
@ -506,10 +501,10 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
|
|||
ast::proto_bare { p.warn("fn is deprecated, use native fn"); }
|
||||
_ { /* fallthrough */ }
|
||||
}
|
||||
t = parse_ty_fn(proto, p);
|
||||
t = ast::ty_fn(proto, parse_ty_fn(p));
|
||||
} else if eat_word(p, "native") {
|
||||
expect_word(p, "fn");
|
||||
t = parse_ty_fn(ast::proto_bare, p);
|
||||
t = ast::ty_fn(ast::proto_bare, parse_ty_fn(p));
|
||||
} else if p.token == token::MOD_SEP || is_ident(p.token) {
|
||||
let path = parse_path(p);
|
||||
t = ast::ty_path(path, p.get_id());
|
||||
|
|
|
|||
|
|
@ -336,17 +336,6 @@ fn print_type(s: ps, &&ty: @ast::ty) {
|
|||
word(s.s, "]");
|
||||
}
|
||||
ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
|
||||
ast::ty_task { word(s.s, "task"); }
|
||||
ast::ty_port(t) {
|
||||
word(s.s, "port<");
|
||||
print_type(s, t);
|
||||
word(s.s, ">");
|
||||
}
|
||||
ast::ty_chan(t) {
|
||||
word(s.s, "chan<");
|
||||
print_type(s, t);
|
||||
word(s.s, ">");
|
||||
}
|
||||
ast::ty_rec(fields) {
|
||||
word(s.s, "{");
|
||||
fn print_field(s: ps, f: ast::ty_field) {
|
||||
|
|
@ -370,12 +359,18 @@ fn print_type(s: ps, &&ty: @ast::ty) {
|
|||
print_ty_fn(s, some(proto), d, none, none);
|
||||
}
|
||||
ast::ty_path(path, _) { print_path(s, path, false); }
|
||||
ast::ty_type { word(s.s, "type"); }
|
||||
ast::ty_constr(t, cs) {
|
||||
print_type(s, t);
|
||||
space(s.s);
|
||||
word(s.s, ast_ty_constrs_str(cs));
|
||||
}
|
||||
ast::ty_mac(_) {
|
||||
fail "print_type doesn't know how to print a ty_mac";
|
||||
}
|
||||
ast::ty_infer {
|
||||
fail "print_type shouldn't see a ty_infer";
|
||||
}
|
||||
|
||||
}
|
||||
end(s);
|
||||
}
|
||||
|
|
@ -703,11 +698,6 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
|
|||
alt els {
|
||||
some(_else) {
|
||||
alt _else.node {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// "another else-if"
|
||||
ast::expr_if(i, t, e) {
|
||||
cbox(s, indent_unit - 1u);
|
||||
|
|
@ -718,11 +708,6 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
|
|||
print_block(s, t);
|
||||
do_else(s, e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// "final else"
|
||||
ast::expr_block(b) {
|
||||
cbox(s, indent_unit - 1u);
|
||||
|
|
@ -730,6 +715,10 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
|
|||
word(s.s, " else ");
|
||||
print_block(s, b);
|
||||
}
|
||||
// BLEAH, constraints would be great here
|
||||
_ {
|
||||
fail "print_if saw if with weird alternative";
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {/* fall through */ }
|
||||
|
|
|
|||
|
|
@ -165,7 +165,6 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
|
|||
v.visit_ty(decl.output, e, v);
|
||||
}
|
||||
ty_path(p, _) { visit_path(p, e, v); }
|
||||
ty_type {/* no-op */ }
|
||||
ty_constr(t, cs) {
|
||||
v.visit_ty(t, e, v);
|
||||
for tc: @spanned<constr_general_<@path, node_id>> in cs {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import syntax::print::pprust::{path_to_str, constr_args_to_str, proto_to_str};
|
|||
import syntax::{ast, ast_util};
|
||||
import middle::ast_map;
|
||||
|
||||
fn mode_str(m: ty::mode) -> str {
|
||||
fn mode_str(m: ast::mode) -> str {
|
||||
alt m {
|
||||
ast::by_ref { "&&" }
|
||||
ast::by_val { "++" }
|
||||
|
|
@ -20,7 +20,7 @@ fn mode_str(m: ty::mode) -> str {
|
|||
}
|
||||
|
||||
fn ty_to_str(cx: ctxt, typ: t) -> str {
|
||||
fn fn_input_to_str(cx: ctxt, input: {mode: middle::ty::mode, ty: t}) ->
|
||||
fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
|
||||
str {
|
||||
let modestr = alt input.mode {
|
||||
ast::by_ref {
|
||||
|
|
|
|||
|
|
@ -87,12 +87,17 @@ Visit all pairs in the map in order.
|
|||
fn traverse<K, V: copy>(m: treemap<K, V>, f: fn(K, V)) {
|
||||
alt *m {
|
||||
empty { }
|
||||
node(@k, @v, _, _) {
|
||||
/*
|
||||
Previously, this had what looked like redundant
|
||||
matches to me, so I changed it. but that may be a
|
||||
de-optimization -- tjc
|
||||
*/
|
||||
node(@k, @v, left, right) {
|
||||
// copy v to make aliases work out
|
||||
let v1 = v;
|
||||
alt *m { node(_, _, left, _) { traverse(left, f); } }
|
||||
traverse(left, f);
|
||||
f(k, v1);
|
||||
alt *m { node(_, _, _, right) { traverse(right, f); } }
|
||||
traverse(right, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -398,7 +398,8 @@ mod tests {
|
|||
fn first_free_arg_should_be_a_filter() {
|
||||
let args = ["progname", "filter"];
|
||||
check (vec::is_not_empty(args));
|
||||
let opts = alt parse_opts(args) { either::left(o) { o } };
|
||||
let opts = alt parse_opts(args) { either::left(o) { o }
|
||||
_ { fail "Malformed arg in first_free_arg_should_be_a_filter"; } };
|
||||
assert (str::eq("filter", option::get(opts.filter)));
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +407,8 @@ mod tests {
|
|||
fn parse_ignored_flag() {
|
||||
let args = ["progname", "filter", "--ignored"];
|
||||
check (vec::is_not_empty(args));
|
||||
let opts = alt parse_opts(args) { either::left(o) { o } };
|
||||
let opts = alt parse_opts(args) { either::left(o) { o }
|
||||
_ { fail "Malformed arg in parse_ignored_flag"; } };
|
||||
assert (opts.run_ignored);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,14 +66,13 @@ Find a value based on the key
|
|||
fn find<K: copy, V: copy>(m: treemap<K, V>, k: K) -> option<V> {
|
||||
alt *m {
|
||||
empty { none }
|
||||
node(@kk, @v, _, _) {
|
||||
// TODO: was that an optimization?
|
||||
node(@kk, @v, left, right) {
|
||||
if k == kk {
|
||||
some(v)
|
||||
} else if k < kk {
|
||||
|
||||
// Again, ugliness to unpack left and right individually.
|
||||
alt *m { node(_, _, left, _) { find(left, k) } }
|
||||
} else { alt *m { node(_, _, _, right) { find(right, k) } } }
|
||||
find(left, k)
|
||||
} else { find(right, k) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,11 +85,16 @@ Visit all pairs in the map in order.
|
|||
fn traverse<K, V>(m: treemap<K, V>, f: fn(K, V)) {
|
||||
alt *m {
|
||||
empty { }
|
||||
node(k, v, _, _) {
|
||||
/*
|
||||
Previously, this had what looked like redundant
|
||||
matches to me, so I changed it. but that may be a
|
||||
de-optimization -- tjc
|
||||
*/
|
||||
node(k, v, left, right) {
|
||||
let k1 = k, v1 = v;
|
||||
alt *m { node(_, _, left, _) { traverse(left, f); } }
|
||||
traverse(left, f);
|
||||
f(*k1, *v1);
|
||||
alt *m { node(_, _, _, right) { traverse(right, f); } }
|
||||
traverse(right, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ fn test_connect() {
|
|||
connected(cd) {
|
||||
close_connection(thread, 0u32);
|
||||
}
|
||||
_ { fail "test_connect: port isn't connected"; }
|
||||
}
|
||||
join_thread(thread);
|
||||
delete_thread(thread);
|
||||
|
|
@ -156,12 +157,15 @@ fn test_http() {
|
|||
}
|
||||
delete_buf(buf);
|
||||
}
|
||||
_ { fail "test_http: protocol error"; }
|
||||
}
|
||||
}
|
||||
close_connection(thread, 0u32);
|
||||
}
|
||||
_ { fail "test_http: expected `wrote`"; }
|
||||
}
|
||||
}
|
||||
_ { fail "test_http: port not connected"; }
|
||||
}
|
||||
join_thread(thread);
|
||||
delete_thread(thread);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ fn parse_item_attrs<T>(
|
|||
astsrv::exec(srv) {|ctxt|
|
||||
let attrs = alt ctxt.ast_map.get(id) {
|
||||
ast_map::node_item(item) { item.attrs }
|
||||
_ {
|
||||
fail "parse_item_attrs: not an item";
|
||||
}
|
||||
};
|
||||
parse_attrs(attrs)
|
||||
}
|
||||
|
|
@ -277,6 +280,7 @@ fn fold_enum(
|
|||
|
||||
attr_parser::parse_variant(ast_variant.node.attrs)
|
||||
}
|
||||
_ { fail "fold_enum: undocumented invariant"; }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -363,7 +367,6 @@ fn fold_res_should_extract_arg_docs() {
|
|||
assert doc.args[0].desc == some("b");
|
||||
}
|
||||
|
||||
|
||||
fn fold_iface(
|
||||
fold: fold::fold<astsrv::srv>,
|
||||
doc: doc::ifacedoc
|
||||
|
|
@ -395,6 +398,9 @@ fn merge_method_attrs(
|
|||
(method.ident, attr_parser::parse_method(method.attrs))
|
||||
}
|
||||
}
|
||||
_ {
|
||||
fail "Undocumented invariant in merge_method_attrs";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -441,4 +447,4 @@ fn should_extract_iface_method_docs() {
|
|||
assert doc.topmod.ifaces()[0].methods[0].args[0].desc == some("a");
|
||||
assert doc.topmod.ifaces()[0].methods[0].return.desc == some("return");
|
||||
assert doc.topmod.ifaces()[0].methods[0].failure == some("failure");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,4 +43,4 @@ fn from_str_sess(sess: session::session, source: str) -> @ast::crate {
|
|||
|
||||
fn cfg(sess: session::session) -> ast::crate_cfg {
|
||||
driver::default_configuration(sess, "rustdoc", "<anon>")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,8 +111,12 @@ fn is_exported_from_mod(
|
|||
ast::item_mod(m) {
|
||||
ast_util::is_exported(item_name, m)
|
||||
}
|
||||
_ {
|
||||
fail "is_exported_from_mod: not a mod";
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { fail "is_exported_from_mod: not an item"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -243,4 +247,4 @@ fn should_prune_unexported_ifaces_from_top_mod() {
|
|||
let doc = extract::from_srv(srv, "");
|
||||
let doc = run(srv, doc);
|
||||
assert vec::is_empty(doc.topmod.ifaces());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ fn get_fn_sig(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
|
|||
}) {
|
||||
some(pprust::fun_to_str(decl, ident, []))
|
||||
}
|
||||
_ {
|
||||
fail "get_fn_sig: undocumented invariant";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -87,6 +90,7 @@ fn get_ret_ty(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
|
|||
}) {
|
||||
ret_ty_to_str(decl)
|
||||
}
|
||||
_ { fail "get_ret_ty: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -145,6 +149,9 @@ fn get_arg_tys(srv: astsrv::srv, fn_id: doc::ast_id) -> [(str, str)] {
|
|||
}) {
|
||||
decl_arg_tys(decl)
|
||||
}
|
||||
_ {
|
||||
fail "get_arg_tys: undocumented invariant";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -180,6 +187,9 @@ fn fold_const(
|
|||
}) {
|
||||
pprust::ty_to_str(ty)
|
||||
}
|
||||
_ {
|
||||
fail "fold_const: undocumented invariant";
|
||||
}
|
||||
}
|
||||
})
|
||||
with doc
|
||||
|
|
@ -215,6 +225,7 @@ fn fold_enum(
|
|||
|
||||
pprust::variant_to_str(ast_variant)
|
||||
}
|
||||
_ { fail "fold_enum: undocumented invariant"; }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -251,6 +262,7 @@ fn fold_res(
|
|||
}) {
|
||||
pprust::res_to_str(decl, doc.name, [])
|
||||
}
|
||||
_ { fail "fold_res: undocumented invariant"; }
|
||||
}
|
||||
})
|
||||
with doc
|
||||
|
|
@ -336,8 +348,10 @@ fn get_method_ret_ty(
|
|||
some(method) {
|
||||
ret_ty_to_str(method.decl)
|
||||
}
|
||||
_ { fail "get_method_ret_ty: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
_ { fail "get_method_ret_ty: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -358,8 +372,10 @@ fn get_method_sig(
|
|||
some(method) {
|
||||
some(pprust::fun_to_str(method.decl, method.ident, []))
|
||||
}
|
||||
_ { fail "get_method_ret_sig: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
_ { fail "get_method_ret_sig: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -396,8 +412,10 @@ fn get_method_arg_tys(
|
|||
some(method) {
|
||||
decl_arg_tys(method.decl)
|
||||
}
|
||||
_ { fail "get_method_arg_tys: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
_ { fail "get_method_arg_tys: undocumented invariant"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
src/test/compile-fail/non-exhaustive-match-nested.rs
Normal file
13
src/test/compile-fail/non-exhaustive-match-nested.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// -*- rust -*-
|
||||
// error-pattern: Non-exhaustive pattern
|
||||
enum t { a(u), b }
|
||||
enum u { c, d }
|
||||
|
||||
fn main() {
|
||||
let x = a(c);
|
||||
alt x {
|
||||
a(d) { fail "hello"; }
|
||||
b { fail "goodbye"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,9 +1,5 @@
|
|||
|
||||
|
||||
|
||||
// -*- rust -*-
|
||||
|
||||
// error-pattern:non-exhaustive match failure
|
||||
// error-pattern: Non-exhaustive pattern
|
||||
enum t { a, b, }
|
||||
|
||||
fn main() { let x = a; alt x { b { } } }
|
||||
|
|
@ -4,6 +4,6 @@ mod m1 {
|
|||
enum foo { foo1, foo2, }
|
||||
}
|
||||
|
||||
fn bar(x: m1::foo) { alt x { m1::foo1 { } } }
|
||||
fn bar(x: m1::foo) { alt x { m1::foo1 { } m1::foo2 { } } }
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue