Skip to content

Commit

Permalink
rustc: allow paths in constants to refer to polymorphic items.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jan 4, 2015
1 parent 5fe3062 commit c37e7ae
Show file tree
Hide file tree
Showing 14 changed files with 285 additions and 189 deletions.
15 changes: 3 additions & 12 deletions src/librustc/middle/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
expression");
}
}
ast::ExprPath(ref pth) => {
// NB: In the future you might wish to relax this slightly
// to handle on-demand instantiation of functions via
// foo::<bar> in a const. Currently that is only done on
// a path in trans::callee that only works in block contexts.
if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
span_err!(v.tcx.sess, e.span, E0013,
"paths in constants may only refer to items without \
type parameters");
}
ast::ExprPath(_) => {
match v.tcx.def_map.borrow()[e.id] {
DefStatic(..) | DefConst(..) |
DefFn(..) | DefStruct(_) |
DefVariant(_, _, _) => {}
DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
DefStruct(_) | DefVariant(_, _, _) => {}

def => {
debug!("(checking const) found bad def: {}", def);
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,14 +559,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
id, expr_ty.repr(self.tcx()), def);

match def {
def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
def::DefStaticMethod(..) | def::DefConst(..) => {
def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
Ok(self.cat_rvalue_node(id, span, expr_ty))
}
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
def::DefLabel(_) | def::DefSelfTy(..) |
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
Ok(Rc::new(cmt_ {
id:id,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Since we're in trans we don't care for any region parameters
let substs = subst::Substs::erased(substs.types.clone());

let (val, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
let (val, _, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);

val
} else if did.krate == ast::LOCAL_CRATE {
Expand Down
98 changes: 58 additions & 40 deletions src/librustc_trans/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use trans::cleanup::CleanupMethods;
use trans::closure;
use trans::common;
use trans::common::*;
use trans::consts;
use trans::datum::*;
use trans::expr;
use trans::glue;
Expand Down Expand Up @@ -152,7 +153,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
_ => false
}
} => {
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
bcx.fcx.param_substs);
Callee {
bcx: bcx,
data: NamedTupleConstructor(substs, 0)
Expand All @@ -162,23 +164,28 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic,
_ => false
} => {
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
bcx.fcx.param_substs);
let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
}
def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
def::DefStaticMethod(did, def::FromImpl(_)) => {
fn_callee(bcx, trans_fn_ref(bcx, did, ExprId(ref_expr.id)))
fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
bcx.fcx.param_substs).val)
}
def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
fn_callee(bcx, meth::trans_static_method_callee(bcx, meth_did,
fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
meth_did,
trait_did,
ref_expr.id))
ref_expr.id,
bcx.fcx.param_substs).val)
}
def::DefVariant(tid, vid, _) => {
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
bcx.fcx.param_substs);

// Nullary variants are not callable
assert!(vinfo.args.len() > 0u);
Expand All @@ -189,7 +196,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
}
}
def::DefStruct(_) => {
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
bcx.fcx.param_substs);
Callee {
bcx: bcx,
data: NamedTupleConstructor(substs, 0)
Expand Down Expand Up @@ -217,15 +225,19 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)

/// Translates a reference (with id `ref_id`) to the fn/method with id `def_id` into a function
/// pointer. This may require monomorphization or inlining.
pub fn trans_fn_ref(bcx: Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef {
pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
def_id: ast::DefId,
node: ExprOrMethodCall,
param_substs: &subst::Substs<'tcx>)
-> Datum<'tcx, Rvalue> {
let _icx = push_ctxt("trans_fn_ref");

let substs = node_id_substs(bcx, node);
let substs = node_id_substs(ccx, node, param_substs);
debug!("trans_fn_ref(def_id={}, node={}, substs={})",
def_id.repr(bcx.tcx()),
def_id.repr(ccx.tcx()),
node,
substs.repr(bcx.tcx()));
trans_fn_ref_with_substs(bcx, def_id, node, substs)
substs.repr(ccx.tcx()));
trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs)
}

fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Expand All @@ -235,10 +247,11 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-> Callee<'blk, 'tcx> {
Callee {
bcx: bcx,
data: Fn(trans_fn_ref_with_substs(bcx,
data: Fn(trans_fn_ref_with_substs(bcx.ccx(),
def_id,
ExprId(ref_id),
substs)),
bcx.fcx.param_substs,
substs).val),
}
}

