Skip to content

Commit 9a90d43

Browse files
committed
rustc: allow paths in constants to refer to polymorphic items.
1 parent a0c07da commit 9a90d43

File tree

14 files changed

+286
-189
lines changed

14 files changed

+286
-189
lines changed

src/librustc/middle/check_const.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
111111
expression");
112112
}
113113
}
114-
ast::ExprPath(ref pth) => {
115-
// NB: In the future you might wish to relax this slightly
116-
// to handle on-demand instantiation of functions via
117-
// foo::<bar> in a const. Currently that is only done on
118-
// a path in trans::callee that only works in block contexts.
119-
if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
120-
span_err!(v.tcx.sess, e.span, E0013,
121-
"paths in constants may only refer to items without \
122-
type parameters");
123-
}
114+
ast::ExprPath(_) => {
124115
match v.tcx.def_map.borrow()[e.id] {
125116
DefStatic(..) | DefConst(..) |
126-
DefFn(..) | DefStruct(_) |
127-
DefVariant(_, _, _) => {}
117+
DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
118+
DefStruct(_) | DefVariant(_, _, _) => {}
128119

129120
def => {
130121
debug!("(checking const) found bad def: {}", def);

src/librustc/middle/mem_categorization.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -559,14 +559,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
559559
id, expr_ty.repr(self.tcx()), def);
560560

561561
match def {
562-
def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
563-
def::DefStaticMethod(..) | def::DefConst(..) => {
562+
def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
563+
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
564564
Ok(self.cat_rvalue_node(id, span, expr_ty))
565565
}
566566
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
567567
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
568568
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
569-
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
569+
def::DefLabel(_) | def::DefSelfTy(..) |
570570
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
571571
Ok(Rc::new(cmt_ {
572572
id:id,

src/librustc_trans/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
511511
// Since we're in trans we don't care for any region parameters
512512
let substs = subst::Substs::erased(substs.types.clone());
513513

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

516516
val
517517
} else if did.krate == ast::LOCAL_CRATE {

src/librustc_trans/trans/callee.rs

+58-40
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use trans::cleanup::CleanupMethods;
3838
use trans::closure;
3939
use trans::common;
4040
use trans::common::*;
41+
use trans::consts;
4142
use trans::datum::*;
4243
use trans::expr;
4344
use trans::glue;
@@ -152,7 +153,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
152153
_ => false
153154
}
154155
} => {
155-
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
156+
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
157+
bcx.fcx.param_substs);
156158
Callee {
157159
bcx: bcx,
158160
data: NamedTupleConstructor(substs, 0)
@@ -162,23 +164,28 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
162164
ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic,
163165
_ => false
164166
} => {
165-
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
167+
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
168+
bcx.fcx.param_substs);
166169
let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
167170
Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
168171
}
169172
def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
170173
def::DefStaticMethod(did, def::FromImpl(_)) => {
171-
fn_callee(bcx, trans_fn_ref(bcx, did, ExprId(ref_expr.id)))
174+
fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
175+
bcx.fcx.param_substs).val)
172176
}
173177
def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
174178
def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
175-
fn_callee(bcx, meth::trans_static_method_callee(bcx, meth_did,
179+
fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
180+
meth_did,
176181
trait_did,
177-
ref_expr.id))
182+
ref_expr.id,
183+
bcx.fcx.param_substs).val)
178184
}
179185
def::DefVariant(tid, vid, _) => {
180186
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
181-
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
187+
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
188+
bcx.fcx.param_substs);
182189

183190
// Nullary variants are not callable
184191
assert!(vinfo.args.len() > 0u);
@@ -189,7 +196,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
189196
}
190197
}
191198
def::DefStruct(_) => {
192-
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
199+
let substs = node_id_substs(bcx.ccx(), ExprId(ref_expr.id),
200+
bcx.fcx.param_substs);
193201
Callee {
194202
bcx: bcx,
195203
data: NamedTupleConstructor(substs, 0)
@@ -217,15 +225,19 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
217225

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

223-
let substs = node_id_substs(bcx, node);
235+
let substs = node_id_substs(ccx, node, param_substs);
224236
debug!("trans_fn_ref(def_id={}, node={}, substs={})",
225-
def_id.repr(bcx.tcx()),
237+
def_id.repr(ccx.tcx()),
226238
node,
227-
substs.repr(bcx.tcx()));
228-
trans_fn_ref_with_substs(bcx, def_id, node, substs)
239+
substs.repr(ccx.tcx()));
240+
trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs)
229241
}
230242

231243
fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -235,10 +247,11 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
235247
-> Callee<'blk, 'tcx> {
236248
Callee {
237249
bcx: bcx,
238-
data: Fn(trans_fn_ref_with_substs(bcx,
250+
data: Fn(trans_fn_ref_with_substs(bcx.ccx(),
239251
def_id,
240252
ExprId(ref_id),
241-
substs)),
253+
bcx.fcx.param_substs,
254+
substs).val),
242255
}
243256
}
244257

