2012-12-03 16:48:01 -08:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-04-06 16:47:01 -07:00
|
|
|
use back::link::mangle_internal_name_by_path_and_seq;
|
2014-05-28 22:26:56 -07:00
|
|
|
use llvm::{ValueRef, get_param};
|
2013-04-06 14:01:56 -07:00
|
|
|
use middle::trans::adt;
|
2012-12-13 13:05:22 -08:00
|
|
|
use middle::trans::base::*;
|
|
|
|
use middle::trans::build::*;
|
2014-01-27 14:18:36 +02:00
|
|
|
use middle::trans::callee::ArgVals;
|
2012-12-23 17:41:37 -05:00
|
|
|
use middle::trans::callee;
|
2012-12-13 13:05:22 -08:00
|
|
|
use middle::trans::common::*;
|
|
|
|
use middle::trans::datum::*;
|
2012-12-23 17:41:37 -05:00
|
|
|
use middle::trans::glue;
|
2013-01-30 11:46:19 -08:00
|
|
|
use middle::trans::machine;
|
2012-12-23 17:41:37 -05:00
|
|
|
use middle::trans::meth;
|
2014-01-10 14:02:36 -08:00
|
|
|
use middle::trans::type_::Type;
|
2012-12-13 13:05:22 -08:00
|
|
|
use middle::trans::type_of::*;
|
2013-02-25 14:11:21 -05:00
|
|
|
use middle::ty;
|
2014-06-21 03:39:03 -07:00
|
|
|
use util::ppaux::ty_to_string;
|
2012-12-13 13:05:22 -08:00
|
|
|
|
2014-01-22 14:03:02 -05:00
|
|
|
use arena::TypedArena;
|
2014-02-26 12:58:41 -05:00
|
|
|
use libc::c_uint;
|
2013-09-02 03:45:37 +02:00
|
|
|
use syntax::ast::DefId;
|
2012-12-13 13:05:22 -08:00
|
|
|
use syntax::ast;
|
2014-02-14 07:07:09 +02:00
|
|
|
use syntax::ast_map;
|
2014-01-10 14:02:36 -08:00
|
|
|
use syntax::parse::token::{InternedString, special_idents};
|
|
|
|
use syntax::parse::token;
|
2013-06-16 22:52:44 +12:00
|
|
|
|
2014-09-06 19:13:04 +03:00
|
|
|
pub struct Reflector<'a, 'blk, 'tcx: 'blk> {
|
2012-06-07 13:51:35 -07:00
|
|
|
visitor_val: ValueRef,
|
2014-08-04 13:56:56 -07:00
|
|
|
visitor_items: &'a [ty::ImplOrTraitItem],
|
2014-09-06 19:13:04 +03:00
|
|
|
final_bcx: Block<'blk, 'tcx>,
|
2013-06-16 15:45:48 +12:00
|
|
|
tydesc_ty: Type,
|
2014-09-06 19:13:04 +03:00
|
|
|
bcx: Block<'blk, 'tcx>
|
2013-02-04 14:02:01 -08:00
|
|
|
}
|
2012-05-16 18:24:00 -07:00
|
|
|
|
2014-09-06 19:13:04 +03:00
|
|
|
impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn c_uint(&mut self, u: uint) -> ValueRef {
|
2012-06-07 19:42:22 -07:00
|
|
|
C_uint(self.bcx.ccx(), u)
|
2012-06-07 13:51:35 -07:00
|
|
|
}
|
|
|
|
|
2013-09-02 02:56:08 -04:00
|
|
|
pub fn c_bool(&mut self, b: bool) -> ValueRef {
|
2014-03-15 22:29:34 +02:00
|
|
|
C_bool(self.bcx.ccx(), b)
|
2013-09-02 02:56:08 -04:00
|
|
|
}
|
|
|
|
|
2014-01-10 14:02:36 -08:00
|
|
|
pub fn c_slice(&mut self, s: InternedString) -> ValueRef {
|
2013-01-04 23:06:25 -08:00
|
|
|
// We're careful to not use first class aggregates here because that
|
|
|
|
// will kick us off fast isel. (Issue #4352.)
|
|
|
|
let bcx = self.bcx;
|
2014-04-27 10:19:15 +12:00
|
|
|
let str_ty = ty::mk_str_slice(bcx.tcx(), ty::ReStatic, ast::MutImmutable);
|
2014-01-15 14:39:08 -05:00
|
|
|
let scratch = rvalue_scratch_datum(bcx, str_ty, "");
|
2014-01-10 14:02:36 -08:00
|
|
|
let len = C_uint(bcx.ccx(), s.get().len());
|
2014-04-03 16:26:08 -04:00
|
|
|
let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s, false), Type::i8p(bcx.ccx()));
|
2013-01-04 23:06:25 -08:00
|
|
|
Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
|
|
|
|
Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
|
|
|
|
scratch.val
|
2012-06-08 16:41:38 -07:00
|
|
|
}
|
|
|
|
|
2014-03-04 10:02:49 -08:00
|
|
|
pub fn c_size_and_align(&mut self, t: ty::t) -> Vec<ValueRef> {
|
2013-02-25 14:11:21 -05:00
|
|
|
let tr = type_of(self.bcx.ccx(), t);
|
2013-01-30 11:46:19 -08:00
|
|
|
let s = machine::llsize_of_real(self.bcx.ccx(), tr);
|
2014-08-06 11:59:40 +02:00
|
|
|
let a = align_of(self.bcx.ccx(), t);
|
2014-03-04 10:02:49 -08:00
|
|
|
return vec!(self.c_uint(s as uint),
|
|
|
|
self.c_uint(a as uint));
|
2012-06-11 18:33:58 -07:00
|
|
|
}
|
|
|
|
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef {
|
2012-06-19 18:35:56 -07:00
|
|
|
let bcx = self.bcx;
|
2012-07-10 15:25:58 -07:00
|
|
|
let static_ti = get_tydesc(bcx.ccx(), t);
|
2014-04-22 03:45:16 +03:00
|
|
|
glue::lazily_emit_visit_glue(bcx.ccx(), &*static_ti);
|
2013-06-16 15:45:48 +12:00
|
|
|
PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to())
|
2012-06-19 18:35:56 -07:00
|
|
|
}
|
|
|
|
|
2014-03-04 10:02:49 -08:00
|
|
|
pub fn c_mt(&mut self, mt: &ty::mt) -> Vec<ValueRef> {
|
|
|
|
vec!(self.c_uint(mt.mutbl as uint),
|
|
|
|
self.c_tydesc(mt.ty))
|
2012-06-19 18:35:56 -07:00
|
|
|
}
|
|
|
|
|
2013-06-27 15:04:22 +02:00
|
|
|
pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
|
2014-01-15 14:39:08 -05:00
|
|
|
let fcx = self.bcx.fcx;
|
2012-06-07 19:42:22 -07:00
|
|
|
let tcx = self.bcx.tcx();
|
2014-08-04 13:56:56 -07:00
|
|
|
let mth_idx = ty::impl_or_trait_item_idx(token::str_to_ident(format!(
|
2014-05-19 17:23:26 -07:00
|
|
|
"visit_{}", ty_name).as_slice()),
|
2014-08-04 13:56:56 -07:00
|
|
|
self.visitor_items.as_slice()).expect(
|
2014-06-02 15:49:42 -07:00
|
|
|
format!("couldn't find visit method for {}", ty_name).as_slice());
|
2014-08-04 13:56:56 -07:00
|
|
|
let method = match self.visitor_items[mth_idx] {
|
|
|
|
ty::MethodTraitItem(ref method) => (*method).clone(),
|
|
|
|
};
|
|
|
|
let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone());
|
2014-08-06 11:59:40 +02:00
|
|
|
debug!("Emit call visit method: visit_{}: {}", ty_name, ty_to_string(tcx, mth_ty));
|
2012-06-07 13:51:35 -07:00
|
|
|
let v = self.visitor_val;
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("passing {} args:", args.len());
|
2013-07-08 08:12:01 +02:00
|
|
|
let mut bcx = self.bcx;
|
2013-08-03 12:45:23 -04:00
|
|
|
for (i, a) in args.iter().enumerate() {
|
2014-06-21 03:39:03 -07:00
|
|
|
debug!("arg {}: {}", i, bcx.val_to_string(*a));
|
2012-06-08 16:41:38 -07:00
|
|
|
}
|
2013-07-08 08:12:01 +02:00
|
|
|
let result = unpack_result!(bcx, callee::trans_call_inner(
|
2014-03-05 00:26:51 +02:00
|
|
|
self.bcx, None, mth_ty,
|
2014-01-15 14:39:08 -05:00
|
|
|
|bcx, _| meth::trans_trait_callee_from_llval(bcx,
|
|
|
|
mth_ty,
|
|
|
|
mth_idx,
|
|
|
|
v),
|
2014-01-27 14:18:36 +02:00
|
|
|
ArgVals(args), None));
|
2014-01-15 14:39:08 -05:00
|
|
|
let next_bcx = fcx.new_temp_block("next");
|
2012-08-28 15:54:45 -07:00
|
|
|
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
|
2012-06-19 18:35:56 -07:00
|
|
|
self.bcx = next_bcx
|
2012-06-07 13:51:35 -07:00
|
|
|
}
|
|
|
|
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn bracketed(&mut self,
|
2013-06-27 15:04:22 +02:00
|
|
|
bracket_name: &str,
|
2013-05-31 15:17:22 -07:00
|
|
|
extra: &[ValueRef],
|
2013-11-19 13:22:03 -08:00
|
|
|
inner: |&mut Reflector|) {
|
2014-05-19 23:19:56 -07:00
|
|
|
self.visit(format!("enter_{}", bracket_name).as_slice(), extra);
|
2013-02-08 22:21:45 -08:00
|
|
|
inner(self);
|
2014-05-19 23:19:56 -07:00
|
|
|
self.visit(format!("leave_{}", bracket_name).as_slice(), extra);
|
2012-06-08 13:26:06 -07:00
|
|
|
}
|
|
|
|
|
2013-06-27 15:04:22 +02:00
|
|
|
pub fn leaf(&mut self, name: &str) {
|
2013-05-23 09:39:10 -07:00
|
|
|
self.visit(name, []);
|
2012-06-07 13:51:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Entrypoint
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn visit_ty(&mut self, t: ty::t) {
|
2012-06-08 13:26:06 -07:00
|
|
|
let bcx = self.bcx;
|
2014-03-15 22:29:34 +02:00
|
|
|
let tcx = bcx.tcx();
|
2014-06-21 03:39:03 -07:00
|
|
|
debug!("reflect::visit_ty {}", ty_to_string(bcx.tcx(), t));
|
2012-06-08 13:26:06 -07:00
|
|
|
|
2013-03-20 01:17:42 -04:00
|
|
|
match ty::get(t).sty {
|
2013-06-27 15:04:22 +02:00
|
|
|
ty::ty_bot => self.leaf("bot"),
|
|
|
|
ty::ty_nil => self.leaf("nil"),
|
|
|
|
ty::ty_bool => self.leaf("bool"),
|
2013-09-03 19:24:12 -04:00
|
|
|
ty::ty_char => self.leaf("char"),
|
2014-01-09 15:05:33 +02:00
|
|
|
ty::ty_int(ast::TyI) => self.leaf("int"),
|
|
|
|
ty::ty_int(ast::TyI8) => self.leaf("i8"),
|
|
|
|
ty::ty_int(ast::TyI16) => self.leaf("i16"),
|
|
|
|
ty::ty_int(ast::TyI32) => self.leaf("i32"),
|
|
|
|
ty::ty_int(ast::TyI64) => self.leaf("i64"),
|
|
|
|
ty::ty_uint(ast::TyU) => self.leaf("uint"),
|
|
|
|
ty::ty_uint(ast::TyU8) => self.leaf("u8"),
|
|
|
|
ty::ty_uint(ast::TyU16) => self.leaf("u16"),
|
|
|
|
ty::ty_uint(ast::TyU32) => self.leaf("u32"),
|
|
|
|
ty::ty_uint(ast::TyU64) => self.leaf("u64"),
|
|
|
|
ty::ty_float(ast::TyF32) => self.leaf("f32"),
|
|
|
|
ty::ty_float(ast::TyF64) => self.leaf("f64"),
|
2012-06-07 13:51:35 -07:00
|
|
|
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_open(_) | ty::ty_str | ty::ty_vec(_, None) | ty::ty_trait(..) => {
|
|
|
|
// Unfortunately we can't do anything here because at runtime we
|
|
|
|
// pass around the value by pointer (*u8). But unsized pointers are
|
|
|
|
// fat and so we can't just cast them to *u8 and back. So we have
|
2014-08-27 17:07:28 +12:00
|
|
|
// to work with the pointer directly (see ty_ptr/ty_rptr/ty_uniq).
|
2014-08-06 11:59:40 +02:00
|
|
|
fail!("Can't reflect unsized type")
|
|
|
|
}
|
|
|
|
// FIXME(15049) Reflection for unsized structs.
|
|
|
|
ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), t) => {
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
fail!("Can't reflect unsized type")
|
|
|
|
}
|
|
|
|
|
2014-04-29 13:10:23 +12:00
|
|
|
// Should rename to vec_*.
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_vec(ty, Some(sz)) => {
|
|
|
|
let mut extra = (vec!(self.c_uint(sz))).append(self.c_size_and_align(t).as_slice());
|
|
|
|
extra.push(self.c_tydesc(ty));
|
2014-05-19 17:23:26 -07:00
|
|
|
self.visit("evec_fixed", extra.as_slice())
|
2013-02-08 22:21:45 -08:00
|
|
|
}
|
2014-01-12 02:25:51 +02:00
|
|
|
// Should remove mt from box and uniq.
|
2013-12-30 18:57:48 -08:00
|
|
|
ty::ty_box(typ) => {
|
|
|
|
let extra = self.c_mt(&ty::mt {
|
|
|
|
ty: typ,
|
|
|
|
mutbl: ast::MutImmutable,
|
|
|
|
});
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("box", extra.as_slice())
|
2013-02-08 22:21:45 -08:00
|
|
|
}
|
2014-04-25 15:14:52 +12:00
|
|
|
ty::ty_ptr(ref mt) => {
|
2014-08-27 17:07:28 +12:00
|
|
|
match ty::get(mt.ty).sty {
|
|
|
|
ty::ty_vec(ty, None) => {
|
|
|
|
let extra = self.c_mt(&ty::mt{ty: ty, mutbl: mt.mutbl});
|
|
|
|
self.visit("evec_slice", extra.as_slice())
|
|
|
|
}
|
|
|
|
ty::ty_str => self.visit("estr_slice", &[]),
|
|
|
|
ty::ty_trait(..) => {
|
|
|
|
let extra = [
|
|
|
|
self.c_slice(token::intern_and_get_ident(
|
|
|
|
ty_to_string(tcx, t).as_slice()))
|
|
|
|
];
|
|
|
|
self.visit("trait", extra);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let extra = self.c_mt(mt);
|
|
|
|
self.visit("ptr", extra.as_slice())
|
|
|
|
}
|
|
|
|
}
|
2014-04-25 15:14:52 +12:00
|
|
|
}
|
2014-01-12 02:25:51 +02:00
|
|
|
ty::ty_uniq(typ) => {
|
2014-04-09 19:15:31 +12:00
|
|
|
match ty::get(typ).sty {
|
2014-06-11 17:18:57 +12:00
|
|
|
ty::ty_trait(..) => {
|
|
|
|
let extra = [
|
|
|
|
self.c_slice(token::intern_and_get_ident(
|
2014-06-21 03:39:03 -07:00
|
|
|
ty_to_string(tcx, t).as_slice()))
|
2014-06-11 17:18:57 +12:00
|
|
|
];
|
|
|
|
self.visit("trait", extra);
|
|
|
|
}
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
// FIXME(15049) allow reflection of Box<[T]>. You'll need to
|
|
|
|
// restore visit_evec_uniq.
|
|
|
|
ty::ty_vec(_, None) => {
|
|
|
|
fail!("Box<[T]> theoretically doesn't exist, so don't try to reflect it")
|
|
|
|
}
|
|
|
|
ty::ty_str => fail!("Can't reflect Box<str> which shouldn't be used anyway"),
|
2014-04-09 19:15:31 +12:00
|
|
|
_ => {
|
|
|
|
let extra = self.c_mt(&ty::mt {
|
|
|
|
ty: typ,
|
|
|
|
mutbl: ast::MutImmutable,
|
|
|
|
});
|
|
|
|
self.visit("uniq", extra.as_slice())
|
|
|
|
}
|
|
|
|
}
|
2013-02-08 22:21:45 -08:00
|
|
|
}
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_rptr(_, ref mt) => {
|
2014-04-09 19:15:31 +12:00
|
|
|
match ty::get(mt.ty).sty {
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_vec(ty, None) => {
|
|
|
|
let extra = self.c_mt(&ty::mt{ty: ty, mutbl: mt.mutbl});
|
2014-04-25 15:14:52 +12:00
|
|
|
self.visit("evec_slice", extra.as_slice())
|
2014-04-09 19:15:31 +12:00
|
|
|
}
|
2014-05-19 17:23:26 -07:00
|
|
|
ty::ty_str => self.visit("estr_slice", &[]),
|
2014-06-11 17:18:57 +12:00
|
|
|
ty::ty_trait(..) => {
|
|
|
|
let extra = [
|
|
|
|
self.c_slice(token::intern_and_get_ident(
|
2014-06-21 03:39:03 -07:00
|
|
|
ty_to_string(tcx, t).as_slice()))
|
2014-06-11 17:18:57 +12:00
|
|
|
];
|
|
|
|
self.visit("trait", extra);
|
|
|
|
}
|
2014-04-09 19:15:31 +12:00
|
|
|
_ => {
|
|
|
|
let extra = self.c_mt(mt);
|
|
|
|
self.visit("rptr", extra.as_slice())
|
|
|
|
}
|
|
|
|
}
|
2012-06-07 13:51:35 -07:00
|
|
|
}
|
|
|
|
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_tup(ref tys) => {
|
2014-03-30 23:53:26 -04:00
|
|
|
let extra = (vec!(self.c_uint(tys.len())))
|
|
|
|
.append(self.c_size_and_align(t).as_slice());
|
2014-03-08 21:36:22 +01:00
|
|
|
self.bracketed("tup", extra.as_slice(), |this| {
|
2013-08-03 12:45:23 -04:00
|
|
|
for (i, t) in tys.iter().enumerate() {
|
2014-03-04 10:02:49 -08:00
|
|
|
let extra = vec!(this.c_uint(i), this.c_tydesc(*t));
|
2014-03-08 21:36:22 +01:00
|
|
|
this.visit("tup_field", extra.as_slice());
|
2013-02-08 22:21:45 -08:00
|
|
|
}
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2012-06-08 13:26:06 -07:00
|
|
|
}
|
|
|
|
|
2013-01-31 17:12:29 -08:00
|
|
|
// FIXME (#2594): fetch constants out of intrinsic
|
|
|
|
// FIXME (#4809): visitor should break out bare fns from other fns
|
|
|
|
ty::ty_closure(ref fty) => {
|
2014-04-06 18:04:40 -07:00
|
|
|
let pureval = ast_fn_style_constant(fty.fn_style);
|
2014-04-11 18:03:10 +03:00
|
|
|
let sigilval = match fty.store {
|
|
|
|
ty::UniqTraitStore => 2u,
|
|
|
|
ty::RegionTraitStore(..) => 4u,
|
|
|
|
};
|
2013-01-31 17:12:29 -08:00
|
|
|
let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
|
2014-03-04 10:02:49 -08:00
|
|
|
let extra = vec!(self.c_uint(pureval),
|
2013-01-31 17:12:29 -08:00
|
|
|
self.c_uint(sigilval),
|
2013-05-14 18:52:12 +09:00
|
|
|
self.c_uint(fty.sig.inputs.len()),
|
2014-03-04 10:02:49 -08:00
|
|
|
self.c_uint(retval));
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("enter_fn", extra.as_slice());
|
2013-01-31 17:12:29 -08:00
|
|
|
self.visit_sig(retval, &fty.sig);
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("leave_fn", extra.as_slice());
|
2013-01-31 17:12:29 -08:00
|
|
|
}
|
|
|
|
|
2012-06-21 16:44:10 -07:00
|
|
|
// FIXME (#2594): fetch constants out of intrinsic:: for the
|
|
|
|
// numbers.
|
2013-01-31 17:12:29 -08:00
|
|
|
ty::ty_bare_fn(ref fty) => {
|
2014-04-06 18:04:40 -07:00
|
|
|
let pureval = ast_fn_style_constant(fty.fn_style);
|
2013-01-31 17:12:29 -08:00
|
|
|
let sigilval = 0u;
|
2013-01-08 06:21:19 -08:00
|
|
|
let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
|
2014-03-04 10:02:49 -08:00
|
|
|
let extra = vec!(self.c_uint(pureval),
|
2013-01-31 17:12:29 -08:00
|
|
|
self.c_uint(sigilval),
|
2013-05-14 18:52:12 +09:00
|
|
|
self.c_uint(fty.sig.inputs.len()),
|
2014-03-04 10:02:49 -08:00
|
|
|
self.c_uint(retval));
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("enter_fn", extra.as_slice());
|
2013-01-31 17:12:29 -08:00
|
|
|
self.visit_sig(retval, &fty.sig);
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("leave_fn", extra.as_slice());
|
2012-06-08 13:26:06 -07:00
|
|
|
}
|
|
|
|
|
2012-12-10 13:47:54 -08:00
|
|
|
ty::ty_struct(did, ref substs) => {
|
2013-02-08 22:21:45 -08:00
|
|
|
let fields = ty::struct_fields(tcx, did, substs);
|
2013-09-02 02:56:08 -04:00
|
|
|
let mut named_fields = false;
|
|
|
|
if !fields.is_empty() {
|
2014-03-08 21:36:22 +01:00
|
|
|
named_fields = fields.get(0).ident.name !=
|
|
|
|
special_idents::unnamed_field.name;
|
2013-09-02 02:56:08 -04:00
|
|
|
}
|
2012-06-14 19:53:56 -07:00
|
|
|
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
// This and the type_is_sized check on individual field types are
|
|
|
|
// because we cannot reflect unsized types (see note above). We
|
|
|
|
// just pretend the unsized field does not exist and print nothing.
|
|
|
|
// This is sub-optimal.
|
2014-08-06 11:59:40 +02:00
|
|
|
let len = fields.len();
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
|
2014-03-30 23:53:26 -04:00
|
|
|
let extra = (vec!(
|
2014-05-09 18:45:36 -07:00
|
|
|
self.c_slice(
|
2014-06-21 03:39:03 -07:00
|
|
|
token::intern_and_get_ident(ty_to_string(tcx,
|
2014-05-09 18:45:36 -07:00
|
|
|
t).as_slice())),
|
2014-01-10 14:02:36 -08:00
|
|
|
self.c_bool(named_fields),
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
self.c_uint(len)
|
2014-03-30 23:53:26 -04:00
|
|
|
)).append(self.c_size_and_align(t).as_slice());
|
2014-03-08 21:36:22 +01:00
|
|
|
self.bracketed("class", extra.as_slice(), |this| {
|
2013-08-03 12:45:23 -04:00
|
|
|
for (i, field) in fields.iter().enumerate() {
|
2014-08-06 11:59:40 +02:00
|
|
|
let extra = (vec!(
|
|
|
|
this.c_uint(i),
|
|
|
|
this.c_slice(token::get_ident(field.ident)),
|
|
|
|
this.c_bool(named_fields)
|
|
|
|
)).append(this.c_mt(&field.mt).as_slice());
|
|
|
|
this.visit("class_field", extra.as_slice());
|
2013-02-08 22:21:45 -08:00
|
|
|
}
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2012-06-08 15:35:55 -07:00
|
|
|
}
|
|
|
|
|
2012-06-21 16:44:10 -07:00
|
|
|
// FIXME (#2595): visiting all the variants in turn is probably
|
|
|
|
// not ideal. It'll work but will get costly on big enums. Maybe
|
|
|
|
// let the visitor tell us if it wants to visit only a particular
|
|
|
|
// variant?
|
2012-08-10 10:49:31 -07:00
|
|
|
ty::ty_enum(did, ref substs) => {
|
2013-04-06 14:01:56 -07:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
let repr = adt::represent_type(bcx.ccx(), t);
|
2014-03-15 22:29:34 +02:00
|
|
|
let variants = ty::substd_enum_variants(ccx.tcx(), did, substs);
|
2013-06-16 15:45:48 +12:00
|
|
|
let llptrty = type_of(ccx, t).ptr_to();
|
2014-03-15 22:29:34 +02:00
|
|
|
let opaquety = ty::get_opaque_ty(ccx.tcx()).unwrap();
|
|
|
|
let opaqueptrty = ty::mk_ptr(ccx.tcx(), ty::mt { ty: opaquety,
|
2013-09-02 03:45:37 +02:00
|
|
|
mutbl: ast::MutImmutable });
|
2013-04-06 16:47:01 -07:00
|
|
|
|
2013-04-07 20:47:44 -07:00
|
|
|
let make_get_disr = || {
|
2014-02-14 07:07:09 +02:00
|
|
|
let sym = mangle_internal_name_by_path_and_seq(
|
|
|
|
ast_map::Values([].iter()).chain(None), "get_disr");
|
2013-04-24 01:29:46 -07:00
|
|
|
|
2014-09-05 09:18:53 -07:00
|
|
|
let fn_ty = ty::mk_ctor_fn(ccx.tcx(), ast::DUMMY_NODE_ID,
|
2014-05-21 15:07:48 -04:00
|
|
|
[opaqueptrty], ty::mk_u64());
|
2014-05-09 18:45:36 -07:00
|
|
|
let llfdecl = decl_internal_rust_fn(ccx,
|
2014-05-21 15:07:48 -04:00
|
|
|
fn_ty,
|
2014-05-09 18:45:36 -07:00
|
|
|
sym.as_slice());
|
2014-01-22 14:03:02 -05:00
|
|
|
let arena = TypedArena::new();
|
2014-05-14 20:53:48 -04:00
|
|
|
let empty_param_substs = param_substs::empty();
|
2014-08-11 19:16:00 -07:00
|
|
|
let fcx = new_fn_ctxt(ccx, llfdecl, ast::DUMMY_NODE_ID, false,
|
2014-05-14 20:53:48 -04:00
|
|
|
ty::mk_u64(), &empty_param_substs,
|
2014-08-11 16:55:13 -07:00
|
|
|
None, &arena);
|
2014-07-05 01:52:12 +02:00
|
|
|
let bcx = init_function(&fcx, false, ty::mk_u64());
|
2014-01-07 08:54:58 -08:00
|
|
|
|
2014-05-28 22:26:56 -07:00
|
|
|
// we know the return type of llfdecl is an int here, so
|
|
|
|
// no need for a special check to see if the return type
|
|
|
|
// is immediate.
|
|
|
|
let arg = get_param(llfdecl, fcx.arg_pos(0u) as c_uint);
|
2013-04-07 20:47:44 -07:00
|
|
|
let arg = BitCast(bcx, arg, llptrty);
|
2014-04-22 03:03:02 +03:00
|
|
|
let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx)));
|
2014-08-11 19:16:00 -07:00
|
|
|
assert!(!fcx.needs_ret_allocas);
|
|
|
|
let ret_slot = fcx.get_ret_slot(bcx, ty::mk_u64(), "ret_slot");
|
|
|
|
Store(bcx, ret, ret_slot);
|
2013-12-20 20:41:54 -08:00
|
|
|
match fcx.llreturn.get() {
|
2014-01-15 14:39:08 -05:00
|
|
|
Some(llreturn) => Br(bcx, llreturn),
|
|
|
|
None => {}
|
2013-07-13 03:25:46 +02:00
|
|
|
};
|
2014-07-05 21:47:14 +02:00
|
|
|
finish_fn(&fcx, bcx, ty::mk_u64());
|
2013-04-07 20:47:44 -07:00
|
|
|
llfdecl
|
2013-04-06 16:47:01 -07:00
|
|
|
};
|
2012-06-08 15:35:55 -07:00
|
|
|
|
2014-03-30 23:53:26 -04:00
|
|
|
let enum_args = (vec!(self.c_uint(variants.len()), make_get_disr()))
|
|
|
|
.append(self.c_size_and_align(t).as_slice());
|
2014-03-08 21:36:22 +01:00
|
|
|
self.bracketed("enum", enum_args.as_slice(), |this| {
|
2013-08-03 12:45:23 -04:00
|
|
|
for (i, v) in variants.iter().enumerate() {
|
2014-02-14 07:07:09 +02:00
|
|
|
let name = token::get_ident(v.name);
|
2014-03-15 22:29:34 +02:00
|
|
|
let variant_args = [this.c_uint(i),
|
|
|
|
C_u64(ccx, v.disr_val),
|
2013-05-14 18:52:12 +09:00
|
|
|
this.c_uint(v.args.len()),
|
2014-03-15 22:29:34 +02:00
|
|
|
this.c_slice(name)];
|
2014-03-08 21:36:22 +01:00
|
|
|
this.bracketed("enum_variant",
|
2014-03-15 22:29:34 +02:00
|
|
|
variant_args,
|
2014-03-08 21:36:22 +01:00
|
|
|
|this| {
|
2013-08-03 12:45:23 -04:00
|
|
|
for (j, a) in v.args.iter().enumerate() {
|
2013-04-06 14:01:56 -07:00
|
|
|
let bcx = this.bcx;
|
2013-04-06 16:47:01 -07:00
|
|
|
let null = C_null(llptrty);
|
2014-04-22 03:03:02 +03:00
|
|
|
let ptr = adt::trans_field_ptr(bcx, &*repr, null, v.disr_val, j);
|
2013-06-13 19:19:50 +12:00
|
|
|
let offset = p2i(ccx, ptr);
|
2014-03-15 22:29:34 +02:00
|
|
|
let field_args = [this.c_uint(j),
|
2013-04-06 14:01:56 -07:00
|
|
|
offset,
|
2014-03-15 22:29:34 +02:00
|
|
|
this.c_tydesc(*a)];
|
2014-03-08 21:36:22 +01:00
|
|
|
this.visit("enum_variant_field",
|
2014-03-15 22:29:34 +02:00
|
|
|
field_args);
|
2012-06-19 18:35:56 -07:00
|
|
|
}
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2012-06-08 15:35:55 -07:00
|
|
|
}
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2012-06-08 15:35:55 -07:00
|
|
|
}
|
2012-06-08 13:26:06 -07:00
|
|
|
|
2013-09-02 01:15:03 -04:00
|
|
|
// Miscellaneous extra types
|
2013-06-27 15:04:22 +02:00
|
|
|
ty::ty_infer(_) => self.leaf("infer"),
|
|
|
|
ty::ty_err => self.leaf("err"),
|
2014-05-28 22:26:56 -07:00
|
|
|
ty::ty_unboxed_closure(..) => self.leaf("err"),
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_param(ref p) => {
|
2014-03-04 10:02:49 -08:00
|
|
|
let extra = vec!(self.c_uint(p.idx));
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("param", extra.as_slice())
|
2013-02-08 22:21:45 -08:00
|
|
|
}
|
2012-06-07 13:51:35 -07:00
|
|
|
}
|
2012-05-14 17:57:39 -07:00
|
|
|
}
|
2013-01-31 17:12:29 -08:00
|
|
|
|
2013-05-31 15:17:22 -07:00
|
|
|
pub fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) {
|
2013-08-03 12:45:23 -04:00
|
|
|
for (i, arg) in sig.inputs.iter().enumerate() {
|
2013-04-24 01:29:46 -07:00
|
|
|
let modeval = 5u; // "by copy"
|
2014-03-04 10:02:49 -08:00
|
|
|
let extra = vec!(self.c_uint(i),
|
2013-01-31 17:12:29 -08:00
|
|
|
self.c_uint(modeval),
|
2014-03-04 10:02:49 -08:00
|
|
|
self.c_tydesc(*arg));
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("fn_input", extra.as_slice());
|
2013-01-31 17:12:29 -08:00
|
|
|
}
|
2014-03-04 10:02:49 -08:00
|
|
|
let extra = vec!(self.c_uint(retval),
|
2013-10-25 01:56:34 -04:00
|
|
|
self.c_bool(sig.variadic),
|
2014-03-04 10:02:49 -08:00
|
|
|
self.c_tydesc(sig.output));
|
2014-03-08 21:36:22 +01:00
|
|
|
self.visit("fn_output", extra.as_slice());
|
2013-01-31 17:12:29 -08:00
|
|
|
}
|
2012-05-14 17:57:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Emit a sequence of calls to visit_ty::visit_foo
|
2014-09-06 19:13:04 +03:00
|
|
|
pub fn emit_calls_to_trait_visit_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|
|
|
t: ty::t,
|
|
|
|
visitor_val: ValueRef,
|
|
|
|
visitor_trait_id: DefId)
|
|
|
|
-> Block<'blk, 'tcx> {
|
2014-01-15 14:39:08 -05:00
|
|
|
let fcx = bcx.fcx;
|
|
|
|
let final = fcx.new_temp_block("final");
|
2014-03-15 22:29:34 +02:00
|
|
|
let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
|
2013-02-25 14:11:21 -05:00
|
|
|
let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
|
2014-08-04 13:56:56 -07:00
|
|
|
let visitor_items = ty::trait_items(bcx.tcx(), visitor_trait_id);
|
2013-02-04 14:02:01 -08:00
|
|
|
let mut r = Reflector {
|
2012-06-07 13:51:35 -07:00
|
|
|
visitor_val: visitor_val,
|
2014-08-04 13:56:56 -07:00
|
|
|
visitor_items: visitor_items.as_slice(),
|
2012-06-19 18:35:56 -07:00
|
|
|
final_bcx: final,
|
|
|
|
tydesc_ty: tydesc_ty,
|
2013-02-04 14:02:01 -08:00
|
|
|
bcx: bcx
|
|
|
|
};
|
2012-06-07 13:51:35 -07:00
|
|
|
r.visit_ty(t);
|
2012-06-19 18:35:56 -07:00
|
|
|
Br(r.bcx, final.llbb);
|
2012-08-01 17:30:05 -07:00
|
|
|
return final;
|
2012-05-14 17:57:39 -07:00
|
|
|
}
|
2012-11-04 20:41:00 -08:00
|
|
|
|
2014-04-06 18:04:40 -07:00
|
|
|
pub fn ast_fn_style_constant(fn_style: ast::FnStyle) -> uint {
|
|
|
|
match fn_style {
|
2014-01-09 15:05:33 +02:00
|
|
|
ast::UnsafeFn => 1u,
|
2014-04-06 18:04:40 -07:00
|
|
|
ast::NormalFn => 2u,
|
2012-11-04 20:41:00 -08:00
|
|
|
}
|
2012-11-28 17:33:30 -08:00
|
|
|
}
|