Expand Down Expand Up @@ -364,28 +377,30 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
///
/// # Parameters
///
/// - `bcx`: the current block where the reference to the fn occurs
/// - `ccx`: the crate context
/// - `def_id`: def id of the fn or method item being referenced
/// - `node`: node id of the reference to the fn/method, if applicable.
/// This parameter may be zero; but, if so, the resulting value may not
/// have the right type, so it must be cast before being used.
/// - `param_substs`: if the `node` is in a polymorphic function, these
/// are the substitutions required to monomorphize its type
/// - `substs`: values for each of the fn/method's parameters
pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
bcx: Block<'blk, 'tcx>, //
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<'tcx>) // vtables for the call
-> ValueRef
pub fn trans_fn_ref_with_substs<'a, 'tcx>(
ccx: &CrateContext<'a, 'tcx>,
def_id: ast::DefId,
node: ExprOrMethodCall,
param_substs: &subst::Substs<'tcx>,
substs: subst::Substs<'tcx>)
-> Datum<'tcx, Rvalue>
{
let _icx = push_ctxt("trans_fn_ref_with_substs");
let ccx = bcx.ccx();
let tcx = bcx.tcx();
let tcx = ccx.tcx();

debug!("trans_fn_ref_with_substs(bcx={}, def_id={}, node={}, \
substs={})",
bcx.to_str(),
debug!("trans_fn_ref_with_substs(def_id={}, node={}, \
param_substs={}, substs={})",
def_id.repr(tcx),
node,
param_substs.repr(tcx),
substs.repr(tcx));

assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
Expand Down Expand Up @@ -443,15 +458,15 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
(true, source_id, new_substs)
}
ty::TypeTraitItem(_) => {
bcx.tcx().sess.bug("trans_fn_ref_with_vtables() tried \
to translate an associated type?!")
tcx.sess.bug("trans_fn_ref_with_vtables() tried \
to translate an associated type?!")
}
}
}
};

// If this is an unboxed closure, redirect to it.
match closure::get_or_create_declaration_if_unboxed_closure(bcx,
match closure::get_or_create_declaration_if_unboxed_closure(ccx,
def_id,
&substs) {
None => {}
Expand Down Expand Up @@ -494,24 +509,27 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
MethodCallKey(_) => None,
};

let (val, must_cast) =
let (val, fn_ty, must_cast) =
monomorphize::monomorphic_fn(ccx, def_id, &substs, opt_ref_id);
let mut val = val;
if must_cast && node != ExprId(0) {
// Monotype of the REFERENCE to the function (type params
// are subst'd)
let ref_ty = match node {
ExprId(id) => node_id_type(bcx, id),
ExprId(id) => ty::node_id_to_type(tcx, id),
MethodCallKey(method_call) => {
let t = (*bcx.tcx().method_map.borrow())[method_call].ty;
monomorphize_type(bcx, t)
(*tcx.method_map.borrow())[method_call].ty
}
};

val = PointerCast(
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
let ref_ty = monomorphize::apply_param_substs(tcx,
param_substs,
&ref_ty);
let llptrty = type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to();
if llptrty != val_ty(val) {
let val = consts::ptrcast(val, llptrty);
return Datum::new(val, ref_ty, Rvalue::new(ByValue));
}
}
return val;
return Datum::new(val, fn_ty, Rvalue::new(ByValue));
}

// Type scheme of the function item (may have type params)
Expand Down Expand Up @@ -556,12 +574,12 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
let llptrty = llty.ptr_to();
if val_ty(val) != llptrty {
debug!("trans_fn_ref_with_vtables(): casting pointer!");
val = BitCast(bcx, val, llptrty);
val = consts::ptrcast(val, llptrty);
} else {
debug!("trans_fn_ref_with_vtables(): not casting pointer!");
}

val
Datum::new(val, fn_type, Rvalue::new(ByValue))
}

