}
}
+ pub fn trans_empty() -> Substs {
+ Substs {
+ self_ty: None,
+ tps: Vec::new(),
+ regions: ErasedRegions
+ }
+ }
+
pub fn is_noop(&self) -> bool {
let regions_is_noop = match self.regions {
ErasedRegions => false, // may be used to canonicalize
id: ast::NodeId,
has_env: bool,
output_type: ty::t,
- param_substs: Option<&'a param_substs>,
+ param_substs: &'a param_substs,
sp: Option<Span>,
block_arena: &'a TypedArena<Block<'a>>)
-> FunctionContext<'a> {
- for p in param_substs.iter() { p.validate(); }
+ param_substs.validate();
debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
if id == -1 {
} else {
ccx.tcx.map.path_to_str(id).to_string()
},
- id, param_substs.map(|s| s.repr(ccx.tcx())));
+ id, param_substs.repr(ccx.tcx()));
let substd_output_type = output_type.substp(ccx.tcx(), param_substs);
let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
decl: &ast::FnDecl,
body: &ast::Block,
llfndecl: ValueRef,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
id: ast::NodeId,
_attributes: &[ast::Attribute],
output_type: ty::t,
set_uwtable(llfndecl);
debug!("trans_closure(..., param_substs={})",
- param_substs.map(|s| s.repr(ccx.tcx())));
+ param_substs.repr(ccx.tcx()));
let has_env = match ty::get(ty::node_id_to_type(ccx.tcx(), id)).sty {
ty::ty_closure(_) => true,
id,
has_env,
output_type,
- param_substs.map(|s| &*s),
+ param_substs,
Some(body.span),
&arena);
init_function(&fcx, false, output_type);
decl: &ast::FnDecl,
body: &ast::Block,
llfndecl: ValueRef,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
id: ast::NodeId,
attrs: &[ast::Attribute]) {
let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id).to_string());
- debug!("trans_fn(param_substs={})", param_substs.map(|s| s.repr(ccx.tcx())));
+ debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
let _icx = push_ctxt("trans_fn");
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), id));
trans_closure(ccx, decl, body, llfndecl,
variant: &ast::Variant,
_args: &[ast::VariantArg],
disr: ty::Disr,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
llfndecl: ValueRef) {
let _icx = push_ctxt("trans_enum_variant");
pub fn trans_tuple_struct(ccx: &CrateContext,
_fields: &[ast::StructField],
ctor_id: ast::NodeId,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
llfndecl: ValueRef) {
let _icx = push_ctxt("trans_tuple_struct");
fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
ctor_id: ast::NodeId,
disr: ty::Disr,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
llfndecl: ValueRef) {
let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
let ctor_ty = ctor_ty.substp(ccx.tcx(), param_substs);
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
- param_substs.map(|s| &*s), None, &arena);
+ param_substs, None, &arena);
init_function(&fcx, false, result_ty);
let arg_tys = ty::ty_fn_args(ctor_ty);
ast::TupleVariantKind(ref args) if args.len() > 0 => {
let llfn = get_item_val(ccx, variant.node.id);
trans_enum_variant(ccx, id, variant, args.as_slice(),
- disr_val, None, llfn);
+ disr_val, ¶m_substs::empty(), llfn);
}
ast::TupleVariantKind(_) => {
// Nothing to do.
decl,
body,
llfn,
- None,
+ ¶m_substs::empty(),
item.id,
item.attrs.as_slice());
} else {
Some(ctor_id) if struct_def.fields.len() > 0 => {
let llfndecl = get_item_val(ccx, ctor_id);
trans_tuple_struct(ccx, struct_def.fields.as_slice(),
- ctor_id, None, llfndecl);
+ ctor_id, ¶m_substs::empty(), llfndecl);
}
Some(_) | None => {}
}
def_id: ast::DefId,
ref_id: ast::NodeId,
substs: subst::Substs,
- vtables: Option<typeck::vtable_res>)
+ vtables: typeck::vtable_res)
-> Callee<'a> {
Callee {bcx: bcx,
data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ExprId(ref_id),
impl_id: ast::DefId,
method: &ty::Method,
substs: &subst::Substs,
- impl_vtables: Option<typeck::vtable_res>)
- -> (typeck::vtable_res, typeck::vtable_param_res) {
+ impl_vtables: typeck::vtable_res)
+ -> (typeck::vtable_res, typeck::vtable_param_res)
+{
// Get the vtables that the impl implements the trait at
let impl_res = ty::lookup_impl_vtables(bcx.tcx(), impl_id);
};
let mut param_vtables = resolve_vtables_under_param_substs(
- bcx.tcx(), Some(¶m_substs), impl_res.trait_vtables.as_slice());
+ bcx.tcx(), ¶m_substs, impl_res.trait_vtables.as_slice());
// Now we pull any vtables for parameters on the actual method.
let num_method_vtables = method.generics.type_param_defs().len();
- match impl_vtables {
- Some(ref vtables) => {
- let num_impl_type_parameters =
- vtables.len() - num_method_vtables;
- param_vtables.push_all(vtables.tailn(num_impl_type_parameters))
- },
- None => {
- param_vtables.extend(range(0, num_method_vtables).map(
- |_| -> typeck::vtable_param_res {
- Vec::new()
- }
- ))
- }
- }
+ let num_impl_type_parameters = impl_vtables.len() - num_method_vtables;
+ param_vtables.push_all(impl_vtables.tailn(num_impl_type_parameters));
let self_vtables = resolve_param_vtables_under_param_substs(
- bcx.tcx(), Some(¶m_substs), impl_res.self_vtables.as_slice());
+ bcx.tcx(), ¶m_substs, impl_res.self_vtables.as_slice());
(param_vtables, self_vtables)
}
def_id: ast::DefId, // def id of fn
node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A
substs: subst::Substs, // values for fn's ty params
- vtables: Option<typeck::vtable_res>) // vtables for the call
+ vtables: typeck::vtable_res) // vtables for the call
-> ValueRef {
/*!
* Translates a reference to a fn/method item, monomorphizing and
self_vtables.repr(tcx), param_vtables.repr(tcx));
(true, source_id,
- new_substs, Some(self_vtables), Some(param_vtables))
+ new_substs, Some(self_vtables), param_vtables)
}
};
did,
0,
subst::Substs::empty(),
- None)
+ Vec::new())
},
ArgVals(args),
dest)
let _icx = push_ctxt("closure::get_wrapper_for_bare_fn");
let arena = TypedArena::new();
- let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output, None, None, &arena);
+ let empty_param_substs = param_substs::empty();
+ let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output,
+ &empty_param_substs, None, &arena);
init_function(&fcx, true, f.sig.output);
let bcx = fcx.entry_bcx.borrow().clone().unwrap();
// will only be set in the case of default methods.
pub struct param_substs {
pub substs: subst::Substs,
- pub vtables: Option<typeck::vtable_res>,
+ pub vtables: typeck::vtable_res,
pub self_vtables: Option<typeck::vtable_param_res>
}
impl param_substs {
+ pub fn empty() -> param_substs {
+ param_substs {
+ substs: subst::Substs::trans_empty(),
+ vtables: Vec::new(),
+ self_vtables: None
+ }
+ }
+
pub fn validate(&self) {
for t in self.substs.tps.iter() {
assert!(!ty::type_needs_infer(*t));
}
pub trait SubstP {
- fn substp(&self, tcx: &ty::ctxt, param_substs: Option<¶m_substs>)
+ fn substp(&self, tcx: &ty::ctxt, param_substs: ¶m_substs)
-> Self;
}
impl<T:Subst+Clone> SubstP for T {
- fn substp(&self, tcx: &ty::ctxt, param_substs: Option<¶m_substs>)
- -> T {
- match param_substs {
- Some(substs) => {
- self.subst(tcx, &substs.substs)
- }
- None => {
- (*self).clone()
- }
- }
+ fn substp(&self, tcx: &ty::ctxt, substs: ¶m_substs) -> T {
+ self.subst(tcx, &substs.substs)
}
}
// If this function is being monomorphized, this contains the type
// substitutions used.
- pub param_substs: Option<&'a param_substs>,
+ pub param_substs: &'a param_substs,
// The source span and nesting context where this function comes from, for
// error reporting and symbol generation.
}
pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
- match bcx.fcx.param_substs {
- Some(ref substs) => {
- t.subst(bcx.tcx(), &substs.substs)
- }
- _ => {
- assert!(!ty::type_has_params(t));
- assert!(!ty::type_has_self(t));
- t
- }
- }
+ t.subst(bcx.tcx(), &bcx.fcx.param_substs.substs)
}
pub fn node_id_type(bcx: &Block, id: ast::NodeId) -> ty::t {
}
pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
- -> Option<typeck::vtable_res> {
+ -> typeck::vtable_res {
bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
resolve_vtables_in_fn_ctxt(bcx.fcx, vts.as_slice())
- })
+ }).unwrap_or_else(|| Vec::new())
}
// Apply the typaram substitutions in the FunctionContext to some
}
pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
vts: &[typeck::vtable_param_res])
-> typeck::vtable_res {
vts.iter().map(|ds| {
pub fn resolve_param_vtables_under_param_substs(
tcx: &ty::ctxt,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
ds: &[typeck::vtable_origin])
-> typeck::vtable_param_res {
ds.iter().map(|d| {
pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
vt: &typeck::vtable_origin)
-> typeck::vtable_origin {
match *vt {
resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
}
typeck::vtable_param(n_param, n_bound) => {
- match param_substs {
- Some(substs) => {
- find_vtable(tcx, substs, n_param, n_bound)
- }
- _ => {
- tcx.sess.bug(format!(
- "resolve_vtable_under_param_substs: asked to lookup \
- but no vtables in the fn_ctxt!").as_slice())
- }
- }
+ find_vtable(tcx, param_substs, n_param, n_bound)
}
}
}
let param_bounds = match n_param {
typeck::param_self => ps.self_vtables.as_ref().expect("self vtables missing"),
typeck::param_numbered(n) => {
- let tables = ps.vtables.as_ref()
- .expect("vtables missing where they are needed");
- tables.get(n)
+ ps.vtables.get(n)
}
};
param_bounds.get(n_bound).clone()
/// indicates why no debuginfo should be created for the function.
pub fn create_function_debug_context(cx: &CrateContext,
fn_ast_id: ast::NodeId,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
llfn: ValueRef) -> FunctionDebugContext {
if cx.sess().opts.debuginfo == NoDebugInfo {
return FunctionDebugContext { repr: DebugInfoDisabled };
fn get_function_signature(cx: &CrateContext,
fn_ast_id: ast::NodeId,
fn_decl: &ast::FnDecl,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
error_span: Span) -> DIArray {
if cx.sess().opts.debuginfo == LimitedDebugInfo {
return create_DIArray(DIB(cx), []);
fn get_template_parameters(cx: &CrateContext,
generics: &ast::Generics,
- param_substs: Option<¶m_substs>,
+ param_substs: ¶m_substs,
file_metadata: DIFile,
name_to_append_suffix_to: &mut String)
-> DIArray {
- let self_type = match param_substs {
- Some(param_substs) => param_substs.substs.self_ty,
- _ => None
- };
+ let self_type = param_substs.substs.self_ty;
// Only true for static default methods:
let has_self_type = self_type.is_some();
}
// Handle other generic parameters
- let actual_types = match param_substs {
- Some(param_substs) => ¶m_substs.substs.tps,
- None => {
- return create_DIArray(DIB(cx), template_params.as_slice());
- }
- };
-
+ let actual_types = ¶m_substs.substs.tps;
for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
let actual_type = *actual_types.get(index);
// Add actual type name to <...> clause of function name
let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
base::set_llvm_fn_attrs(attrs, llfn);
- base::trans_fn(ccx, decl, body, llfn, None, id, []);
+ base::trans_fn(ccx, decl, body, llfn, ¶m_substs::empty(), id, []);
llfn
}
let _s = StatRecorder::new(ccx, glue_name);
let arena = TypedArena::new();
- let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(), None, None, &arena);
+ let empty_param_substs = param_substs::empty();
+ let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(),
+ &empty_param_substs, None, &arena);
init_function(&fcx, false, ty::mk_nil());
if num_type_params == 0 {
let llfn = get_item_val(ccx, mth.id);
- trans_fn(ccx, mth.decl, mth.body, llfn, None, mth.id, []);
+ trans_fn(ccx, mth.decl, mth.body, llfn,
+ ¶m_substs::empty(), mth.id, []);
}
local_def(mth.id)
}
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx, decl, item.id, false, output_type,
- Some(&*substs), Some(item.span), &arena);
+ substs, Some(item.span), &arena);
init_function(&fcx, true, output_type);
set_always_inline(fcx.llfn);
if method.generics.ty_params.len() == 0u {
let llfn = get_item_val(ccx, method.id);
trans_fn(ccx, method.decl, method.body,
- llfn, None, method.id, []);
+ llfn, ¶m_substs::empty(), method.id, []);
} else {
let mut v = TransItemVisitor{ ccx: ccx };
visit::walk_method_helper(&mut v, *method, ());
param_num: p,
bound_num: b
}) => {
- match bcx.fcx.param_substs {
- Some(substs) => {
- ty::populate_implementations_for_trait_if_necessary(
- bcx.tcx(),
- trait_id);
-
- let vtbl = find_vtable(bcx.tcx(), substs, p, b);
- trans_monomorphized_callee(bcx, method_call,
- trait_id, off, vtbl)
- }
- // how to get rid of this?
- None => fail!("trans_method_callee: missing param_substs")
- }
+ ty::populate_implementations_for_trait_if_necessary(
+ bcx.tcx(),
+ trait_id);
+
+ let vtbl = find_vtable(bcx.tcx(), bcx.fcx.param_substs, p, b);
+ trans_monomorphized_callee(bcx, method_call,
+ trait_id, off, vtbl)
}
typeck::MethodObject(ref mt) => {
let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id),
callee_substs,
- Some(callee_origins));
+ callee_origins);
let callee_ty = node_id_type(bcx, expr_id);
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
mth_id,
MethodCall(method_call),
callee_substs,
- Some(callee_origins));
+ callee_origins);
Callee { bcx: bcx, data: Fn(llfn) }
}
MethodCall(method_call) => method_call
};
let mut vtables = rcvr_origins;
- match node_vtables(bcx, vtable_key) {
- Some(vt) => {
- let start = vt.len() - n_m_tps;
- vtables.extend(vt.move_iter().skip(start));
- }
- None => {
- vtables.extend(range(0, n_m_tps).map(
- |_| -> typeck::vtable_param_res {
- Vec::new()
- }
- ));
- }
- }
+ let vt = node_vtables(bcx, vtable_key);
+ let start = vt.len() - n_m_tps;
+ vtables.extend(vt.move_iter().skip(start));
let ty_substs = subst::Substs {
tps: tps,
C_null(Type::nil(ccx).ptr_to())
} else {
trans_fn_ref_with_vtables(bcx, m_id, ExprId(0),
- substs.clone(), Some(vtables.clone()))
+ substs.clone(), vtables.clone())
}
}).collect()
}
pub fn monomorphic_fn(ccx: &CrateContext,
fn_id: ast::DefId,
real_substs: &subst::Substs,
- vtables: Option<typeck::vtable_res>,
+ vtables: typeck::vtable_res,
self_vtables: Option<typeck::vtable_param_res>,
ref_id: Option<ast::NodeId>)
-> (ValueRef, bool) {
} => {
let d = mk_lldecl();
set_llvm_fn_attrs(i.attrs.as_slice(), d);
- trans_fn(ccx, decl, body, d, Some(&psubsts), fn_id.node, []);
+ trans_fn(ccx, decl, body, d, &psubsts, fn_id.node, []);
d
}
_ => {
v,
args.as_slice(),
this_tv.disr_val,
- Some(&psubsts),
+ &psubsts,
d);
}
ast::StructVariantKind(_) =>
ast_map::NodeMethod(mth) => {
let d = mk_lldecl();
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
- trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
+ trans_fn(ccx, mth.decl, mth.body, d, &psubsts, mth.id, []);
d
}
ast_map::NodeTraitMethod(method) => {
ast::Provided(mth) => {
let d = mk_lldecl();
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
- trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
+ trans_fn(ccx, mth.decl, mth.body, d, &psubsts, mth.id, []);
d
}
_ => {
struct_def.fields.as_slice(),
struct_def.ctor_id.expect("ast-mapped tuple struct \
didn't have a ctor id"),
- Some(&psubsts),
+ &psubsts,
d);
d
}
fn_ty,
sym.as_slice());
let arena = TypedArena::new();
+ let empty_param_substs = param_substs::empty();
let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
- ty::mk_u64(), None, None, &arena);
+ ty::mk_u64(), &empty_param_substs,
+ None, &arena);
init_function(&fcx, false, ty::mk_u64());
let arg = unsafe {
pub fn tcx(&self) -> &'a ty::ctxt { self.infcx.tcx }
}
-fn has_trait_bounds(type_param_defs: &[ty::TypeParameterDef]) -> bool {
- type_param_defs.iter().any(
- |type_param_def| !type_param_def.bounds.trait_bounds.is_empty())
-}
-
fn lookup_vtables(vcx: &VtableContext,
span: Span,
type_param_defs: &[ty::TypeParameterDef],
let item_ty = ty::lookup_item_type(cx.tcx, did);
debug!("early resolve expr: def {:?} {:?}, {:?}, {}", ex.id, did, def,
fcx.infcx().ty_to_str(item_ty.ty));
- if has_trait_bounds(item_ty.generics.type_param_defs()) {
- debug!("early_resolve_expr: looking up vtables for type params {}",
- item_ty.generics.type_param_defs().repr(fcx.tcx()));
- let vcx = fcx.vtable_context();
- let vtbls = lookup_vtables(&vcx, ex.span,
- item_ty.generics.type_param_defs(),
- &item_substs.substs, is_early);
- if !is_early {
- insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
- }
+ debug!("early_resolve_expr: looking up vtables for type params {}",
+ item_ty.generics.type_param_defs().repr(fcx.tcx()));
+ let vcx = fcx.vtable_context();
+ let vtbls = lookup_vtables(&vcx, ex.span,
+ item_ty.generics.type_param_defs(),
+ &item_substs.substs, is_early);
+ if !is_early {
+ insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
}
});
}
ast::ExprMethodCall(_, _, _) => {
match fcx.inh.method_map.borrow().find(&MethodCall::expr(ex.id)) {
Some(method) => {
- debug!("vtable resolution on parameter bounds for method call {}",
- ex.repr(fcx.tcx()));
- let type_param_defs = ty::method_call_type_param_defs(cx.tcx, method.origin);
- if has_trait_bounds(type_param_defs.as_slice()) {
- let substs = fcx.method_ty_substs(ex.id);
- let vcx = fcx.vtable_context();
- let vtbls = lookup_vtables(&vcx, ex.span,
- type_param_defs.as_slice(),
- &substs, is_early);
- if !is_early {
- insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
- }
- }
+ debug!("vtable resolution on parameter bounds for method call {}",
+ ex.repr(fcx.tcx()));
+ let type_param_defs = ty::method_call_type_param_defs(cx.tcx, method.origin);
+ let substs = fcx.method_ty_substs(ex.id);
+ let vcx = fcx.vtable_context();
+ let vtbls = lookup_vtables(&vcx, ex.span,
+ type_param_defs.as_slice(),
+ &substs, is_early);
+ if !is_early {
+ insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
+ }
}
None => {}
}
ex.repr(fcx.tcx()));
let type_param_defs =
ty::method_call_type_param_defs(cx.tcx, method.origin);
- if has_trait_bounds(type_param_defs.deref().as_slice()) {
- let vcx = fcx.vtable_context();
- let vtbls = lookup_vtables(&vcx, ex.span,
- type_param_defs.deref()
- .as_slice(),
- &method.substs, is_early);
- if !is_early {
- insert_vtables(fcx, method_call, vtbls);
- }
+ let vcx = fcx.vtable_context();
+ let vtbls = lookup_vtables(&vcx, ex.span,
+ type_param_defs.deref()
+ .as_slice(),
+ &method.substs, is_early);
+ if !is_early {
+ insert_vtables(fcx, method_call, vtbls);
}
}
None => {}
/// Resolve vtables for a method call after typeck has finished.
/// Used by trans to monomorphize artificial method callees (e.g. drop).
pub fn trans_resolve_method(tcx: &ty::ctxt, id: ast::NodeId,
- substs: &subst::Substs) -> Option<vtable_res> {
+ substs: &subst::Substs) -> vtable_res {
let generics = ty::lookup_item_type(tcx, ast_util::local_def(id)).generics;
let type_param_defs = &*generics.type_param_defs;
- if has_trait_bounds(type_param_defs.as_slice()) {
- let vcx = VtableContext {
- infcx: &infer::new_infer_ctxt(tcx),
- param_env: &ty::construct_parameter_environment(tcx, None, [], [], [], [], id)
- };
+ let vcx = VtableContext {
+ infcx: &infer::new_infer_ctxt(tcx),
+ param_env: &ty::construct_parameter_environment(tcx, None, [], [], [], [], id)
+ };
- Some(lookup_vtables(&vcx,
- tcx.map.span(id),
- type_param_defs.as_slice(),
- substs,
- false))
- } else {
- None
- }
+ lookup_vtables(&vcx,
+ tcx.map.span(id),
+ type_param_defs.as_slice(),
+ substs,
+ false)
}
impl<'a, 'b> visit::Visitor<()> for &'a FnCtxt<'b> {