librustc: Remove the concept of modes from the compiler.
This commit does not remove `ty::arg`, although that should be possible to do now.
This commit is contained in:
parent
a12a3db5b4
commit
f30f54e9d0
src
librustc
metadata
middle
util
libsyntax
@ -128,7 +128,6 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
|
||||
tag_table_freevars = 0x59,
|
||||
tag_table_tcache = 0x5a,
|
||||
tag_table_param_defs = 0x5b,
|
||||
tag_table_inferred_modes = 0x5c,
|
||||
tag_table_mutbl = 0x5d,
|
||||
tag_table_last_use = 0x5e,
|
||||
tag_table_spill = 0x5f,
|
||||
|
@ -244,8 +244,8 @@ fn doc_transformed_self_ty(doc: ebml::Doc,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_type(_item_id: ast::def_id, item: ebml::Doc,
|
||||
tcx: ty::ctxt, cdata: cmd) -> ty::t {
|
||||
pub fn item_type(_: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
|
||||
-> ty::t {
|
||||
doc_type(item, tcx, cdata)
|
||||
}
|
||||
|
||||
|
@ -469,16 +469,9 @@ fn parse_onceness(c: char) -> ast::Onceness {
|
||||
}
|
||||
|
||||
fn parse_arg(st: @mut PState, conv: conv_did) -> ty::arg {
|
||||
ty::arg { mode: parse_mode(st), ty: parse_ty(st, conv) }
|
||||
}
|
||||
|
||||
fn parse_mode(st: @mut PState) -> ast::mode {
|
||||
let m = ast::expl(match next(st) {
|
||||
'+' => ast::by_copy,
|
||||
'=' => ast::by_ref,
|
||||
_ => fail!(~"bad mode")
|
||||
});
|
||||
return m;
|
||||
ty::arg {
|
||||
ty: parse_ty(st, conv)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_closure_ty(st: @mut PState, conv: conv_did) -> ty::ClosureTy {
|
||||
@ -511,8 +504,7 @@ fn parse_sig(st: @mut PState, conv: conv_did) -> ty::FnSig {
|
||||
assert!((next(st) == '['));
|
||||
let mut inputs: ~[ty::arg] = ~[];
|
||||
while peek(st) != ']' {
|
||||
let mode = parse_mode(st);
|
||||
inputs.push(ty::arg { mode: mode, ty: parse_ty(st, conv) });
|
||||
inputs.push(ty::arg { ty: parse_ty(st, conv) });
|
||||
}
|
||||
st.pos += 1u; // eat the ']'
|
||||
let ret_ty = parse_ty(st, conv);
|
||||
|
@ -344,17 +344,9 @@ fn enc_sigil(w: @io::Writer, sigil: Sigil) {
|
||||
}
|
||||
|
||||
pub fn enc_arg(w: @io::Writer, cx: @ctxt, arg: ty::arg) {
|
||||
enc_mode(w, cx, arg.mode);
|
||||
enc_ty(w, cx, arg.ty);
|
||||
}
|
||||
|
||||
pub fn enc_mode(w: @io::Writer, cx: @ctxt, m: mode) {
|
||||
match ty::resolved_mode(cx.tcx, m) {
|
||||
by_copy => w.write_char('+'),
|
||||
by_ref => w.write_char('='),
|
||||
}
|
||||
}
|
||||
|
||||
fn enc_purity(w: @io::Writer, p: purity) {
|
||||
match p {
|
||||
pure_fn => w.write_char('p'),
|
||||
|
@ -410,7 +410,7 @@ impl tr for ast::def {
|
||||
ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
|
||||
ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) }
|
||||
ast::def_const(did) => { ast::def_const(did.tr(xcx)) }
|
||||
ast::def_arg(nid, m, b) => { ast::def_arg(xcx.tr_id(nid), m, b) }
|
||||
ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) }
|
||||
ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) }
|
||||
ast::def_variant(e_did, v_did) => {
|
||||
ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
|
||||
@ -571,6 +571,9 @@ fn encode_method_map_entry(ecx: @e::EncodeContext,
|
||||
do ebml_w.emit_field(~"origin", 1u) {
|
||||
mme.origin.encode(ebml_w);
|
||||
}
|
||||
do ebml_w.emit_field(~"self_mode", 3) {
|
||||
mme.self_mode.encode(ebml_w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,6 +593,9 @@ fn encode_method_map_entry(ecx: @e::EncodeContext,
|
||||
do ebml_w.emit_struct_field("origin", 1u) {
|
||||
mme.origin.encode(ebml_w);
|
||||
}
|
||||
do ebml_w.emit_struct_field("self_mode", 3) {
|
||||
mme.self_mode.encode(ebml_w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,6 +617,10 @@ impl read_method_map_entry_helper for reader::Decoder {
|
||||
Decodable::decode(self);
|
||||
method_origin.tr(xcx)
|
||||
}),
|
||||
self_mode: self.read_field(~"self_mode", 3, || {
|
||||
let self_mode: ty::SelfMode = Decodable::decode(self);
|
||||
self_mode
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -625,7 +635,7 @@ impl read_method_map_entry_helper for reader::Decoder {
|
||||
self_arg: self.read_struct_field("self_arg", 0u, || {
|
||||
self.read_arg(xcx)
|
||||
}),
|
||||
explicit_self: self.read_struct_field("explicit_self", 2u, || {
|
||||
explicit_self: self.read_struct_field("explicit_self", 2, || {
|
||||
let self_type: ast::self_ty_ = Decodable::decode(self);
|
||||
self_type
|
||||
}),
|
||||
@ -634,6 +644,10 @@ impl read_method_map_entry_helper for reader::Decoder {
|
||||
Decodable::decode(self);
|
||||
method_origin.tr(xcx)
|
||||
}),
|
||||
self_mode: self.read_struct_field("self_mode", 3, || {
|
||||
let self_mode: ty::SelfMode = Decodable::decode(self);
|
||||
self_mode
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -978,20 +992,6 @@ fn encode_side_tables_for_id(ecx: @e::EncodeContext,
|
||||
}
|
||||
}
|
||||
|
||||
// I believe it is not necessary to encode this information. The
|
||||
// ids will appear in the AST but in the *type* information, which
|
||||
// is what we actually use in trans, all modes will have been
|
||||
// resolved.
|
||||
//
|
||||
//for tcx.inferred_modes.find(&id).each |m| {
|
||||
// ebml_w.tag(c::tag_table_inferred_modes) {||
|
||||
// ebml_w.id(id);
|
||||
// ebml_w.tag(c::tag_table_val) {||
|
||||
// tyencode::enc_mode(ebml_w.writer, ty_str_ctxt(), m);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
if maps.mutbl_map.contains(&id) {
|
||||
do ebml_w.tag(c::tag_table_mutbl) {
|
||||
ebml_w.id(id);
|
||||
|
@ -147,38 +147,6 @@ fn req_loans_in_expr(ex: @ast::expr,
|
||||
visit::visit_expr(ex, self, vt);
|
||||
}
|
||||
|
||||
ast::expr_call(f, ref args, _) => {
|
||||
let arg_tys = ty::ty_fn_args(ty::expr_ty(self.tcx(), f));
|
||||
let scope_r = ty::re_scope(ex.id);
|
||||
for vec::each2(*args, arg_tys) |arg, arg_ty| {
|
||||
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
|
||||
ast::by_ref => {
|
||||
let arg_cmt = self.bccx.cat_expr(*arg);
|
||||
self.guarantee_valid(arg_cmt, m_imm, scope_r);
|
||||
}
|
||||
ast::by_copy => {}
|
||||
}
|
||||
}
|
||||
visit::visit_expr(ex, self, vt);
|
||||
}
|
||||
|
||||
ast::expr_method_call(_, _, _, ref args, _) => {
|
||||
let arg_tys = ty::ty_fn_args(ty::node_id_to_type(self.tcx(),
|
||||
ex.callee_id));
|
||||
let scope_r = ty::re_scope(ex.id);
|
||||
for vec::each2(*args, arg_tys) |arg, arg_ty| {
|
||||
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
|
||||
ast::by_ref => {
|
||||
let arg_cmt = self.bccx.cat_expr(*arg);
|
||||
self.guarantee_valid(arg_cmt, m_imm, scope_r);
|
||||
}
|
||||
ast::by_copy => {}
|
||||
}
|
||||
}
|
||||
|
||||
visit::visit_expr(ex, self, vt);
|
||||
}
|
||||
|
||||
ast::expr_match(ex_v, ref arms) => {
|
||||
let cmt = self.bccx.cat_expr(ex_v);
|
||||
for (*arms).each |arm| {
|
||||
|
@ -19,7 +19,6 @@ use std::smallintmap::SmallIntMap;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::span;
|
||||
use syntax::codemap;
|
||||
use syntax::print::pprust::mode_to_str;
|
||||
use syntax::{ast, visit};
|
||||
|
||||
/**
|
||||
@ -53,7 +52,6 @@ pub enum lint {
|
||||
unrecognized_lint,
|
||||
non_implicitly_copyable_typarams,
|
||||
vecs_implicitly_copyable,
|
||||
deprecated_mode,
|
||||
deprecated_pattern,
|
||||
non_camel_case_types,
|
||||
type_limits,
|
||||
@ -61,14 +59,11 @@ pub enum lint {
|
||||
deprecated_mutable_fields,
|
||||
deprecated_drop,
|
||||
unused_unsafe,
|
||||
foreign_mode,
|
||||
|
||||
managed_heap_memory,
|
||||
owned_heap_memory,
|
||||
heap_memory,
|
||||
|
||||
legacy_modes,
|
||||
|
||||
unused_variable,
|
||||
dead_assignment,
|
||||
unused_mut,
|
||||
@ -159,20 +154,6 @@ pub fn get_lint_dict() -> LintDict {
|
||||
default: warn
|
||||
}),
|
||||
|
||||
(~"deprecated_mode",
|
||||
LintSpec {
|
||||
lint: deprecated_mode,
|
||||
desc: "warn about deprecated uses of modes",
|
||||
default: warn
|
||||
}),
|
||||
|
||||
(~"foreign_mode",
|
||||
LintSpec {
|
||||
lint: foreign_mode,
|
||||
desc: "warn about deprecated uses of modes in foreign fns",
|
||||
default: warn
|
||||
}),
|
||||
|
||||
(~"deprecated_pattern",
|
||||
LintSpec {
|
||||
lint: deprecated_pattern,
|
||||
@ -208,13 +189,6 @@ pub fn get_lint_dict() -> LintDict {
|
||||
default: allow
|
||||
}),
|
||||
|
||||
(~"legacy modes",
|
||||
LintSpec {
|
||||
lint: legacy_modes,
|
||||
desc: "allow legacy modes",
|
||||
default: forbid
|
||||
}),
|
||||
|
||||
(~"type_limits",
|
||||
LintSpec {
|
||||
lint: type_limits,
|
||||
@ -486,7 +460,6 @@ fn check_item(i: @ast::item, cx: ty::ctxt) {
|
||||
check_item_path_statement(cx, i);
|
||||
check_item_non_camel_case_types(cx, i);
|
||||
check_item_heap(cx, i);
|
||||
check_item_deprecated_modes(cx, i);
|
||||
check_item_type_limits(cx, i);
|
||||
check_item_default_methods(cx, i);
|
||||
check_item_deprecated_mutable_fields(cx, i);
|
||||
@ -719,20 +692,6 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
|
||||
|
||||
fn check_foreign_fn(cx: ty::ctxt, fn_id: ast::node_id,
|
||||
decl: &ast::fn_decl) {
|
||||
// warn about `&&` mode on foreign functions, both because it is
|
||||
// deprecated and because its semantics have changed recently:
|
||||
for decl.inputs.eachi |i, arg| {
|
||||
match ty::resolved_mode(cx, arg.mode) {
|
||||
ast::by_copy => {}
|
||||
ast::by_ref => {
|
||||
cx.sess.span_lint(
|
||||
foreign_mode, fn_id, fn_id, arg.ty.span,
|
||||
fmt!("foreign function uses `&&` mode \
|
||||
on argument %u", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tys = vec::map(decl.inputs, |a| a.ty );
|
||||
for vec::each(vec::append_one(tys, decl.output)) |ty| {
|
||||
match ty.node {
|
||||
@ -995,119 +954,13 @@ fn check_item_unused_mut(tcx: ty::ctxt, it: @ast::item) {
|
||||
visit::visit_item(it, (), visit);
|
||||
}
|
||||
|
||||
fn check_fn(tcx: ty::ctxt, fk: &visit::fn_kind, decl: &ast::fn_decl,
|
||||
_body: &ast::blk, span: span, id: ast::node_id) {
|
||||
fn check_fn(_: ty::ctxt,
|
||||
fk: &visit::fn_kind,
|
||||
_: &ast::fn_decl,
|
||||
_: &ast::blk,
|
||||
_: span,
|
||||
id: ast::node_id) {
|
||||
debug!("lint check_fn fk=%? id=%?", fk, id);
|
||||
|
||||
// Check for deprecated modes
|
||||
match *fk {
|
||||
// don't complain about blocks, since they tend to get their modes
|
||||
// specified from the outside
|
||||
visit::fk_fn_block(*) => {}
|
||||
|
||||
_ => {
|
||||
let fn_ty = ty::node_id_to_type(tcx, id);
|
||||
check_fn_deprecated_modes(tcx, fn_ty, decl, span, id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: &ast::fn_decl,
|
||||
span: span, id: ast::node_id) {
|
||||
match ty::get(fn_ty).sty {
|
||||
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) |
|
||||
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) => {
|
||||
let mut counter = 0;
|
||||
for vec::each2(sig.inputs, decl.inputs) |arg_ty, arg_ast| {
|
||||
counter += 1;
|
||||
debug!("arg %d, ty=%s, mode=%s",
|
||||
counter,
|
||||
ty_to_str(tcx, arg_ty.ty),
|
||||
mode_to_str(arg_ast.mode));
|
||||
match arg_ast.mode {
|
||||
ast::expl(ast::by_copy) => {
|
||||
if !tcx.legacy_modes {
|
||||
tcx.sess.span_lint(
|
||||
deprecated_mode, id, id, span,
|
||||
fmt!("argument %d uses by-copy mode",
|
||||
counter));
|
||||
}
|
||||
}
|
||||
|
||||
ast::expl(_) => {
|
||||
tcx.sess.span_lint(
|
||||
deprecated_mode, id, id,
|
||||
span,
|
||||
fmt!("argument %d uses an explicit mode", counter));
|
||||
}
|
||||
|
||||
ast::infer(_) => {
|
||||
if tcx.legacy_modes {
|
||||
let kind = ty::type_contents(tcx, arg_ty.ty);
|
||||
if !kind.is_safe_for_default_mode(tcx) {
|
||||
tcx.sess.span_lint(
|
||||
deprecated_mode, id, id,
|
||||
span,
|
||||
fmt!("argument %d uses the default mode \
|
||||
but shouldn't",
|
||||
counter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match ty::get(arg_ty.ty).sty {
|
||||
ty::ty_closure(*) | ty::ty_bare_fn(*) => {
|
||||
let span = arg_ast.ty.span;
|
||||
// Recurse to check fn-type argument
|
||||
match arg_ast.ty.node {
|
||||
ast::ty_closure(@ast::TyClosure{decl: ref d, _}) |
|
||||
ast::ty_bare_fn(@ast::TyBareFn{decl: ref d, _})=>{
|
||||
check_fn_deprecated_modes(tcx, arg_ty.ty,
|
||||
d, span, id);
|
||||
}
|
||||
ast::ty_path(*) => {
|
||||
// This is probably a typedef, so we can't
|
||||
// see the actual fn decl
|
||||
// e.g. fn foo(f: InitOp<T>)
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_warn(span, ~"what");
|
||||
error!("arg %d, ty=%s, mode=%s",
|
||||
counter,
|
||||
ty_to_str(tcx, arg_ty.ty),
|
||||
mode_to_str(arg_ast.mode));
|
||||
error!("%?",arg_ast.ty.node);
|
||||
fail!()
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => tcx.sess.impossible_case(span, ~"check_fn: function has \
|
||||
non-fn type")
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) {
|
||||
match it.node {
|
||||
ast::item_ty(ty, _) => {
|
||||
match ty.node {
|
||||
ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) |
|
||||
ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
|
||||
let fn_ty = ty::node_id_to_type(tcx, it.id);
|
||||
check_fn_deprecated_modes(
|
||||
tcx, fn_ty, decl, ty.span, it.id)
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
|
||||
|
@ -236,19 +236,19 @@ struct LocalInfo {
|
||||
}
|
||||
|
||||
enum VarKind {
|
||||
Arg(node_id, ident, rmode),
|
||||
Arg(node_id, ident),
|
||||
Local(LocalInfo),
|
||||
ImplicitRet
|
||||
}
|
||||
|
||||
fn relevant_def(def: def) -> Option<node_id> {
|
||||
match def {
|
||||
def_binding(nid, _) |
|
||||
def_arg(nid, _, _) |
|
||||
def_local(nid, _) |
|
||||
def_self(nid, _) => Some(nid),
|
||||
def_binding(nid, _) |
|
||||
def_arg(nid, _) |
|
||||
def_local(nid, _) |
|
||||
def_self(nid, _) => Some(nid),
|
||||
|
||||
_ => None
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,10 +321,9 @@ pub impl IrMaps {
|
||||
self.num_vars += 1;
|
||||
|
||||
match vk {
|
||||
Local(LocalInfo {id:node_id, _}) |
|
||||
Arg(node_id, _, _) => {
|
||||
Local(LocalInfo { id: node_id, _ }) | Arg(node_id, _) => {
|
||||
self.variable_map.insert(node_id, v);
|
||||
}
|
||||
},
|
||||
ImplicitRet => {}
|
||||
}
|
||||
|
||||
@ -345,8 +344,9 @@ pub impl IrMaps {
|
||||
|
||||
fn variable_name(&mut self, var: Variable) -> @~str {
|
||||
match self.var_kinds[*var] {
|
||||
Local(LocalInfo {ident: nm, _}) |
|
||||
Arg(_, nm, _) => self.tcx.sess.str_of(nm),
|
||||
Local(LocalInfo { ident: nm, _ }) | Arg(_, nm) => {
|
||||
self.tcx.sess.str_of(nm)
|
||||
},
|
||||
ImplicitRet => @~"<implicit-ret>"
|
||||
}
|
||||
}
|
||||
@ -372,25 +372,22 @@ pub impl IrMaps {
|
||||
let vk = self.var_kinds[*var];
|
||||
debug!("Node %d is a last use of variable %?", expr_id, vk);
|
||||
match vk {
|
||||
Arg(id, _, by_copy) |
|
||||
Local(LocalInfo {id: id, kind: FromLetNoInitializer, _}) |
|
||||
Local(LocalInfo {id: id, kind: FromLetWithInitializer, _}) |
|
||||
Local(LocalInfo {id: id, kind: FromMatch(_), _}) => {
|
||||
let v = match self.last_use_map.find(&expr_id) {
|
||||
Some(&v) => v,
|
||||
None => {
|
||||
let v = @mut ~[];
|
||||
self.last_use_map.insert(expr_id, v);
|
||||
v
|
||||
}
|
||||
};
|
||||
Arg(id, _) |
|
||||
Local(LocalInfo { id: id, kind: FromLetNoInitializer, _ }) |
|
||||
Local(LocalInfo { id: id, kind: FromLetWithInitializer, _ }) |
|
||||
Local(LocalInfo { id: id, kind: FromMatch(_), _ }) => {
|
||||
let v = match self.last_use_map.find(&expr_id) {
|
||||
Some(&v) => v,
|
||||
None => {
|
||||
let v = @mut ~[];
|
||||
self.last_use_map.insert(expr_id, v);
|
||||
v
|
||||
}
|
||||
};
|
||||
|
||||
v.push(id);
|
||||
}
|
||||
Arg(_, _, by_ref) |
|
||||
ImplicitRet => {
|
||||
debug!("--but it is not owned");
|
||||
}
|
||||
v.push(id);
|
||||
}
|
||||
ImplicitRet => debug!("--but it is not owned"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -424,12 +421,11 @@ fn visit_fn(fk: &visit::fn_kind,
|
||||
}
|
||||
|
||||
for decl.inputs.each |arg| {
|
||||
let mode = ty::resolved_mode(self.tcx, arg.mode);
|
||||
do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
|
||||
|_bm, arg_id, _x, path| {
|
||||
debug!("adding argument %d", arg_id);
|
||||
let ident = ast_util::path_to_ident(path);
|
||||
fn_maps.add_variable(Arg(arg_id, ident, mode));
|
||||
fn_maps.add_variable(Arg(arg_id, ident));
|
||||
}
|
||||
};
|
||||
|
||||
@ -439,16 +435,13 @@ fn visit_fn(fk: &visit::fn_kind,
|
||||
match method.self_ty.node {
|
||||
sty_value | sty_region(*) | sty_box(_) | sty_uniq(_) => {
|
||||
fn_maps.add_variable(Arg(method.self_id,
|
||||
special_idents::self_,
|
||||
by_copy));
|
||||
special_idents::self_));
|
||||
}
|
||||
sty_static => {}
|
||||
}
|
||||
}
|
||||
fk_dtor(_, _, self_id, _) => {
|
||||
fn_maps.add_variable(Arg(self_id,
|
||||
special_idents::self_,
|
||||
by_copy));
|
||||
fn_maps.add_variable(Arg(self_id, special_idents::self_));
|
||||
}
|
||||
fk_item_fn(*) | fk_anon(*) | fk_fn_block(*) => {}
|
||||
}
|
||||
@ -973,30 +966,8 @@ pub impl Liveness {
|
||||
entry_ln
|
||||
}
|
||||
|
||||
fn propagate_through_fn_block(&self, decl: &fn_decl, blk: &blk)
|
||||
-> LiveNode {
|
||||
// inputs passed by & mode should be considered live on exit:
|
||||
for decl.inputs.each |arg| {
|
||||
match ty::resolved_mode(self.tcx, arg.mode) {
|
||||
by_ref => {
|
||||
// By val and by ref do not own, so register a
|
||||
// read at the end. This will prevent us from
|
||||
// moving out of such variables but also prevent
|
||||
// us from registering last uses and so forth.
|
||||
do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
|
||||
|_bm, arg_id, _sp, _path|
|
||||
{
|
||||
let var = self.variable(arg_id, blk.span);
|
||||
self.acc(self.s.exit_ln, var, ACC_READ);
|
||||
}
|
||||
}
|
||||
by_copy => {
|
||||
// By copy is an owned mode. If we don't use the
|
||||
// variable, nobody will.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate_through_fn_block(&self, _: &fn_decl, blk: &blk)
|
||||
-> LiveNode {
|
||||
// the fallthrough exit is only for those cases where we do not
|
||||
// explicitly return:
|
||||
self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln);
|
||||
@ -1771,7 +1742,7 @@ pub impl Liveness {
|
||||
// borrow checker
|
||||
let vk = self.ir.var_kinds[*var];
|
||||
match vk {
|
||||
Arg(_, name, _) => {
|
||||
Arg(_, name) => {
|
||||
self.tcx.sess.span_err(
|
||||
move_expr.span,
|
||||
fmt!("illegal move from argument `%s`, which is not \
|
||||
|
@ -482,17 +482,14 @@ pub impl mem_categorization_ctxt {
|
||||
}
|
||||
}
|
||||
|
||||
ast::def_arg(vid, mode, mutbl) => {
|
||||
ast::def_arg(vid, mutbl) => {
|
||||
// Idea: make this could be rewritten to model by-ref
|
||||
// stuff as `&const` and `&mut`?
|
||||
|
||||
// m: mutability of the argument
|
||||
// lp: loan path, must be none for aliasable things
|
||||
let m = if mutbl {McDeclared} else {McImmutable};
|
||||
let lp = match ty::resolved_mode(self.tcx, mode) {
|
||||
ast::by_copy => Some(@lp_arg(vid)),
|
||||
ast::by_ref => None,
|
||||
};
|
||||
let lp = Some(@lp_arg(vid));
|
||||
@cmt_ {
|
||||
id:id,
|
||||
span:span,
|
||||
|
@ -718,41 +718,22 @@ pub impl VisitContext {
|
||||
receiver_expr: @expr,
|
||||
visitor: vt<VisitContext>)
|
||||
{
|
||||
self.use_fn_arg(by_copy, receiver_expr, visitor);
|
||||
self.use_fn_arg(receiver_expr, visitor);
|
||||
}
|
||||
|
||||
fn use_fn_args(&self,
|
||||
callee_id: node_id,
|
||||
_: node_id,
|
||||
arg_exprs: &[@expr],
|
||||
visitor: vt<VisitContext>)
|
||||
{
|
||||
/*!
|
||||
*
|
||||
* Uses the argument expressions according to the function modes.
|
||||
*/
|
||||
|
||||
let arg_tys =
|
||||
ty::ty_fn_args(ty::node_id_to_type(self.tcx, callee_id));
|
||||
for vec::each2(arg_exprs, arg_tys) |arg_expr, arg_ty| {
|
||||
let arg_mode = ty::resolved_mode(self.tcx, arg_ty.mode);
|
||||
self.use_fn_arg(arg_mode, *arg_expr, visitor);
|
||||
visitor: vt<VisitContext>) {
|
||||
//! Uses the argument expressions.
|
||||
for arg_exprs.each |arg_expr| {
|
||||
self.use_fn_arg(*arg_expr, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
fn use_fn_arg(&self,
|
||||
arg_mode: rmode,
|
||||
arg_expr: @expr,
|
||||
visitor: vt<VisitContext>)
|
||||
{
|
||||
/*!
|
||||
*
|
||||
* Uses the argument according to the given argument mode.
|
||||
*/
|
||||
|
||||
match arg_mode {
|
||||
by_ref => self.use_expr(arg_expr, Read, visitor),
|
||||
by_copy => self.consume_expr(arg_expr, visitor)
|
||||
}
|
||||
fn use_fn_arg(&self, arg_expr: @expr, visitor: vt<VisitContext>) {
|
||||
//! Uses the argument.
|
||||
self.consume_expr(arg_expr, visitor)
|
||||
}
|
||||
|
||||
fn arms_have_by_move_bindings(&self,
|
||||
|
@ -42,7 +42,7 @@ use syntax::ast::Generics;
|
||||
use syntax::ast::{gt, ident, inherited, item, item_struct};
|
||||
use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod};
|
||||
use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le};
|
||||
use syntax::ast::{local, local_crate, lt, method, mode, mul};
|
||||
use syntax::ast::{local, local_crate, lt, method, mul};
|
||||
use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident};
|
||||
use syntax::ast::{Path, pat_lit, pat_range, pat_struct};
|
||||
use syntax::ast::{prim_ty, private, provided};
|
||||
@ -123,7 +123,7 @@ pub struct Export2 {
|
||||
pub enum PatternBindingMode {
|
||||
RefutableMode,
|
||||
LocalIrrefutableMode,
|
||||
ArgumentIrrefutableMode(mode)
|
||||
ArgumentIrrefutableMode,
|
||||
}
|
||||
|
||||
#[deriving(Eq)]
|
||||
@ -3708,8 +3708,7 @@ pub impl Resolver {
|
||||
}
|
||||
Some(declaration) => {
|
||||
for declaration.inputs.each |argument| {
|
||||
let binding_mode =
|
||||
ArgumentIrrefutableMode(argument.mode);
|
||||
let binding_mode = ArgumentIrrefutableMode;
|
||||
let mutability =
|
||||
if argument.is_mutbl {Mutable} else {Immutable};
|
||||
self.resolve_pattern(argument.pat,
|
||||
@ -4184,10 +4183,9 @@ pub impl Resolver {
|
||||
// But for locals, we use `def_local`.
|
||||
def_local(pattern.id, is_mutable)
|
||||
}
|
||||
ArgumentIrrefutableMode(argument_mode) => {
|
||||
ArgumentIrrefutableMode => {
|
||||
// And for function arguments, `def_arg`.
|
||||
def_arg(pattern.id, argument_mode,
|
||||
is_mutable)
|
||||
def_arg(pattern.id, is_mutable)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -33,11 +33,16 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
|
||||
constraints.push(copy *c);
|
||||
|
||||
let aoutty = ty::arg {
|
||||
mode: ast::expl(ast::by_copy),
|
||||
ty: expr_ty(bcx, out)
|
||||
};
|
||||
aoutputs.push(unpack_result!(bcx, {
|
||||
callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
|
||||
callee::trans_arg_expr(bcx,
|
||||
aoutty,
|
||||
ty::ByCopy,
|
||||
out,
|
||||
&mut cleanups,
|
||||
None,
|
||||
callee::DontAutorefArg)
|
||||
}));
|
||||
|
||||
let e = match out.node {
|
||||
@ -46,12 +51,17 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
|
||||
};
|
||||
|
||||
let outty = ty::arg {
|
||||
mode: ast::expl(ast::by_copy),
|
||||
ty: expr_ty(bcx, e)
|
||||
};
|
||||
|
||||
unpack_result!(bcx, {
|
||||
callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
|
||||
callee::trans_arg_expr(bcx,
|
||||
outty,
|
||||
ty::ByCopy,
|
||||
e,
|
||||
&mut cleanups,
|
||||
None,
|
||||
callee::DontAutorefArg)
|
||||
})
|
||||
|
||||
};
|
||||
@ -66,12 +76,17 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
|
||||
constraints.push(copy *c);
|
||||
|
||||
let inty = ty::arg {
|
||||
mode: ast::expl(ast::by_copy),
|
||||
ty: expr_ty(bcx, in)
|
||||
};
|
||||
|
||||
unpack_result!(bcx, {
|
||||
callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
|
||||
callee::trans_arg_expr(bcx,
|
||||
inty,
|
||||
ty::ByCopy,
|
||||
in,
|
||||
&mut cleanups,
|
||||
None,
|
||||
callee::DontAutorefArg)
|
||||
})
|
||||
|
||||
};
|
||||
|
@ -1728,7 +1728,6 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
||||
raw_llargs: &[ValueRef],
|
||||
arg_tys: &[ty::arg]) -> block {
|
||||
let _icx = fcx.insn_ctxt("copy_args_to_allocas");
|
||||
let tcx = bcx.tcx();
|
||||
let mut bcx = bcx;
|
||||
|
||||
match fcx.llself {
|
||||
@ -1757,24 +1756,16 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
||||
// the argument would be passed by value, we store it into an alloca.
|
||||
// This alloca should be optimized away by LLVM's mem-to-reg pass in
|
||||
// the event it's not truly needed.
|
||||
let llarg;
|
||||
match ty::resolved_mode(tcx, arg_ty.mode) {
|
||||
ast::by_ref => {
|
||||
llarg = raw_llarg;
|
||||
}
|
||||
ast::by_copy => {
|
||||
// only by value if immediate:
|
||||
if datum::appropriate_mode(arg_ty.ty).is_by_value() {
|
||||
let alloc = alloc_ty(bcx, arg_ty.ty);
|
||||
Store(bcx, raw_llarg, alloc);
|
||||
llarg = alloc;
|
||||
} else {
|
||||
llarg = raw_llarg;
|
||||
}
|
||||
// only by value if immediate:
|
||||
let llarg = if datum::appropriate_mode(arg_ty.ty).is_by_value() {
|
||||
let alloc = alloc_ty(bcx, arg_ty.ty);
|
||||
Store(bcx, raw_llarg, alloc);
|
||||
alloc
|
||||
} else {
|
||||
raw_llarg
|
||||
};
|
||||
|
||||
add_clean(bcx, llarg, arg_ty.ty);
|
||||
}
|
||||
}
|
||||
add_clean(bcx, llarg, arg_ty.ty);
|
||||
|
||||
bcx = _match::bind_irrefutable_pat(bcx,
|
||||
args[arg_n].pat,
|
||||
@ -1966,7 +1957,6 @@ pub fn trans_enum_variant(ccx: @CrateContext,
|
||||
// Translate variant arguments to function arguments.
|
||||
let fn_args = do args.map |varg| {
|
||||
ast::arg {
|
||||
mode: ast::expl(ast::by_copy),
|
||||
is_mutbl: false,
|
||||
ty: varg.ty,
|
||||
pat: ast_util::ident_to_pat(
|
||||
@ -2041,7 +2031,6 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
|
||||
// Translate struct fields to function arguments.
|
||||
let fn_args = do fields.map |field| {
|
||||
ast::arg {
|
||||
mode: ast::expl(ast::by_copy),
|
||||
is_mutbl: false,
|
||||
ty: field.node.ty,
|
||||
pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
|
||||
@ -2408,8 +2397,8 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
|
||||
} else {
|
||||
let start_fn_type = csearch::get_type(ccx.tcx,
|
||||
start_def_id).ty;
|
||||
trans_external_path(ccx, start_def_id, start_fn_type)
|
||||
};
|
||||
trans_external_path(ccx, start_def_id, start_fn_type);
|
||||
}
|
||||
|
||||
let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname());
|
||||
|
||||
|
@ -57,7 +57,7 @@ pub struct MethodData {
|
||||
llfn: ValueRef,
|
||||
llself: ValueRef,
|
||||
self_ty: ty::t,
|
||||
self_mode: ast::rmode
|
||||
self_mode: ty::SelfMode,
|
||||
}
|
||||
|
||||
pub enum CalleeData {
|
||||
@ -378,10 +378,20 @@ pub fn trans_lang_call(bcx: block,
|
||||
csearch::get_type(bcx.ccx().tcx, did).ty
|
||||
};
|
||||
let rty = ty::ty_fn_ret(fty);
|
||||
return callee::trans_call_inner(
|
||||
bcx, None, fty, rty,
|
||||
|bcx| trans_fn_ref_with_vtables_to_callee(bcx, did, 0, ~[], None),
|
||||
ArgVals(args), dest, DontAutorefArg);
|
||||
callee::trans_call_inner(bcx,
|
||||
None,
|
||||
fty,
|
||||
rty,
|
||||
|bcx| {
|
||||
trans_fn_ref_with_vtables_to_callee(bcx,
|
||||
did,
|
||||
0,
|
||||
~[],
|
||||
None)
|
||||
},
|
||||
ArgVals(args),
|
||||
dest,
|
||||
DontAutorefArg)
|
||||
}
|
||||
|
||||
pub fn trans_lang_call_with_type_params(bcx: block,
|
||||
@ -483,7 +493,8 @@ pub fn trans_call_inner(in_cx: block,
|
||||
}
|
||||
Method(d) => {
|
||||
// Weird but true: we pass self in the *environment* slot!
|
||||
let llself = PointerCast(bcx, d.llself,
|
||||
let llself = PointerCast(bcx,
|
||||
d.llself,
|
||||
T_opaque_box_ptr(ccx));
|
||||
(d.llfn, llself)
|
||||
}
|
||||
@ -520,7 +531,7 @@ pub fn trans_call_inner(in_cx: block,
|
||||
// Now that the arguments have finished evaluating, we need to revoke
|
||||
// the cleanup for the self argument, if it exists
|
||||
match callee.data {
|
||||
Method(d) if d.self_mode == ast::by_copy => {
|
||||
Method(d) if d.self_mode == ty::ByCopy => {
|
||||
revoke_clean(bcx, d.llself);
|
||||
}
|
||||
_ => {}
|
||||
@ -629,7 +640,11 @@ pub fn trans_args(cx: block,
|
||||
let last = arg_exprs.len() - 1u;
|
||||
for vec::eachi(arg_exprs) |i, arg_expr| {
|
||||
let arg_val = unpack_result!(bcx, {
|
||||
trans_arg_expr(bcx, arg_tys[i], *arg_expr, &mut temp_cleanups,
|
||||
trans_arg_expr(bcx,
|
||||
arg_tys[i],
|
||||
ty::ByCopy,
|
||||
*arg_expr,
|
||||
&mut temp_cleanups,
|
||||
if i == last { ret_flag } else { None },
|
||||
autoref_arg)
|
||||
});
|
||||
@ -660,6 +675,7 @@ pub enum AutorefArg {
|
||||
// call takes place:
|
||||
pub fn trans_arg_expr(bcx: block,
|
||||
formal_ty: ty::arg,
|
||||
self_mode: ty::SelfMode,
|
||||
arg_expr: @ast::expr,
|
||||
temp_cleanups: &mut ~[ValueRef],
|
||||
ret_flag: Option<ValueRef>,
|
||||
@ -667,10 +683,10 @@ pub fn trans_arg_expr(bcx: block,
|
||||
let _icx = bcx.insn_ctxt("trans_arg_expr");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
debug!("trans_arg_expr(formal_ty=(%?,%s), arg_expr=%s, \
|
||||
debug!("trans_arg_expr(formal_ty=(%s), self_mode=%?, arg_expr=%s, \
|
||||
ret_flag=%?)",
|
||||
formal_ty.mode,
|
||||
formal_ty.ty.repr(bcx.tcx()),
|
||||
self_mode,
|
||||
arg_expr.repr(bcx.tcx()),
|
||||
ret_flag.map(|v| bcx.val_str(*v)));
|
||||
let _indenter = indenter();
|
||||
@ -686,8 +702,7 @@ pub fn trans_arg_expr(bcx: block,
|
||||
blk @ @ast::expr {
|
||||
node: ast::expr_fn_block(ref decl, ref body),
|
||||
_
|
||||
}) =>
|
||||
{
|
||||
}) => {
|
||||
let scratch_ty = expr_ty(bcx, arg_expr);
|
||||
let scratch = alloc_ty(bcx, scratch_ty);
|
||||
let arg_ty = expr_ty(bcx, arg_expr);
|
||||
@ -714,8 +729,6 @@ pub fn trans_arg_expr(bcx: block,
|
||||
|
||||
debug!(" arg datum: %s", arg_datum.to_str(bcx.ccx()));
|
||||
|
||||
// finally, deal with the various modes
|
||||
let arg_mode = ty::resolved_mode(ccx.tcx, formal_ty.mode);
|
||||
let mut val;
|
||||
if ty::type_is_bot(arg_datum.ty) {
|
||||
// For values of type _|_, we generate an
|
||||
@ -735,24 +748,27 @@ pub fn trans_arg_expr(bcx: block,
|
||||
val = arg_datum.to_ref_llval(bcx);
|
||||
}
|
||||
DontAutorefArg => {
|
||||
match arg_mode {
|
||||
ast::by_ref => {
|
||||
match self_mode {
|
||||
ty::ByRef => {
|
||||
// This assertion should really be valid, but because
|
||||
// the explicit self code currently passes by-ref, it
|
||||
// does not hold.
|
||||
//
|
||||
//assert !bcx.ccx().maps.moves_map.contains_key(
|
||||
// &arg_expr.id);
|
||||
debug!("by ref arg with type %s",
|
||||
bcx.ty_to_str(arg_datum.ty));
|
||||
val = arg_datum.to_ref_llval(bcx);
|
||||
}
|
||||
|
||||
ast::by_copy => {
|
||||
ty::ByCopy => {
|
||||
debug!("by copy arg with type %s, storing to scratch",
|
||||
bcx.ty_to_str(arg_datum.ty));
|
||||
let scratch = scratch_datum(bcx, arg_datum.ty, false);
|
||||
|
||||
arg_datum.store_to_datum(bcx, arg_expr.id,
|
||||
INIT, scratch);
|
||||
arg_datum.store_to_datum(bcx,
|
||||
arg_expr.id,
|
||||
INIT,
|
||||
scratch);
|
||||
|
||||
// Technically, ownership of val passes to the callee.
|
||||
// However, we must cleanup should we fail before the
|
||||
@ -761,12 +777,8 @@ pub fn trans_arg_expr(bcx: block,
|
||||
temp_cleanups.push(scratch.val);
|
||||
|
||||
match arg_datum.appropriate_mode() {
|
||||
ByValue => {
|
||||
val = Load(bcx, scratch.val);
|
||||
}
|
||||
ByRef => {
|
||||
val = scratch.val;
|
||||
}
|
||||
ByValue => val = Load(bcx, scratch.val),
|
||||
ByRef => val = scratch.val,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -776,6 +788,10 @@ pub fn trans_arg_expr(bcx: block,
|
||||
if formal_ty.ty != arg_datum.ty {
|
||||
// this could happen due to e.g. subtyping
|
||||
let llformal_ty = type_of::type_of_explicit_arg(ccx, &formal_ty);
|
||||
let llformal_ty = match self_mode {
|
||||
ty::ByRef => T_ptr(llformal_ty),
|
||||
ty::ByCopy => llformal_ty,
|
||||
};
|
||||
debug!("casting actual type (%s) to match formal (%s)",
|
||||
bcx.val_str(val), bcx.llty_str(llformal_ty));
|
||||
val = PointerCast(bcx, val, llformal_ty);
|
||||
|
@ -1072,7 +1072,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::def_arg(nid, _, _) => {
|
||||
ast::def_arg(nid, _) => {
|
||||
take_local(bcx, bcx.fcx.llargs, nid)
|
||||
}
|
||||
ast::def_local(nid, _) | ast::def_binding(nid, _) => {
|
||||
|
@ -791,10 +791,11 @@ pub fn trans_intrinsic(ccx: @CrateContext,
|
||||
sigil: ast::BorrowedSigil,
|
||||
onceness: ast::Many,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[arg {mode: ast::expl(ast::by_copy),
|
||||
ty: star_u8}],
|
||||
output: ty::mk_nil()}
|
||||
sig: FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[ arg { ty: star_u8 } ],
|
||||
output: ty::mk_nil()
|
||||
}
|
||||
});
|
||||
let datum = Datum {val: get_param(decl, first_real_arg),
|
||||
mode: ByRef, ty: fty, source: ZeroMem};
|
||||
|
@ -145,14 +145,18 @@ pub fn trans_self_arg(bcx: block,
|
||||
let _icx = bcx.insn_ctxt("impl::trans_self_arg");
|
||||
let mut temp_cleanups = ~[];
|
||||
|
||||
// Compute the mode and type of self.
|
||||
// Compute the type of self.
|
||||
let self_arg = arg {
|
||||
mode: mentry.self_arg.mode,
|
||||
ty: monomorphize_type(bcx, mentry.self_arg.ty)
|
||||
};
|
||||
|
||||
let result = trans_arg_expr(bcx, self_arg, base,
|
||||
&mut temp_cleanups, None, DontAutorefArg);
|
||||
let result = trans_arg_expr(bcx,
|
||||
self_arg,
|
||||
mentry.self_mode,
|
||||
base,
|
||||
&mut temp_cleanups,
|
||||
None,
|
||||
DontAutorefArg);
|
||||
|
||||
// FIXME(#3446)---this is wrong, actually. The temp_cleanups
|
||||
// should be revoked only after all arguments have been passed.
|
||||
@ -224,14 +228,13 @@ pub fn trans_method_callee(bcx: block,
|
||||
typeck::method_static(did) => {
|
||||
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
|
||||
let Result {bcx, val} = trans_self_arg(bcx, self, mentry);
|
||||
let tcx = bcx.tcx();
|
||||
Callee {
|
||||
bcx: bcx,
|
||||
data: Method(MethodData {
|
||||
llfn: callee_fn.llfn,
|
||||
llself: val,
|
||||
self_ty: node_id_type(bcx, self.id),
|
||||
self_mode: ty::resolved_mode(tcx, mentry.self_arg.mode)
|
||||
self_mode: mentry.self_mode,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -442,7 +445,7 @@ pub fn trans_monomorphized_callee(bcx: block,
|
||||
trait_id: ast::def_id,
|
||||
n_method: uint,
|
||||
vtbl: typeck::vtable_origin)
|
||||
-> Callee {
|
||||
-> Callee {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_monomorphized_callee");
|
||||
return match vtbl {
|
||||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||
@ -463,8 +466,11 @@ pub fn trans_monomorphized_callee(bcx: block,
|
||||
bcx, mth_id, impl_did, callee_id, rcvr_origins);
|
||||
|
||||
// translate the function
|
||||
let callee = trans_fn_ref_with_vtables(
|
||||
bcx, mth_id, callee_id, callee_substs, Some(callee_origins));
|
||||
let callee = trans_fn_ref_with_vtables(bcx,
|
||||
mth_id,
|
||||
callee_id,
|
||||
callee_substs,
|
||||
Some(callee_origins));
|
||||
|
||||
// create a llvalue that represents the fn ptr
|
||||
let fn_ty = node_id_type(bcx, callee_id);
|
||||
@ -472,14 +478,13 @@ pub fn trans_monomorphized_callee(bcx: block,
|
||||
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
|
||||
|
||||
// combine the self environment with the rest
|
||||
let tcx = bcx.tcx();
|
||||
Callee {
|
||||
bcx: bcx,
|
||||
data: Method(MethodData {
|
||||
llfn: llfn_val,
|
||||
llself: llself_val,
|
||||
self_ty: node_id_type(bcx, base.id),
|
||||
self_mode: ty::resolved_mode(tcx, mentry.self_arg.mode)
|
||||
self_mode: mentry.self_mode,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -496,7 +501,7 @@ pub fn combine_impl_and_methods_tps(bcx: block,
|
||||
impl_did: ast::def_id,
|
||||
callee_id: ast::node_id,
|
||||
rcvr_substs: &[ty::t])
|
||||
-> ~[ty::t] {
|
||||
-> ~[ty::t] {
|
||||
/*!
|
||||
*
|
||||
* Creates a concatenated set of substitutions which includes
|
||||
@ -668,7 +673,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
||||
Store(bcx, llself, llscratch);
|
||||
llself = llscratch;
|
||||
|
||||
self_mode = ast::by_ref;
|
||||
self_mode = ty::ByRef;
|
||||
}
|
||||
ast::sty_box(_) => {
|
||||
// Bump the reference count on the box.
|
||||
@ -686,7 +691,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
||||
Store(bcx, llself, llscratch);
|
||||
llself = llscratch;
|
||||
|
||||
self_mode = ast::by_ref;
|
||||
self_mode = ty::ByRef;
|
||||
}
|
||||
ast::sty_uniq(_) => {
|
||||
// Pass the unique pointer.
|
||||
@ -699,7 +704,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
||||
Store(bcx, llself, llscratch);
|
||||
llself = llscratch;
|
||||
|
||||
self_mode = ast::by_ref;
|
||||
self_mode = ty::ByRef;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,9 +280,15 @@ pub impl Reflector {
|
||||
|
||||
let make_get_disr = || {
|
||||
let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)];
|
||||
let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr");
|
||||
let args = [ty::arg { mode: ast::expl(ast::by_copy),
|
||||
ty: opaqueptrty }];
|
||||
let sym = mangle_internal_name_by_path_and_seq(ccx,
|
||||
sub_path,
|
||||
~"get_disr");
|
||||
let args = [
|
||||
ty::arg {
|
||||
ty: opaqueptrty
|
||||
}
|
||||
];
|
||||
|
||||
let llfty = type_of_fn(ccx, args, ty::mk_int());
|
||||
let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
|
||||
let arg = unsafe {
|
||||
@ -347,13 +353,7 @@ pub impl Reflector {
|
||||
|
||||
fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) {
|
||||
for sig.inputs.eachi |i, arg| {
|
||||
let modeval = match arg.mode {
|
||||
ast::infer(_) => 0u,
|
||||
ast::expl(e) => match e {
|
||||
ast::by_ref => 1u,
|
||||
ast::by_copy => 5u
|
||||
}
|
||||
};
|
||||
let modeval = 5u; // "by copy"
|
||||
let extra = ~[self.c_uint(i),
|
||||
self.c_uint(modeval),
|
||||
self.c_tydesc(arg.ty)];
|
||||
|
@ -19,11 +19,8 @@ use util::ppaux;
|
||||
|
||||
use syntax::ast;
|
||||
|
||||
pub fn arg_is_indirect(ccx: @CrateContext, arg: &ty::arg) -> bool {
|
||||
match ty::resolved_mode(ccx.tcx, arg.mode) {
|
||||
ast::by_copy => !ty::type_is_immediate(arg.ty),
|
||||
ast::by_ref => true
|
||||
}
|
||||
pub fn arg_is_indirect(_: @CrateContext, arg: &ty::arg) -> bool {
|
||||
!ty::type_is_immediate(arg.ty)
|
||||
}
|
||||
|
||||
pub fn type_of_explicit_arg(ccx: @CrateContext, arg: &ty::arg) -> TypeRef {
|
||||
|
@ -78,12 +78,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
|
||||
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
|
||||
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
|
||||
for vec::each(sig.inputs) |arg| {
|
||||
match ty::resolved_mode(ccx.tcx, arg.mode) {
|
||||
by_copy => {
|
||||
type_needs(cx, use_repr, arg.ty);
|
||||
}
|
||||
by_ref => {}
|
||||
}
|
||||
type_needs(cx, use_repr, arg.ty);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
@ -332,15 +327,9 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
|
||||
node_type_needs(cx, use_tydesc, val.id);
|
||||
}
|
||||
expr_call(f, _, _) => {
|
||||
for vec::each(
|
||||
ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id))
|
||||
) |a| {
|
||||
match a.mode {
|
||||
expl(by_copy) => {
|
||||
type_needs(cx, use_repr, a.ty);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
for vec::each(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
|
||||
f.id))) |a| {
|
||||
type_needs(cx, use_repr, a.ty);
|
||||
}
|
||||
}
|
||||
expr_method_call(rcvr, _, _, _, _) => {
|
||||
@ -349,12 +338,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
|
||||
|
||||
for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
|
||||
e.callee_id)).each |a| {
|
||||
match a.mode {
|
||||
expl(by_copy) => {
|
||||
type_needs(cx, use_repr, a.ty);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
type_needs(cx, use_repr, a.ty);
|
||||
}
|
||||
mark_for_method_call(cx, e.id, e.callee_id);
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ use syntax::ast_util;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::span;
|
||||
use syntax::codemap;
|
||||
use syntax::print::pprust;
|
||||
use syntax::parse::token::special_idents;
|
||||
use syntax::{ast, ast_map};
|
||||
use syntax::opt_vec::OptVec;
|
||||
@ -48,11 +47,8 @@ use syntax;
|
||||
|
||||
// Data types
|
||||
|
||||
// Note: after typeck, you should use resolved_mode() to convert this mode
|
||||
// into an rmode, which will take into account the results of mode inference.
|
||||
#[deriving(Eq)]
|
||||
#[deriving(Eq, IterBytes)]
|
||||
pub struct arg {
|
||||
mode: ast::mode,
|
||||
ty: t
|
||||
}
|
||||
|
||||
@ -99,6 +95,16 @@ pub enum TraitStore {
|
||||
RegionTraitStore(Region), // &Trait
|
||||
}
|
||||
|
||||
// XXX: This should probably go away at some point. Maybe after destructors
|
||||
// do?
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Eq)]
|
||||
pub enum SelfMode {
|
||||
ByCopy,
|
||||
ByRef,
|
||||
}
|
||||
|
||||
pub struct field_ty {
|
||||
ident: ident,
|
||||
id: def_id,
|
||||
@ -270,7 +276,6 @@ struct ctxt_ {
|
||||
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
|
||||
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
|
||||
ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
|
||||
inferred_modes: @mut HashMap<ast::node_id, ast::mode>,
|
||||
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
|
||||
normalized_cache: @mut HashMap<t, t>,
|
||||
lang_items: middle::lang_items::LanguageItems,
|
||||
@ -630,7 +635,6 @@ pub enum type_err {
|
||||
terr_record_mutability,
|
||||
terr_record_fields(expected_found<ident>),
|
||||
terr_arg_count,
|
||||
terr_mode_mismatch(expected_found<mode>),
|
||||
terr_regions_does_not_outlive(Region, Region),
|
||||
terr_regions_not_same(Region, Region),
|
||||
terr_regions_no_overlap(Region, Region),
|
||||
@ -919,7 +923,6 @@ pub fn mk_ctxt(s: session::Session,
|
||||
trait_method_def_ids: @mut HashMap::new(),
|
||||
trait_methods_cache: @mut HashMap::new(),
|
||||
ty_param_defs: @mut HashMap::new(),
|
||||
inferred_modes: @mut HashMap::new(),
|
||||
adjustments: @mut HashMap::new(),
|
||||
normalized_cache: new_ty_hash(),
|
||||
lang_items: lang_items,
|
||||
@ -1199,15 +1202,17 @@ pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
|
||||
}
|
||||
|
||||
pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
|
||||
let input_args = input_tys.map(|t| arg {mode: ast::expl(ast::by_copy),
|
||||
ty: *t});
|
||||
let input_args = input_tys.map(|t| arg { ty: *t });
|
||||
mk_bare_fn(cx,
|
||||
BareFnTy {
|
||||
purity: ast::pure_fn,
|
||||
abis: AbiSet::Rust(),
|
||||
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: input_args,
|
||||
output: output}})
|
||||
sig: FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: input_args,
|
||||
output: output
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1258,40 +1263,14 @@ pub fn mach_sty(cfg: @session::config, t: t) -> sty {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
|
||||
return if tcx.legacy_modes {
|
||||
if type_is_borrowed(ty) {
|
||||
// the old mode default was ++ for things like &ptr, but to be
|
||||
// forward-compatible with non-legacy, we should use +
|
||||
ast::by_copy
|
||||
} else if ty::type_is_immediate(ty) {
|
||||
ast::by_copy
|
||||
} else {
|
||||
ast::by_ref
|
||||
}
|
||||
} else {
|
||||
ast::by_copy
|
||||
};
|
||||
|
||||
fn type_is_borrowed(ty: t) -> bool {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_rptr(*) => true,
|
||||
ty_evec(_, vstore_slice(_)) => true,
|
||||
ty_estr(vstore_slice(_)) => true,
|
||||
|
||||
// technically, we prob ought to include
|
||||
// &fn(), but that is treated specially due to #2202
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_ty(ty: t, f: &fn(t)) {
|
||||
maybe_walk_ty(ty, |t| { f(t); true });
|
||||
}
|
||||
|
||||
pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
|
||||
if !f(ty) { return; }
|
||||
if !f(ty) {
|
||||
return;
|
||||
}
|
||||
match get(ty).sty {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
|
||||
@ -1323,7 +1302,9 @@ pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
|
||||
|
||||
pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
|
||||
let args = do sig.inputs.map |arg| {
|
||||
arg { mode: arg.mode, ty: fldop(arg.ty) }
|
||||
arg {
|
||||
ty: fldop(arg.ty)
|
||||
}
|
||||
};
|
||||
|
||||
FnSig {
|
||||
@ -2696,13 +2677,6 @@ impl to_bytes::IterBytes for field {
|
||||
}
|
||||
}
|
||||
|
||||
impl to_bytes::IterBytes for arg {
|
||||
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
|
||||
to_bytes::iter_bytes_2(&self.mode,
|
||||
&self.ty, lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl to_bytes::IterBytes for FnSig {
|
||||
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
|
||||
to_bytes::iter_bytes_2(&self.inputs,
|
||||
@ -3368,78 +3342,6 @@ pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
|
||||
}
|
||||
}
|
||||
|
||||
// Maintains a little union-set tree for inferred modes. `canon()` returns
|
||||
// the current head value for `m0`.
|
||||
fn canon<T:Copy + cmp::Eq>(tbl: &mut HashMap<ast::node_id, ast::inferable<T>>,
|
||||
m0: ast::inferable<T>) -> ast::inferable<T> {
|
||||
match m0 {
|
||||
ast::infer(id) => {
|
||||
let m1 = match tbl.find(&id) {
|
||||
None => return m0,
|
||||
Some(&m1) => m1
|
||||
};
|
||||
let cm1 = canon(tbl, m1);
|
||||
// path compression:
|
||||
if cm1 != m1 { tbl.insert(id, cm1); }
|
||||
cm1
|
||||
},
|
||||
_ => m0
|
||||
}
|
||||
}
|
||||
|
||||
// Maintains a little union-set tree for inferred modes. `resolve_mode()`
|
||||
// returns the current head value for `m0`.
|
||||
pub fn canon_mode(cx: ctxt, m0: ast::mode) -> ast::mode {
|
||||
canon(cx.inferred_modes, m0)
|
||||
}
|
||||
|
||||
// Returns the head value for mode, failing if `m` was a infer(_) that
|
||||
// was never inferred. This should be safe for use after typeck.
|
||||
pub fn resolved_mode(cx: ctxt, m: ast::mode) -> ast::rmode {
|
||||
match canon_mode(cx, m) {
|
||||
ast::infer(_) => {
|
||||
cx.sess.bug(fmt!("mode %? was never resolved", m));
|
||||
}
|
||||
ast::expl(m0) => m0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { resolved_mode(cx, a.mode) }
|
||||
|
||||
// Unifies `m1` and `m2`. Returns unified value or failure code.
|
||||
pub fn unify_mode(cx: ctxt, modes: expected_found<ast::mode>)
|
||||
-> Result<ast::mode, type_err> {
|
||||
let m1 = modes.expected;
|
||||
let m2 = modes.found;
|
||||
match (canon_mode(cx, m1), canon_mode(cx, m2)) {
|
||||
(m1, m2) if (m1 == m2) => {
|
||||
result::Ok(m1)
|
||||
}
|
||||
(ast::infer(_), ast::infer(id2)) => {
|
||||
cx.inferred_modes.insert(id2, m1);
|
||||
result::Ok(m1)
|
||||
}
|
||||
(ast::infer(id), m) | (m, ast::infer(id)) => {
|
||||
cx.inferred_modes.insert(id, m);
|
||||
result::Ok(m1)
|
||||
}
|
||||
(_, _) => {
|
||||
result::Err(terr_mode_mismatch(modes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If `m` was never unified, unifies it with `m_def`. Returns the final value
|
||||
// for `m`.
|
||||
pub fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
|
||||
match canon_mode(cx, m) {
|
||||
ast::infer(id) => {
|
||||
cx.inferred_modes.insert(id, ast::expl(m_def));
|
||||
}
|
||||
ast::expl(_) => ()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
|
||||
match get(t).sty {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) |
|
||||
@ -3537,11 +3439,6 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
|
||||
*cx.sess.str_of(values.found))
|
||||
}
|
||||
terr_arg_count => ~"incorrect number of function parameters",
|
||||
terr_mode_mismatch(values) => {
|
||||
fmt!("expected argument mode %s, but found %s",
|
||||
pprust::mode_to_str(values.expected),
|
||||
pprust::mode_to_str(values.found))
|
||||
}
|
||||
terr_regions_does_not_outlive(*) => {
|
||||
fmt!("lifetime mismatch")
|
||||
}
|
||||
|
@ -501,52 +501,22 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
|
||||
return typ;
|
||||
}
|
||||
|
||||
pub fn ty_of_arg<AC:AstConv,RS:region_scope + Copy + Durable>(
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
a: ast::arg,
|
||||
expected_ty: Option<ty::arg>)
|
||||
-> ty::arg {
|
||||
pub fn ty_of_arg<AC:AstConv,
|
||||
RS:region_scope + Copy + Durable>(
|
||||
self: &AC,
|
||||
rscope: &RS,
|
||||
a: ast::arg,
|
||||
expected_ty: Option<ty::arg>)
|
||||
-> ty::arg {
|
||||
let ty = match a.ty.node {
|
||||
ast::ty_infer if expected_ty.is_some() => expected_ty.get().ty,
|
||||
ast::ty_infer => self.ty_infer(a.ty.span),
|
||||
_ => ast_ty_to_ty(self, rscope, a.ty)
|
||||
ast::ty_infer if expected_ty.is_some() => expected_ty.get().ty,
|
||||
ast::ty_infer => self.ty_infer(a.ty.span),
|
||||
_ => ast_ty_to_ty(self, rscope, a.ty),
|
||||
};
|
||||
|
||||
let mode = {
|
||||
match a.mode {
|
||||
ast::infer(_) if expected_ty.is_some() => {
|
||||
result::get(&ty::unify_mode(
|
||||
self.tcx(),
|
||||
ty::expected_found {expected: expected_ty.get().mode,
|
||||
found: a.mode}))
|
||||
}
|
||||
ast::infer(_) => {
|
||||
match ty::get(ty).sty {
|
||||
// If the type is not specified, then this must be a fn expr.
|
||||
// Leave the mode as infer(_), it will get inferred based
|
||||
// on constraints elsewhere.
|
||||
ty::ty_infer(_) => a.mode,
|
||||
|
||||
// If the type is known, then use the default for that type.
|
||||
// Here we unify m and the default. This should update the
|
||||
// tables in tcx but should never fail, because nothing else
|
||||
// will have been unified with m yet:
|
||||
_ => {
|
||||
let m1 = ast::expl(ty::default_arg_mode_for_ty(self.tcx(),
|
||||
ty));
|
||||
result::get(&ty::unify_mode(
|
||||
self.tcx(),
|
||||
ty::expected_found {expected: m1,
|
||||
found: a.mode}))
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expl(_) => a.mode
|
||||
}
|
||||
};
|
||||
|
||||
arg {mode: mode, ty: ty}
|
||||
arg {
|
||||
ty: ty
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bound_lifetimes<AC:AstConv>(
|
||||
|
@ -96,7 +96,7 @@ use util::common::indenter;
|
||||
use core::hashmap::HashSet;
|
||||
use std::list::Nil;
|
||||
use syntax::ast::{def_id, sty_value, sty_region, sty_box};
|
||||
use syntax::ast::{sty_uniq, sty_static, node_id, by_copy, by_ref};
|
||||
use syntax::ast::{sty_uniq, sty_static, node_id};
|
||||
use syntax::ast::{m_const, m_mutbl, m_imm};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
@ -1051,9 +1051,9 @@ pub impl<'self> LookupContext<'self> {
|
||||
self.fcx.write_substs(self.callee_id, all_substs);
|
||||
method_map_entry {
|
||||
self_arg: arg {
|
||||
mode: ast::expl(self_mode),
|
||||
ty: candidate.rcvr_ty,
|
||||
},
|
||||
self_mode: self_mode,
|
||||
explicit_self: candidate.method_ty.self_ty,
|
||||
origin: candidate.origin,
|
||||
}
|
||||
@ -1298,6 +1298,9 @@ pub impl<'self> LookupContext<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> ast::rmode {
|
||||
match self_type { sty_value => by_copy, _ => by_ref }
|
||||
pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> SelfMode {
|
||||
match self_type {
|
||||
sty_value => ty::ByCopy,
|
||||
_ => ty::ByRef,
|
||||
}
|
||||
}
|
||||
|
@ -1292,8 +1292,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
}
|
||||
|
||||
fn err_args(len: uint) -> ~[ty::arg] {
|
||||
vec::from_fn(len, |_| ty::arg {mode: ast::expl(ast::by_copy),
|
||||
ty: ty::mk_err()})
|
||||
vec::from_fn(len, |_| ty::arg { ty: ty::mk_err() })
|
||||
}
|
||||
|
||||
// A generic function for checking assignment expressions
|
||||
@ -1694,10 +1693,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
let fty = if error_happened {
|
||||
fty_sig = FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: fn_ty.sig.inputs.map(|an_arg| {
|
||||
arg { mode: an_arg.mode,
|
||||
ty: ty::mk_err()
|
||||
}}),
|
||||
inputs: fn_ty.sig.inputs.map(|_| {
|
||||
arg {
|
||||
ty: ty::mk_err()
|
||||
}
|
||||
}),
|
||||
output: ty::mk_err()
|
||||
};
|
||||
ty::mk_err()
|
||||
@ -2762,11 +2762,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
};
|
||||
if bot_field {
|
||||
fcx.write_bot(id);
|
||||
}
|
||||
else if err_field {
|
||||
} else if err_field {
|
||||
fcx.write_error(id);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let typ = ty::mk_tup(tcx, elt_ts);
|
||||
fcx.write_ty(id, typ);
|
||||
}
|
||||
@ -2796,15 +2794,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
check_expr(fcx, idx);
|
||||
let raw_base_t = fcx.expr_ty(base);
|
||||
let idx_t = fcx.expr_ty(idx);
|
||||
if ty::type_is_error(raw_base_t)
|
||||
|| ty::type_is_bot(raw_base_t) {
|
||||
if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
|
||||
fcx.write_ty(id, raw_base_t);
|
||||
}
|
||||
else if ty::type_is_error(idx_t)
|
||||
|| ty::type_is_bot(idx_t) {
|
||||
} else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
|
||||
fcx.write_ty(id, idx_t);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let (base_t, derefs) = do_autoderef(fcx, expr.span, raw_base_t);
|
||||
let base_sty = structure_of(fcx, expr.span, base_t);
|
||||
match ty::index_sty(&base_sty) {
|
||||
@ -2815,15 +2809,29 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
}
|
||||
None => {
|
||||
let resolved = structurally_resolved_type(fcx,
|
||||
expr.span, raw_base_t);
|
||||
let ret_ty = lookup_op_method(fcx, expr, base, resolved,
|
||||
tcx.sess.ident_of(~"index"),
|
||||
~[idx], DoDerefArgs, AutoderefReceiver,
|
||||
|| {
|
||||
fcx.type_error_message(expr.span, |actual|
|
||||
fmt!("cannot index a value \
|
||||
of type `%s`", actual), base_t, None);
|
||||
}, expected);
|
||||
expr.span,
|
||||
raw_base_t);
|
||||
let index_ident = tcx.sess.ident_of(~"index");
|
||||
let error_message = || {
|
||||
fcx.type_error_message(expr.span,
|
||||
|actual| {
|
||||
fmt!("cannot index a value \
|
||||
of type `%s`",
|
||||
actual)
|
||||
},
|
||||
base_t,
|
||||
None);
|
||||
};
|
||||
let ret_ty = lookup_op_method(fcx,
|
||||
expr,
|
||||
base,
|
||||
resolved,
|
||||
index_ident,
|
||||
~[idx],
|
||||
DoDerefArgs,
|
||||
AutoderefReceiver,
|
||||
error_message,
|
||||
expected);
|
||||
fcx.write_ty(id, ret_ty);
|
||||
}
|
||||
}
|
||||
@ -3180,8 +3188,8 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
|
||||
-> ty_param_bounds_and_ty {
|
||||
|
||||
match defn {
|
||||
ast::def_arg(nid, _, _) | ast::def_local(nid, _) |
|
||||
ast::def_self(nid, _) | ast::def_binding(nid, _) => {
|
||||
ast::def_arg(nid, _) | ast::def_local(nid, _) | ast::def_self(nid, _) |
|
||||
ast::def_binding(nid, _) => {
|
||||
let typ = fcx.local_ty(sp, nid);
|
||||
return no_params(typ);
|
||||
}
|
||||
@ -3429,41 +3437,52 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
||||
fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
|
||||
ty::mk_param(ccx.tcx, n, local_def(0))
|
||||
}
|
||||
fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
|
||||
arg {mode: ast::expl(m), ty: ty}
|
||||
fn arg(ty: ty::t) -> ty::arg {
|
||||
arg {
|
||||
ty: ty
|
||||
}
|
||||
}
|
||||
|
||||
let tcx = ccx.tcx;
|
||||
let (n_tps, inputs, output) = match *ccx.tcx.sess.str_of(it.ident) {
|
||||
~"size_of" |
|
||||
~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()),
|
||||
~"init" => (1u, ~[], param(ccx, 0u)),
|
||||
~"forget" => (1u, ~[arg(ast::by_copy, param(ccx, 0u))],
|
||||
ty::mk_nil()),
|
||||
~"transmute" => (2, ~[arg(ast::by_copy, param(ccx, 0))], param(ccx, 1)),
|
||||
~"forget" => (1u, ~[arg(param(ccx, 0u))], ty::mk_nil()),
|
||||
~"transmute" => (2, ~[ arg(param(ccx, 0)) ], param(ccx, 1)),
|
||||
~"move_val" | ~"move_val_init" => {
|
||||
(1u, ~[arg(ast::by_copy,
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
|
||||
param(ccx, 0u))),
|
||||
arg(ast::by_copy, param(ccx, 0u))],
|
||||
(1u,
|
||||
~[
|
||||
arg(ty::mk_mut_rptr(tcx,
|
||||
ty::re_bound(ty::br_anon(0)),
|
||||
param(ccx, 0))),
|
||||
arg(param(ccx, 0u))
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
~"needs_drop" => (1u, ~[], ty::mk_bool()),
|
||||
|
||||
~"atomic_cxchg" | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => {
|
||||
(0u, ~[arg(ast::by_copy,
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int())),
|
||||
arg(ast::by_copy, ty::mk_int()),
|
||||
arg(ast::by_copy, ty::mk_int())],
|
||||
ty::mk_int())
|
||||
(0,
|
||||
~[
|
||||
arg(ty::mk_mut_rptr(tcx,
|
||||
ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int(tcx))),
|
||||
arg(ty::mk_int()),
|
||||
arg(ty::mk_int())
|
||||
],
|
||||
ty::mk_int(tcx))
|
||||
}
|
||||
~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" |
|
||||
~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" |
|
||||
~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => {
|
||||
(0u, ~[arg(ast::by_copy,
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int())),
|
||||
arg(ast::by_copy, ty::mk_int())],
|
||||
(0,
|
||||
~[
|
||||
arg(ty::mk_mut_rptr(tcx,
|
||||
ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int(tcx))),
|
||||
arg(ty::mk_int())
|
||||
],
|
||||
ty::mk_int())
|
||||
}
|
||||
|
||||
@ -3472,14 +3491,15 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
||||
(1u, ~[], ty::mk_nil_ptr(ccx.tcx))
|
||||
}
|
||||
~"visit_tydesc" => {
|
||||
let tydesc_name = special_idents::tydesc;
|
||||
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
|
||||
let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
|
||||
let (_, visitor_object_ty) = ty::visitor_object_ty(ccx.tcx);
|
||||
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty,
|
||||
mutbl: ast::m_imm});
|
||||
(0u, ~[arg(ast::by_copy, td_ptr),
|
||||
arg(ast::by_copy, visitor_object_ty)], ty::mk_nil())
|
||||
let tydesc_name = special_idents::tydesc;
|
||||
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
|
||||
let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
|
||||
let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
|
||||
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
|
||||
ty: tydesc_ty,
|
||||
mutbl: ast::m_imm
|
||||
});
|
||||
(0, ~[ arg(td_ptr), arg(visitor_object_ty) ], ty::mk_nil())
|
||||
}
|
||||
~"frame_address" => {
|
||||
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
|
||||
@ -3489,233 +3509,124 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
sig: ty::FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[arg {mode: ast::expl(ast::by_copy),
|
||||
ty: ty::mk_imm_ptr(
|
||||
ccx.tcx,
|
||||
ty::mk_mach_uint(ast::ty_u8))}],
|
||||
inputs: ~[
|
||||
arg {
|
||||
ty: ty::mk_imm_ptr(ccx.tcx,
|
||||
ty::mk_mach_uint(ast::ty_u8))
|
||||
}
|
||||
],
|
||||
output: ty::mk_nil()
|
||||
}
|
||||
});
|
||||
(0u, ~[arg(ast::by_copy, fty)], ty::mk_nil())
|
||||
(0u, ~[ arg(fty) ], ty::mk_nil())
|
||||
}
|
||||
~"morestack_addr" => {
|
||||
(0u, ~[], ty::mk_nil_ptr(ccx.tcx))
|
||||
}
|
||||
~"memmove32" => {
|
||||
(0, ~[arg(ast::by_copy,
|
||||
ty::mk_ptr(tcx,
|
||||
ty::mt { ty: ty::mk_u8(), mutbl: ast::m_mutbl })),
|
||||
arg(ast::by_copy,
|
||||
ty::mk_ptr(tcx,
|
||||
ty::mt { ty: ty::mk_u8(), mutbl: ast::m_imm })),
|
||||
arg(ast::by_copy,
|
||||
ty::mk_u32())],
|
||||
(0,
|
||||
~[
|
||||
arg(ty::mk_ptr(tcx, ty::mt {
|
||||
ty: ty::mk_u8(),
|
||||
mutbl: ast::m_mutbl
|
||||
})),
|
||||
arg(ty::mk_ptr(tcx, ty::mt {
|
||||
ty: ty::mk_u8(),
|
||||
mutbl: ast::m_imm
|
||||
})),
|
||||
arg(ty::mk_u32())
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
~"memmove64" => {
|
||||
(0, ~[arg(ast::by_copy,
|
||||
ty::mk_ptr(tcx,
|
||||
ty::mt { ty: ty::mk_u8(), mutbl: ast::m_mutbl })),
|
||||
arg(ast::by_copy,
|
||||
ty::mk_ptr(tcx,
|
||||
ty::mt { ty: ty::mk_u8(), mutbl: ast::m_imm })),
|
||||
arg(ast::by_copy,
|
||||
ty::mk_u64())],
|
||||
ty::mk_nil())
|
||||
}
|
||||
~"sqrtf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"sqrtf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"powif32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32()),
|
||||
arg(ast::by_copy, ty::mk_i32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"powif64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64()),
|
||||
arg(ast::by_copy, ty::mk_i32())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"sinf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"sinf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"cosf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"cosf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"powf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32()),
|
||||
arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"powf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64()),
|
||||
arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"expf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"expf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"exp2f32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"exp2f64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"logf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"logf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"log10f32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"log10f64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"log2f32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"log2f64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"fmaf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32()),
|
||||
arg(ast::by_copy, ty::mk_f32()),
|
||||
arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"fmaf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64()),
|
||||
arg(ast::by_copy, ty::mk_f64()),
|
||||
arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"fabsf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"fabsf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"floorf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"floorf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"ceilf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"ceilf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"truncf32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f32())],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"truncf64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_f64())],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"ctpop8" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i8())],
|
||||
ty::mk_i8())
|
||||
}
|
||||
~"ctpop16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16())],
|
||||
ty::mk_i16())
|
||||
}
|
||||
~"ctpop32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32())],
|
||||
ty::mk_i32())
|
||||
}
|
||||
~"ctpop64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64())],
|
||||
ty::mk_i64())
|
||||
}
|
||||
~"ctlz8" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i8())],
|
||||
ty::mk_i8())
|
||||
}
|
||||
~"ctlz16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16())],
|
||||
ty::mk_i16())
|
||||
}
|
||||
~"ctlz32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32())],
|
||||
ty::mk_i32())
|
||||
}
|
||||
~"ctlz64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64())],
|
||||
ty::mk_i64())
|
||||
}
|
||||
~"cttz8" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i8())],
|
||||
ty::mk_i8())
|
||||
}
|
||||
~"cttz16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16())],
|
||||
ty::mk_i16())
|
||||
}
|
||||
~"cttz32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32())],
|
||||
ty::mk_i32())
|
||||
}
|
||||
~"cttz64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64())],
|
||||
ty::mk_i64())
|
||||
}
|
||||
~"bswap16" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i16())],
|
||||
ty::mk_i16())
|
||||
}
|
||||
~"bswap32" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i32())],
|
||||
ty::mk_i32())
|
||||
}
|
||||
~"bswap64" => {
|
||||
(0u, ~[arg(ast::by_copy, ty::mk_i64())],
|
||||
ty::mk_i64())
|
||||
}
|
||||
ref other => {
|
||||
tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" +
|
||||
(*other) + ~"`");
|
||||
return;
|
||||
(0,
|
||||
~[arg(ty::mk_ptr(tcx, ty::mt {
|
||||
ty: ty::mk_u8(),
|
||||
mutbl: ast::m_mutbl
|
||||
})),
|
||||
arg(ty::mk_ptr(tcx, ty::mt {
|
||||
ty: ty::mk_u8(),
|
||||
mutbl: ast::m_imm
|
||||
})),
|
||||
arg(ty::mk_u64())
|
||||
],
|
||||
ty::mk_nil(tcx))
|
||||
}
|
||||
~"sqrtf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"sqrtf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"powif32" => {
|
||||
(0,
|
||||
~[ arg(ty::mk_f32()), arg(ty::mk_i32()) ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"powif64" => {
|
||||
(0,
|
||||
~[ arg(ty::mk_f64()), arg(ty::mk_i32()) ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"sinf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"sinf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"cosf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"cosf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"powf32" => {
|
||||
(0,
|
||||
~[ arg(ty::mk_f32()), arg(ty::mk_f32()) ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"powf64" => {
|
||||
(0,
|
||||
~[ arg(ty::mk_f64()), arg(ty::mk_f64()) ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"expf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"expf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"exp2f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"exp2f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"logf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"logf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"log10f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"log10f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"log2f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"log2f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"fmaf32" => {
|
||||
(0,
|
||||
~[ arg(ty::mk_f32()), arg(ty::mk_f32()), arg(ty::mk_f32()) ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
~"fmaf64" => {
|
||||
(0,
|
||||
~[ arg(ty::mk_f64()), arg(ty::mk_f64()), arg(ty::mk_f64()) ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
~"fabsf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"fabsf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"floorf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"floorf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"ceilf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"ceilf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"truncf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
|
||||
~"truncf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
|
||||
~"ctpop8" => (0, ~[ arg(ty::mk_i8()) ], ty::mk_i8()),
|
||||
~"ctpop16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
|
||||
~"ctpop32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
|
||||
~"ctpop64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
|
||||
~"ctlz8" => (0, ~[ arg(ty::mk_i8()) ], ty::mk_i8()),
|
||||
~"ctlz16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
|
||||
~"ctlz32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
|
||||
~"ctlz64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
|
||||
~"cttz8" => (0, ~[ arg(ty::mk_i8()) ], ty::mk_i8()),
|
||||
~"cttz16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
|
||||
~"cttz32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
|
||||
~"cttz64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
|
||||
~"bswap16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
|
||||
~"bswap32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
|
||||
~"bswap64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
|
||||
ref other => {
|
||||
tcx.sess.span_err(it.span,
|
||||
~"unrecognized intrinsic function: `" +
|
||||
(*other) + ~"`");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
||||
purity: ast::unsafe_fn,
|
||||
|
@ -55,7 +55,7 @@ pub type rvt = visit::vt<@mut Rcx>;
|
||||
fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::def) -> ty::Region {
|
||||
let tcx = fcx.tcx();
|
||||
match def {
|
||||
def_local(node_id, _) | def_arg(node_id, _, _) |
|
||||
def_local(node_id, _) | def_arg(node_id, _) |
|
||||
def_self(node_id, _) | def_binding(node_id, _) => {
|
||||
tcx.region_maps.encl_region(node_id)
|
||||
}
|
||||
|
@ -66,7 +66,9 @@ fn resolve_method_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
|
||||
for resolve_type_vars_in_type(fcx, sp, mme.self_arg.ty).each |t| {
|
||||
let method_map = fcx.ccx.method_map;
|
||||
let new_entry = method_map_entry {
|
||||
self_arg: arg {mode: mme.self_arg.mode, ty: *t },
|
||||
self_arg: arg {
|
||||
ty: *t
|
||||
},
|
||||
..*mme
|
||||
};
|
||||
debug!("writeback::resolve_method_map_entry(id=%?, \
|
||||
@ -213,52 +215,55 @@ fn visit_stmt(s: @ast::stmt, wbcx: @mut WbCtxt, v: wb_vt) {
|
||||
resolve_type_vars_for_node(wbcx, s.span, ty::stmt_node_id(s));
|
||||
visit::visit_stmt(s, wbcx, v);
|
||||
}
|
||||
|
||||
fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) {
|
||||
if !wbcx.success { return; }
|
||||
if !wbcx.success {
|
||||
return;
|
||||
}
|
||||
|
||||
resolve_type_vars_for_node(wbcx, e.span, e.id);
|
||||
resolve_method_map_entry(wbcx.fcx, e.span, e.id);
|
||||
resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id);
|
||||
resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
|
||||
resolve_vtable_map_entry(wbcx.fcx, e.span, e.callee_id);
|
||||
|
||||
match e.node {
|
||||
ast::expr_fn_block(ref decl, _) => {
|
||||
for vec::each(decl.inputs) |input| {
|
||||
let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id);
|
||||
ast::expr_fn_block(ref decl, _) => {
|
||||
for vec::each(decl.inputs) |input| {
|
||||
let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Just in case we never constrained the mode to anything,
|
||||
// constrain it to the default for the type in question.
|
||||
match (r_ty, input.mode) {
|
||||
(Some(t), ast::infer(_)) => {
|
||||
let tcx = wbcx.fcx.ccx.tcx;
|
||||
let m_def = ty::default_arg_mode_for_ty(tcx, t);
|
||||
ty::set_default_mode(tcx, input.mode, m_def);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*) |
|
||||
ast::expr_index(*) => {
|
||||
maybe_resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
|
||||
}
|
||||
|
||||
ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*)
|
||||
| ast::expr_index(*) => {
|
||||
maybe_resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
|
||||
}
|
||||
ast::expr_method_call(*) => {
|
||||
// We must always have written in a callee ID type for these.
|
||||
resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
|
||||
}
|
||||
|
||||
ast::expr_method_call(*) => {
|
||||
// We must always have written in a callee ID type for these.
|
||||
resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
|
||||
}
|
||||
|
||||
_ => ()
|
||||
_ => ()
|
||||
}
|
||||
|
||||
visit::visit_expr(e, wbcx, v);
|
||||
}
|
||||
|
||||
fn visit_block(b: &ast::blk, wbcx: @mut WbCtxt, v: wb_vt) {
|
||||
if !wbcx.success { return; }
|
||||
if !wbcx.success {
|
||||
return;
|
||||
}
|
||||
|
||||
resolve_type_vars_for_node(wbcx, b.span, b.node.id);
|
||||
visit::visit_block(b, wbcx, v);
|
||||
}
|
||||
|
||||
fn visit_pat(p: @ast::pat, wbcx: @mut WbCtxt, v: wb_vt) {
|
||||
if !wbcx.success { return; }
|
||||
if !wbcx.success {
|
||||
return;
|
||||
}
|
||||
|
||||
resolve_type_vars_for_node(wbcx, p.span, p.id);
|
||||
debug!("Type for pattern binding %s (id %d) resolved to %s",
|
||||
pat_to_str(p, wbcx.fcx.ccx.tcx.sess.intr()), p.id,
|
||||
@ -267,6 +272,7 @@ fn visit_pat(p: @ast::pat, wbcx: @mut WbCtxt, v: wb_vt) {
|
||||
p.id)));
|
||||
visit::visit_pat(p, wbcx, v);
|
||||
}
|
||||
|
||||
fn visit_local(l: @ast::local, wbcx: @mut WbCtxt, v: wb_vt) {
|
||||
if !wbcx.success { return; }
|
||||
let var_ty = wbcx.fcx.local_ty(l.span, l.node.id);
|
||||
|
@ -552,10 +552,14 @@ pub fn compare_impl_method(tcx: ty::ctxt,
|
||||
// represent the self argument (unless this is a static method).
|
||||
// This argument will have the *transformed* self type.
|
||||
for trait_m.transformed_self_ty.each |&t| {
|
||||
trait_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t});
|
||||
trait_fn_args.push(ty::arg {
|
||||
ty: t
|
||||
});
|
||||
}
|
||||
for impl_m.transformed_self_ty.each |&t| {
|
||||
impl_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t});
|
||||
impl_fn_args.push(ty::arg {
|
||||
ty: t
|
||||
});
|
||||
}
|
||||
|
||||
// Add in the normal arguments.
|
||||
|
@ -95,7 +95,6 @@ pub trait Combine {
|
||||
b: &ty::ClosureTy) -> cres<ty::ClosureTy>;
|
||||
fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
|
||||
fn flds(&self, a: ty::field, b: ty::field) -> cres<ty::field>;
|
||||
fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode>;
|
||||
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg>;
|
||||
fn sigils(&self, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil>;
|
||||
fn purities(&self, a: purity, b: purity) -> cres<purity>;
|
||||
@ -312,28 +311,20 @@ pub fn super_flds<C:Combine>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_modes<C:Combine>(
|
||||
self: &C, a: ast::mode, b: ast::mode)
|
||||
-> cres<ast::mode> {
|
||||
|
||||
let tcx = self.infcx().tcx;
|
||||
ty::unify_mode(tcx, expected_found(self, a, b))
|
||||
}
|
||||
|
||||
pub fn super_args<C:Combine>(
|
||||
self: &C, a: ty::arg, b: ty::arg)
|
||||
-> cres<ty::arg> {
|
||||
|
||||
do self.modes(a.mode, b.mode).chain |m| {
|
||||
do self.contratys(a.ty, b.ty).chain |t| {
|
||||
Ok(arg {mode: m, ty: t})
|
||||
}
|
||||
pub fn super_args<C:Combine>(self: &C, a: ty::arg, b: ty::arg)
|
||||
-> cres<ty::arg> {
|
||||
do self.contratys(a.ty, b.ty).chain |t| {
|
||||
Ok(arg {
|
||||
ty: t
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_vstores<C:Combine>(
|
||||
self: &C, vk: ty::terr_vstore_kind,
|
||||
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
|
||||
pub fn super_vstores<C:Combine>(self: &C,
|
||||
vk: ty::terr_vstore_kind,
|
||||
a: ty::vstore,
|
||||
b: ty::vstore)
|
||||
-> cres<ty::vstore> {
|
||||
debug!("%s.super_vstores(a=%?, b=%?)", self.tag(), a, b);
|
||||
|
||||
match (a, b) {
|
||||
|
@ -152,10 +152,6 @@ impl Combine for Glb {
|
||||
super_trait_stores(self, vk, a, b)
|
||||
}
|
||||
|
||||
fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode> {
|
||||
super_modes(self, a, b)
|
||||
}
|
||||
|
||||
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
|
||||
super_args(self, a, b)
|
||||
}
|
||||
|
@ -234,10 +234,6 @@ impl Combine for Lub {
|
||||
super_trait_stores(self, vk, a, b)
|
||||
}
|
||||
|
||||
fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode> {
|
||||
super_modes(self, a, b)
|
||||
}
|
||||
|
||||
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
|
||||
super_args(self, a, b)
|
||||
}
|
||||
|
@ -241,14 +241,10 @@ impl Combine for Sub {
|
||||
vk: ty::terr_vstore_kind,
|
||||
a: ty::TraitStore,
|
||||
b: ty::TraitStore)
|
||||
-> cres<ty::TraitStore> {
|
||||
-> cres<ty::TraitStore> {
|
||||
super_trait_stores(self, vk, a, b)
|
||||
}
|
||||
|
||||
fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode> {
|
||||
super_modes(self, a, b)
|
||||
}
|
||||
|
||||
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
|
||||
super_args(self, a, b)
|
||||
}
|
||||
|
@ -116,10 +116,13 @@ pub struct method_param {
|
||||
}
|
||||
|
||||
pub struct method_map_entry {
|
||||
// the type and mode of the self parameter, which is not reflected
|
||||
// in the fn type (FIXME #3446)
|
||||
// the type of the self parameter, which is not reflected in the fn type
|
||||
// (FIXME #3446)
|
||||
self_arg: ty::arg,
|
||||
|
||||
// the mode of `self`
|
||||
self_mode: ty::SelfMode,
|
||||
|
||||
// the type of explicit self on the method
|
||||
explicit_self: ast::self_ty_,
|
||||
|
||||
@ -329,7 +332,6 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt,
|
||||
fn check_start_fn_ty(ccx: @mut CrateCtxt,
|
||||
start_id: ast::node_id,
|
||||
start_span: span) {
|
||||
|
||||
let tcx = ccx.tcx;
|
||||
let start_t = ty::node_id_to_type(tcx, start_id);
|
||||
match ty::get(start_t).sty {
|
||||
@ -351,19 +353,25 @@ fn check_start_fn_ty(ccx: @mut CrateCtxt,
|
||||
_ => ()
|
||||
}
|
||||
|
||||
fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
|
||||
ty::arg {mode: ast::expl(m), ty: ty}
|
||||
fn arg(ty: ty::t) -> ty::arg {
|
||||
ty::arg {
|
||||
ty: ty
|
||||
}
|
||||
}
|
||||
|
||||
let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
||||
purity: ast::impure_fn,
|
||||
abis: abi::AbiSet::Rust(),
|
||||
sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[arg(ast::by_copy, ty::mk_int()),
|
||||
arg(ast::by_copy, ty::mk_imm_ptr(tcx,
|
||||
ty::mk_imm_ptr(tcx, ty::mk_u8()))),
|
||||
arg(ast::by_copy, ty::mk_imm_ptr(tcx, ty::mk_u8()))],
|
||||
output: ty::mk_int()}
|
||||
sig: ty::FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[
|
||||
arg(ty::mk_int()),
|
||||
arg(ty::mk_imm_ptr(tcx,
|
||||
ty::mk_imm_ptr(tcx, ty::mk_u8()))),
|
||||
arg(ty::mk_imm_ptr(tcx, ty::mk_u8()))
|
||||
],
|
||||
output: ty::mk_int()
|
||||
}
|
||||
});
|
||||
|
||||
require_same_types(tcx, None, false, start_span, start_t, se_ty,
|
||||
|
@ -8,28 +8,25 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use middle::ty::canon_mode;
|
||||
use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid,
|
||||
br_fresh};
|
||||
use middle::ty::{ctxt, field, method};
|
||||
use metadata::encoder;
|
||||
use middle::ty::{ReSkolemized, ReVar};
|
||||
use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
|
||||
use middle::ty::{br_fresh, ctxt, field, method};
|
||||
use middle::ty::{mt, t, param_bound, param_ty};
|
||||
use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region};
|
||||
use middle::ty::{ReSkolemized, ReVar};
|
||||
use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum};
|
||||
use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
|
||||
use middle::ty::{ty_trait, ty_int};
|
||||
use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
|
||||
use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
|
||||
use middle::ty::{ty_trait, ty_int};
|
||||
use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
|
||||
use metadata::encoder;
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use syntax::abi::AbiSet;
|
||||
use syntax::ast_map;
|
||||
use syntax::codemap::span;
|
||||
use syntax::print::pprust;
|
||||
use syntax::print::pprust::mode_to_str;
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::ast_map;
|
||||
use syntax::abi::AbiSet;
|
||||
|
||||
pub trait Repr {
|
||||
fn repr(&self, tcx: ctxt) -> ~str;
|
||||
@ -293,26 +290,14 @@ pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
|
||||
|
||||
pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str {
|
||||
let ty::arg {mode: mode, ty: ty} = input;
|
||||
let modestr = match canon_mode(cx, mode) {
|
||||
ast::infer(_) => ~"",
|
||||
ast::expl(m) => {
|
||||
if !ty::type_needs_infer(ty) &&
|
||||
m == ty::default_arg_mode_for_ty(cx, ty) {
|
||||
~""
|
||||
} else {
|
||||
mode_to_str(ast::expl(m)) + ~":"
|
||||
}
|
||||
}
|
||||
};
|
||||
fmt!("%s%s", modestr, ty_to_str(cx, ty))
|
||||
ty_to_str(cx, input.ty)
|
||||
}
|
||||
fn bare_fn_to_str(cx: ctxt,
|
||||
purity: ast::purity,
|
||||
abis: AbiSet,
|
||||
ident: Option<ast::ident>,
|
||||
sig: &ty::FnSig) -> ~str
|
||||
{
|
||||
sig: &ty::FnSig)
|
||||
-> ~str {
|
||||
let mut s = ~"extern ";
|
||||
|
||||
s.push_str(abis.to_str());
|
||||
@ -701,7 +686,7 @@ impl Repr for typeck::method_map_entry {
|
||||
|
||||
impl Repr for ty::arg {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
fmt!("%?(%s)", self.mode, self.ty.repr(tcx))
|
||||
fmt!("(%s)", self.ty.repr(tcx))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ pub enum def {
|
||||
def_mod(def_id),
|
||||
def_foreign_mod(def_id),
|
||||
def_const(def_id),
|
||||
def_arg(node_id, mode, bool /* is_mutbl */),
|
||||
def_arg(node_id, bool /* is_mutbl */),
|
||||
def_local(node_id, bool /* is_mutbl */),
|
||||
def_variant(def_id /* enum */, def_id /* variant */),
|
||||
def_ty(def_id),
|
||||
@ -417,43 +417,6 @@ pub enum unop {
|
||||
neg
|
||||
}
|
||||
|
||||
// Generally, after typeck you can get the inferred value
|
||||
// using ty::resolved_T(...).
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Eq)]
|
||||
pub enum inferable<T> {
|
||||
expl(T),
|
||||
infer(node_id)
|
||||
}
|
||||
|
||||
impl<T:to_bytes::IterBytes> to_bytes::IterBytes for inferable<T> {
|
||||
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
|
||||
match *self {
|
||||
expl(ref t) =>
|
||||
to_bytes::iter_bytes_2(&0u8, t, lsb0, f),
|
||||
|
||||
infer(ref n) =>
|
||||
to_bytes::iter_bytes_2(&1u8, n, lsb0, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "resolved" mode: the real modes.
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
#[deriving(Eq)]
|
||||
pub enum rmode { by_ref, by_copy }
|
||||
|
||||
impl to_bytes::IterBytes for rmode {
|
||||
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
|
||||
(*self as u8).iter_bytes(lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
// inferable mode.
|
||||
pub type mode = inferable<rmode>;
|
||||
|
||||
pub type stmt = spanned<stmt_>;
|
||||
|
||||
#[auto_encode]
|
||||
@ -941,7 +904,6 @@ pub struct inline_asm {
|
||||
#[auto_decode]
|
||||
#[deriving(Eq)]
|
||||
pub struct arg {
|
||||
mode: mode,
|
||||
is_mutbl: bool,
|
||||
ty: @Ty,
|
||||
pat: @pat,
|
||||
|
@ -58,7 +58,7 @@ pub fn def_id_of_def(d: def) -> def_id {
|
||||
def_use(id) | def_struct(id) | def_trait(id) => {
|
||||
id
|
||||
}
|
||||
def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
|
||||
def_arg(id, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
|
||||
| def_upvar(id, _, _, _) | def_binding(id, _) | def_region(id)
|
||||
| def_typaram_binder(id) | def_label(id) => {
|
||||
local_def(id)
|
||||
|
@ -608,7 +608,6 @@ fn mk_ser_method(
|
||||
};
|
||||
|
||||
let ser_inputs = ~[ast::arg {
|
||||
mode: ast::infer(cx.next_id()),
|
||||
is_mutbl: false,
|
||||
ty: ty_s,
|
||||
pat: @ast::pat {
|
||||
@ -670,20 +669,22 @@ fn mk_deser_method(
|
||||
span: span,
|
||||
};
|
||||
|
||||
let deser_inputs = ~[ast::arg {
|
||||
mode: ast::infer(cx.next_id()),
|
||||
is_mutbl: false,
|
||||
ty: ty_d,
|
||||
pat: @ast::pat {
|
||||
let deser_inputs = ~[
|
||||
ast::arg {
|
||||
is_mutbl: false,
|
||||
ty: ty_d,
|
||||
pat: @ast::pat {
|
||||
id: cx.next_id(),
|
||||
node: ast::pat_ident(ast::bind_by_copy,
|
||||
ast_util::ident_to_path(span,
|
||||
cx.ident_of(
|
||||
~"__d")),
|
||||
None),
|
||||
span: span,
|
||||
},
|
||||
id: cx.next_id(),
|
||||
node: ast::pat_ident(
|
||||
ast::bind_by_copy,
|
||||
ast_util::ident_to_path(span, cx.ident_of(~"__d")),
|
||||
None),
|
||||
span: span,
|
||||
},
|
||||
id: cx.next_id(),
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
let deser_decl = ast::fn_decl {
|
||||
inputs: deser_inputs,
|
||||
@ -1120,7 +1121,6 @@ fn mk_enum_deser_body(
|
||||
ast::expr_fn_block(
|
||||
ast::fn_decl {
|
||||
inputs: ~[ast::arg {
|
||||
mode: ast::infer(ext_cx.next_id()),
|
||||
is_mutbl: false,
|
||||
ty: @ast::Ty {
|
||||
id: ext_cx.next_id(),
|
||||
|
@ -419,7 +419,6 @@ pub fn mk_arg(cx: @ext_ctxt,
|
||||
-> ast::arg {
|
||||
let arg_pat = mk_pat_ident(cx, span, ident);
|
||||
ast::arg {
|
||||
mode: ast::infer(cx.next_id()),
|
||||
is_mutbl: false,
|
||||
ty: ty,
|
||||
pat: arg_pat,
|
||||
|
@ -196,7 +196,6 @@ impl ext_ctxt_ast_builder for @ext_ctxt {
|
||||
|
||||
fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg {
|
||||
ast::arg {
|
||||
mode: ast::infer(self.next_id()),
|
||||
is_mutbl: false,
|
||||
ty: ty,
|
||||
pat: @ast::pat {
|
||||
|
@ -105,7 +105,6 @@ fn fold_attribute_(at: attribute, fld: @ast_fold) -> attribute {
|
||||
//used in noop_fold_foreign_item and noop_fold_fn_decl
|
||||
fn fold_arg_(a: arg, fld: @ast_fold) -> arg {
|
||||
ast::arg {
|
||||
mode: a.mode,
|
||||
is_mutbl: a.is_mutbl,
|
||||
ty: fld.fold_ty(a.ty),
|
||||
pat: fld.fold_pat(a.pat),
|
||||
|
@ -17,10 +17,10 @@ use ast::{RegionTyParamBound, TraitTyParamBound};
|
||||
use ast::{provided, public, purity};
|
||||
use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
|
||||
use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
|
||||
use ast::{blk_check_mode, box, by_copy, by_ref};
|
||||
use ast::{blk_check_mode, box};
|
||||
use ast::{crate, crate_cfg, decl, decl_item};
|
||||
use ast::{decl_local, default_blk, deref, quot, enum_def};
|
||||
use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again};
|
||||
use ast::{expr, expr_, expr_addr_of, expr_match, expr_again};
|
||||
use ast::{expr_assign, expr_assign_op, expr_binary, expr_block};
|
||||
use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
|
||||
use ast::{expr_field, expr_fn_block, expr_if, expr_index};
|
||||
@ -32,13 +32,13 @@ use ast::{expr_vstore_slice, expr_vstore_box};
|
||||
use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
|
||||
use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};
|
||||
use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
|
||||
use ast::{ident, impure_fn, infer, inherited, item, item_, item_const};
|
||||
use ast::{ident, impure_fn, inherited, item, item_, item_const};
|
||||
use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl};
|
||||
use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
|
||||
use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int};
|
||||
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const};
|
||||
use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
|
||||
use ast::{match_seq, match_tok, method, mode, mt, mul, mutability};
|
||||
use ast::{match_seq, match_tok, method, mt, mul, mutability};
|
||||
use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
|
||||
use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct};
|
||||
use ast::{pat_tup, pat_uniq, pat_wild, private};
|
||||
@ -765,22 +765,22 @@ pub impl Parser {
|
||||
}
|
||||
|
||||
// parse an optional mode.
|
||||
fn parse_arg_mode(&self) -> mode {
|
||||
// XXX: Remove after snapshot.
|
||||
fn parse_arg_mode(&self) {
|
||||
if self.eat(&token::BINOP(token::MINUS)) {
|
||||
self.obsolete(*self.span, ObsoleteMode);
|
||||
expl(by_copy)
|
||||
} else if self.eat(&token::ANDAND) {
|
||||
expl(by_ref)
|
||||
// Ignore.
|
||||
} else if self.eat(&token::BINOP(token::PLUS)) {
|
||||
if self.eat(&token::BINOP(token::PLUS)) {
|
||||
// ++ mode is obsolete, but we need a snapshot
|
||||
// to stop parsing it.
|
||||
expl(by_copy)
|
||||
// Ignore.
|
||||
} else {
|
||||
expl(by_copy)
|
||||
// Ignore.
|
||||
}
|
||||
} else {
|
||||
infer(self.get_id())
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
@ -810,16 +810,14 @@ pub impl Parser {
|
||||
// This version of parse arg doesn't necessarily require
|
||||
// identifier names.
|
||||
fn parse_arg_general(&self, require_name: bool) -> arg {
|
||||
let m;
|
||||
let mut is_mutbl = false;
|
||||
let pat = if require_name || self.is_named_argument() {
|
||||
m = self.parse_arg_mode();
|
||||
self.parse_arg_mode();
|
||||
is_mutbl = self.eat_keyword(&~"mut");
|
||||
let pat = self.parse_pat(false);
|
||||
self.expect(&token::COLON);
|
||||
pat
|
||||
} else {
|
||||
m = infer(self.get_id());
|
||||
ast_util::ident_to_pat(self.get_id(),
|
||||
*self.last_span,
|
||||
special_idents::invalid)
|
||||
@ -827,8 +825,12 @@ pub impl Parser {
|
||||
|
||||
let t = self.parse_ty(false);
|
||||
|
||||
ast::arg { mode: m, is_mutbl: is_mutbl,
|
||||
ty: t, pat: pat, id: self.get_id() }
|
||||
ast::arg {
|
||||
is_mutbl: is_mutbl,
|
||||
ty: t,
|
||||
pat: pat,
|
||||
id: self.get_id(),
|
||||
}
|
||||
}
|
||||
|
||||
// parse a single function argument
|
||||
@ -838,7 +840,7 @@ pub impl Parser {
|
||||
|
||||
// parse an argument in a lambda header e.g. |arg, arg|
|
||||
fn parse_fn_block_arg(&self) -> arg_or_capture_item {
|
||||
let m = self.parse_arg_mode();
|
||||
self.parse_arg_mode();
|
||||
let is_mutbl = self.eat_keyword(&~"mut");
|
||||
let pat = self.parse_pat(false);
|
||||
let t = if self.eat(&token::COLON) {
|
||||
@ -851,7 +853,6 @@ pub impl Parser {
|
||||
}
|
||||
};
|
||||
either::Left(ast::arg {
|
||||
mode: m,
|
||||
is_mutbl: is_mutbl,
|
||||
ty: t,
|
||||
pat: pat,
|
||||
@ -2440,18 +2441,21 @@ pub impl Parser {
|
||||
|
||||
// used by the copy foo and ref foo patterns to give a good
|
||||
// error message when parsing mistakes like ref foo(a,b)
|
||||
fn parse_pat_ident(&self, refutable: bool,
|
||||
binding_mode: ast::binding_mode) -> ast::pat_ {
|
||||
fn parse_pat_ident(&self,
|
||||
refutable: bool,
|
||||
binding_mode: ast::binding_mode)
|
||||
-> ast::pat_ {
|
||||
if !is_plain_ident(&*self.token) {
|
||||
self.span_fatal(
|
||||
*self.last_span,
|
||||
~"expected identifier, found path");
|
||||
self.span_fatal(*self.last_span,
|
||||
~"expected identifier, found path");
|
||||
}
|
||||
// why a path here, and not just an identifier?
|
||||
let name = self.parse_path_without_tps();
|
||||
let sub = if self.eat(&token::AT) {
|
||||
Some(self.parse_pat(refutable))
|
||||
} else { None };
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// just to be friendly, if they write something like
|
||||
// ref Some(i)
|
||||
@ -4406,10 +4410,11 @@ pub impl Parser {
|
||||
// text that can't be parsed as an item
|
||||
// - mod_items uses extern_mod_allowed = true
|
||||
// - block_tail_ uses extern_mod_allowed = false
|
||||
fn parse_items_and_view_items(&self, first_item_attrs: ~[attribute],
|
||||
fn parse_items_and_view_items(&self,
|
||||
first_item_attrs: ~[attribute],
|
||||
mut extern_mod_allowed: bool,
|
||||
macros_allowed: bool)
|
||||
-> ParsedItemsAndViewItems {
|
||||
-> ParsedItemsAndViewItems {
|
||||
let mut attrs = vec::append(first_item_attrs,
|
||||
self.parse_outer_attributes());
|
||||
// First, parse view items.
|
||||
@ -4539,8 +4544,11 @@ pub impl Parser {
|
||||
|
||||
fn parse_str(&self) -> @~str {
|
||||
match *self.token {
|
||||
token::LIT_STR(s) => { self.bump(); self.id_to_str(s) }
|
||||
_ => self.fatal(~"expected string literal")
|
||||
token::LIT_STR(s) => {
|
||||
self.bump();
|
||||
self.id_to_str(s)
|
||||
}
|
||||
_ => self.fatal(~"expected string literal")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1718,19 +1718,6 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
|
||||
maybe_print_comment(s, decl.output.span.lo);
|
||||
}
|
||||
|
||||
pub fn mode_to_str(m: ast::mode) -> ~str {
|
||||
match m {
|
||||
ast::expl(ast::by_ref) => ~"&&",
|
||||
ast::expl(ast::by_copy) => ~"+",
|
||||
ast::infer(_) => ~""
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_arg_mode(s: @ps, m: ast::mode) {
|
||||
let ms = mode_to_str(m);
|
||||
if ms != ~"" { word(s.s, ms); }
|
||||
}
|
||||
|
||||
pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
|
||||
if !bounds.is_empty() {
|
||||
word(s.s, ~":");
|
||||
@ -1879,7 +1866,6 @@ pub fn print_mt(s: @ps, mt: &ast::mt) {
|
||||
|
||||
pub fn print_arg(s: @ps, input: ast::arg) {
|
||||
ibox(s, indent_unit);
|
||||
print_arg_mode(s, input.mode);
|
||||
if input.is_mutbl {
|
||||
word_space(s, ~"mut");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user