// ______________________________________________________________________
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_trans/trans/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,10 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
// specify any of the types for the function, we just make it a symbol
// that LLVM can later use.
let llpersonality = match pad_bcx.tcx().lang_items.eh_personality() {
Some(def_id) => callee::trans_fn_ref(pad_bcx, def_id, ExprId(0)),
Some(def_id) => {
callee::trans_fn_ref(pad_bcx.ccx(), def_id, ExprId(0),
pad_bcx.fcx.param_substs).val
}
None => {
let mut personality = self.ccx.eh_personality().borrow_mut();
match *personality {
Expand Down
26 changes: 13 additions & 13 deletions src/librustc_trans/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use trans::build::*;
use trans::cleanup::{CleanupMethods, ScopeId};
use trans::common::*;
use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
use trans::datum::{Rvalue, ByValue};
use trans::debuginfo;
use trans::expr;
use trans::monomorphize::{mod, MonoId};
Expand Down Expand Up @@ -453,22 +454,21 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

/// Returns the LLVM function declaration for an unboxed closure, creating it
/// if necessary. If the ID does not correspond to a closure ID, returns None.
pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
closure_id: ast::DefId,
substs: &Substs<'tcx>)
-> Option<ValueRef> {
let ccx = bcx.ccx();
pub fn get_or_create_declaration_if_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
closure_id: ast::DefId,
substs: &Substs<'tcx>)
-> Option<Datum<'tcx, Rvalue>> {
if !ccx.tcx().unboxed_closures.borrow().contains_key(&closure_id) {
// Not an unboxed closure.
return None
}

let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type);
let function_type = ty::node_id_to_type(ccx.tcx(), closure_id.node);
let function_type = monomorphize::apply_param_substs(ccx.tcx(), substs, &function_type);

// Normalize type so differences in regions and typedefs don't cause
// duplicate declarations
let function_type = ty::normalize_ty(bcx.tcx(), function_type);
let function_type = ty::normalize_ty(ccx.tcx(), function_type);
let params = match function_type.sty {
ty::ty_unboxed_closure(_, _, ref substs) => substs.types.clone(),
_ => unreachable!()
Expand All @@ -479,10 +479,10 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
};

match ccx.unboxed_closure_vals().borrow().get(&mono_id) {
Some(llfn) => {
Some(&llfn) => {
debug!("get_or_create_declaration_if_unboxed_closure(): found \
closure");
return Some(*llfn)
return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
}
None => {}
}
Expand All @@ -502,7 +502,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
ccx.tn().type_to_string(val_ty(llfn)));
ccx.unboxed_closure_vals().borrow_mut().insert(mono_id, llfn);

Some(llfn)
Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
}

pub fn trans_unboxed_closure<'blk, 'tcx>(
Expand All @@ -519,7 +519,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(

let closure_id = ast_util::local_def(id);
let llfn = get_or_create_declaration_if_unboxed_closure(
bcx,
bcx.ccx(),
closure_id,
bcx.fcx.param_substs).unwrap();

Expand All @@ -539,7 +539,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
trans_closure(bcx.ccx(),
decl,
body,
llfn,
llfn.val,
bcx.fcx.param_substs,
id,
&[],
Expand Down
Loading

5 comments on commit c37e7ae

@bors
Copy link
Contributor

@bors bors commented on c37e7ae Jan 4, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nikomatsakis
at eddyb@c37e7ae

@bors
Copy link
Contributor

@bors bors commented on c37e7ae Jan 4, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging 11 batched pull requests into batch

@bors
Copy link
Contributor

@bors bors commented on c37e7ae Jan 4, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status: {"merge_sha": "7279119e1241e4679e77c6cabbdb7daf20ba3d07", "rollup_pulls": [[20295, "c37e7ae0c7f876b32bfac85dd7089762c2293084"], [19963, "652a9acb7331e0b70457db0a16e20ba576135b98"], [20428, "5de78040a221d614cdb379b62ecd86d8789b5eab"], [20442, "c8fcbe75619bd8177cd3054fb2d4b72f1b2d1e2e"], [20449, "36c63a3abebce58dd550c0ba032148eac541d64d"], [20452, "ebdf331133af89eef06bede54a5fe53ad4e21af3"], [20457, "f031285c3a76b86525695bbb5b46daa9e77df200"], [20459, "77786e8c4f35773d8a08637d9100ef9a457593a9"], [20485, "eebe7360de3253986736a5ab826379ff754da6a3"], [20487, "15dedb22f6c93f1531627ecadcc80a39177c4b61"], [20495, "e8078c3fedcaab143bfdc298ce4fff2ba52953d9"]]}

@bors
Copy link
Contributor

@bors bors commented on c37e7ae Jan 4, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing rollup candidate = 7279119

Successful merges:

Please sign in to comment.