@@ -364,28 +377,30 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
364377
///
365378
/// # Parameters
366379
///
367-
/// - `bcx`: the current block where the reference to the fn occurs
380+
/// - `ccx`: the crate context
368381
/// - `def_id`: def id of the fn or method item being referenced
369382
/// - `node`: node id of the reference to the fn/method, if applicable.
370383
/// This parameter may be zero; but, if so, the resulting value may not
371384
/// have the right type, so it must be cast before being used.
385+
/// - `param_substs`: if the `node` is in a polymorphic function, these
386+
/// are the substitutions required to monomorphize its type
372387
/// - `substs`: values for each of the fn/method's parameters
373-
pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
374-
bcx: Block<'blk, 'tcx>, //
375-
def_id: ast::DefId, // def id of fn
376-
node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A
377-
substs: subst::Substs<'tcx>) // vtables for the call
378-
-> ValueRef
388+
pub fn trans_fn_ref_with_substs<'a, 'tcx>(
389+
ccx: &CrateContext<'a, 'tcx>,
390+
def_id: ast::DefId,
391+
node: ExprOrMethodCall,
392+
param_substs: &subst::Substs<'tcx>,
393+
substs: subst::Substs<'tcx>)
394+
-> Datum<'tcx, Rvalue>
379395
{
380396
let _icx = push_ctxt("trans_fn_ref_with_substs");
381-
let ccx = bcx.ccx();
382-
let tcx = bcx.tcx();
397+
let tcx = ccx.tcx();
383398

384-
debug!("trans_fn_ref_with_substs(bcx={}, def_id={}, node={}, \
385-
substs={})",
386-
bcx.to_str(),
399+
debug!("trans_fn_ref_with_substs(def_id={}, node={}, \
400+
param_substs={}, substs={})",
387401
def_id.repr(tcx),
388402
node,
403+
param_substs.repr(tcx),
389404
substs.repr(tcx));
390405

391406
assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
@@ -443,15 +458,15 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
443458
(true, source_id, new_substs)
444459
}
445460
ty::TypeTraitItem(_) => {
446-
bcx.tcx().sess.bug("trans_fn_ref_with_vtables() tried \
447-
to translate an associated type?!")
461+
tcx.sess.bug("trans_fn_ref_with_vtables() tried \
462+
to translate an associated type?!")
448463
}
449464
}
450465
}
451466
};
452467

453468
// If this is an unboxed closure, redirect to it.
454-
match closure::get_or_create_declaration_if_unboxed_closure(bcx,
469+
match closure::get_or_create_declaration_if_unboxed_closure(ccx,
455470
def_id,
456471
&substs) {
457472
None => {}
@@ -494,24 +509,27 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
494509
MethodCallKey(_) => None,
495510
};
496511

497-
let (val, must_cast) =
512+
let (val, fn_ty, must_cast) =
498513
monomorphize::monomorphic_fn(ccx, def_id, &substs, opt_ref_id);
499-
let mut val = val;
500514
if must_cast && node != ExprId(0) {
501515
// Monotype of the REFERENCE to the function (type params
502516
// are subst'd)
503517
let ref_ty = match node {
504-
ExprId(id) => node_id_type(bcx, id),
518+
ExprId(id) => ty::node_id_to_type(tcx, id),
505519
MethodCallKey(method_call) => {
506-
let t = (*bcx.tcx().method_map.borrow())[method_call].ty;
507-
monomorphize_type(bcx, t)
520+
(*tcx.method_map.borrow())[method_call].ty
508521
}
509522
};
510-
511-
val = PointerCast(
512-
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
523+
let ref_ty = monomorphize::apply_param_substs(tcx,
524+
param_substs,
525+
&ref_ty);
526+
let llptrty = type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to();
527+
if llptrty != val_ty(val) {
528+
let val = consts::ptrcast(val, llptrty);
529+
return Datum::new(val, ref_ty, Rvalue::new(ByValue));
530+
}
513531
}
514-
return val;
532+
return Datum::new(val, fn_ty, Rvalue::new(ByValue));
515533
}
516534

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

564-
val
582+
Datum::new(val, fn_type, Rvalue::new(ByValue))
565583
}
566584

567585
// ______________________________________________________________________

src/librustc_trans/trans/cleanup.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,10 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
726726
// specify any of the types for the function, we just make it a symbol
727727
// that LLVM can later use.
728728
let llpersonality = match pad_bcx.tcx().lang_items.eh_personality() {
729-
Some(def_id) => callee::trans_fn_ref(pad_bcx, def_id, ExprId(0)),
729+
Some(def_id) => {
730+
callee::trans_fn_ref(pad_bcx.ccx(), def_id, ExprId(0),
731+
pad_bcx.fcx.param_substs).val
732+
}
730733
None => {
731734
let mut personality = self.ccx.eh_personality().borrow_mut();
732735
match *personality {

src/librustc_trans/trans/closure.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use trans::build::*;
2020
use trans::cleanup::{CleanupMethods, ScopeId};
2121
use trans::common::*;
2222
use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
23+
use trans::datum::{Rvalue, ByValue};
2324
use trans::debuginfo;
2425
use trans::expr;
2526
use trans::monomorphize::{self, MonoId};
@@ -453,22 +454,21 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
453454

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

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

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

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

505-
Some(llfn)
505+
Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
506506
}
507507

508508
pub fn trans_unboxed_closure<'blk, 'tcx>(
@@ -519,7 +519,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
519519

520520
let closure_id = ast_util::local_def(id);
521521
let llfn = get_or_create_declaration_if_unboxed_closure(
522-
bcx,
522+
bcx.ccx(),
523523
closure_id,
524524
bcx.fcx.param_substs).unwrap();
525525

@@ -539,7 +539,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
539539
trans_closure(bcx.ccx(),
540540
decl,
541541
body,
542-
llfn,
542+
llfn.val,
543543
bcx.fcx.param_substs,
544544
id,
545545
&[],

0 commit comments

Comments
 (0)