Skip to content

Commit 4eadabd

Browse files
committed
Auto merge of #29907 - nagisa:mir-moar-constants, r=nikomatsakis
Still will not translate references to items like `X` or `Y::V` where ``` struct X; enum Y { V } ``` but I must go work on university things so I’m PRing what I have. r? @nikomatsakis
2 parents 48700be + 7dd9579 commit 4eadabd

File tree

14 files changed

+490
-28
lines changed

14 files changed

+490
-28
lines changed

src/librustc/mir/repr.rs

+10
Original file line numberDiff line numberDiff line change
@@ -698,10 +698,20 @@ pub struct Constant<'tcx> {
698698
pub literal: Literal<'tcx>,
699699
}
700700

701+
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
702+
pub enum ItemKind {
703+
Constant,
704+
Function,
705+
Struct,
706+
Variant,
707+
Method,
708+
}
709+
701710
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
702711
pub enum Literal<'tcx> {
703712
Item {
704713
def_id: DefId,
714+
kind: ItemKind,
705715
substs: &'tcx Substs<'tcx>,
706716
},
707717
Value {

src/librustc_mir/build/misc.rs

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
6666
-> Operand<'tcx> {
6767
let literal = Literal::Item {
6868
def_id: item_ref.def_id,
69+
kind: item_ref.kind,
6970
substs: item_ref.substs,
7071
};
7172
self.literal_operand(span, item_ref.ty, literal)

src/librustc_mir/hair/cx/expr.rs

+30-6
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
480480
kind: ExprKind::Literal {
481481
literal: Literal::Item {
482482
def_id: callee.def_id,
483+
kind: ItemKind::Method,
483484
substs: callee.substs,
484485
},
485486
},
@@ -514,16 +515,39 @@ fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<
514515

515516
fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> {
516517
let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
517-
match cx.tcx.def_map.borrow()[&expr.id].full_def() {
518+
// Otherwise there may be def_map borrow conflicts
519+
let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
520+
match def {
518521
def::DefVariant(_, def_id, false) |
519522
def::DefStruct(def_id) |
520523
def::DefFn(def_id, _) |
521-
def::DefConst(def_id) |
522-
def::DefMethod(def_id) |
523-
def::DefAssociatedConst(def_id) =>
524+
def::DefMethod(def_id) => {
525+
let kind = match def {
526+
def::DefVariant(..) => ItemKind::Variant,
527+
def::DefStruct(..) => ItemKind::Struct,
528+
def::DefFn(..) => ItemKind::Function,
529+
def::DefMethod(..) => ItemKind::Method,
530+
_ => panic!()
531+
};
524532
ExprKind::Literal {
525-
literal: Literal::Item { def_id: def_id, substs: substs }
526-
},
533+
literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
534+
}
535+
},
536+
def::DefConst(def_id) |
537+
def::DefAssociatedConst(def_id) => {
538+
if let Some(v) = cx.try_const_eval_literal(expr) {
539+
ExprKind::Literal { literal: v }
540+
} else {
541+
ExprKind::Literal {
542+
literal: Literal::Item {
543+
def_id: def_id,
544+
kind: ItemKind::Constant,
545+
substs: substs
546+
}
547+
}
548+
}
549+
}
550+
527551

528552
def::DefStatic(node_id, _) =>
529553
ExprKind::StaticRef {

src/librustc_mir/hair/cx/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
7676
Literal::Value { value: const_eval::eval_const_expr(self.tcx, e) }
7777
}
7878

79+
pub fn try_const_eval_literal(&mut self, e: &hir::Expr) -> Option<Literal<'tcx>> {
80+
let hint = const_eval::EvalHint::ExprTypeChecked;
81+
const_eval::eval_const_expr_partial(self.tcx, e, hint, None)
82+
.ok()
83+
.map(|v| Literal::Value { value: v })
84+
}
85+
7986
pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
8087
let eq_def_id = self.tcx.lang_items.eq_trait().unwrap();
8188
self.cmp_method_ref(eq_def_id, "eq", ty)
@@ -132,6 +139,7 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
132139
let method_ty = method_ty.ty.subst(self.tcx, &substs);
133140
return ItemRef {
134141
ty: method_ty,
142+
kind: ItemKind::Method,
135143
def_id: method.def_id,
136144
substs: self.tcx.mk_substs(substs),
137145
};

src/librustc_mir/hair/cx/pattern.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
9797
Literal::Value { value: value }
9898
} else {
9999
let substs = self.cx.tcx.mk_substs(Substs::empty());
100-
Literal::Item { def_id: def_id, substs: substs }
100+
Literal::Item {
101+
def_id: def_id,
102+
kind: ItemKind::Constant,
103+
substs: substs
104+
}
101105
};
102106
PatternKind::Constant { value: literal }
103107
}

src/librustc_mir/hair/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! unit-tested and separated from the Rust source and compiler data
1515
//! structures.
1616
17-
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp};
17+
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind};
1818
use rustc::middle::def_id::DefId;
1919
use rustc::middle::region::CodeExtent;
2020
use rustc::middle::subst::Substs;
@@ -29,6 +29,7 @@ pub mod cx;
2929
#[derive(Clone, Debug)]
3030
pub struct ItemRef<'tcx> {
3131
pub ty: Ty<'tcx>,
32+
pub kind: ItemKind,
3233
pub def_id: DefId,
3334
pub substs: &'tcx Substs<'tcx>,
3435
}

src/librustc_trans/trans/consts.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,13 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit)
108108
}
109109
}
110110

111-
pub fn trans_constval<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
111+
pub fn trans_constval<'blk, 'tcx>(bcx: common::Block<'blk, 'tcx>,
112112
cv: &ConstVal,
113113
ty: Ty<'tcx>,
114114
param_substs: &'tcx Substs<'tcx>)
115115
-> ValueRef
116116
{
117+
let ccx = bcx.ccx();
117118
let llty = type_of::type_of(ccx, ty);
118119
match *cv {
119120
ConstVal::Float(v) => C_floating_f64(v, llty),
@@ -123,19 +124,17 @@ pub fn trans_constval<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
123124
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
124125
ConstVal::ByteStr(ref v) => addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
125126
ConstVal::Struct(id) | ConstVal::Tuple(id) => {
126-
let expr = ccx.tcx().map.expect_expr(id);
127+
let expr = bcx.tcx().map.expect_expr(id);
127128
match const_expr(ccx, expr, param_substs, None, TrueConst::Yes) {
128129
Ok((val, _)) => val,
129130
Err(e) => panic!("const eval failure: {}", e.description()),
130131
}
131132
},
132-
ConstVal::Function(_) => {
133-
unimplemented!()
133+
ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => {
134+
let expr = bcx.tcx().map.expect_expr(id);
135+
expr::trans(bcx, expr).datum.val
134136
},
135-
ConstVal::Array(..) => {
136-
unimplemented!()
137-
},
138-
ConstVal::Repeat(..) => {
137+
ConstVal::Function(_) => {
139138
unimplemented!()
140139
},
141140
}

src/librustc_trans/trans/meth.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
472472
///
473473
/// In fact, all virtual calls can be thought of as normal trait calls
474474
/// that go through this shim function.
475-
fn trans_object_shim<'a, 'tcx>(
475+
pub fn trans_object_shim<'a, 'tcx>(
476476
ccx: &'a CrateContext<'a, 'tcx>,
477477
upcast_trait_ref: ty::PolyTraitRef<'tcx>,
478478
method_id: DefId,

src/librustc_trans/trans/mir/constant.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use rustc::mir::repr as mir;
1414
use trans::consts;
1515
use trans::common::{self, Block};
1616

17-
use super::operand::OperandRef;
17+
18+
use super::operand::{OperandRef, OperandValue};
1819
use super::MirContext;
1920

2021
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
@@ -24,14 +25,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
2425
ty: Ty<'tcx>)
2526
-> OperandRef<'tcx>
2627
{
27-
use super::operand::OperandValue::{Ref, Immediate};
28-
2928
let ccx = bcx.ccx();
30-
let val = consts::trans_constval(ccx, cv, ty, bcx.fcx.param_substs);
29+
let val = consts::trans_constval(bcx, cv, ty, bcx.fcx.param_substs);
3130
let val = if common::type_is_immediate(ccx, ty) {
32-
Immediate(val)
31+
OperandValue::Immediate(val)
3332
} else {
34-
Ref(val)
33+
OperandValue::Ref(val)
3534
};
3635

3736
assert!(!ty.has_erasable_regions());
@@ -47,13 +46,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4746
constant: &mir::Constant<'tcx>)
4847
-> OperandRef<'tcx>
4948
{
50-
let constant_ty = bcx.monomorphize(&constant.ty);
49+
let ty = bcx.monomorphize(&constant.ty);
5150
match constant.literal {
52-
mir::Literal::Item { .. } => {
53-
unimplemented!()
54-
}
51+
mir::Literal::Item { def_id, kind, substs } =>
52+
self.trans_item_ref(bcx, ty, kind, substs, def_id),
5553
mir::Literal::Value { ref value } => {
56-
self.trans_constval(bcx, value, constant_ty)
54+
self.trans_constval(bcx, value, ty)
5755
}
5856
}
5957
}

src/librustc_trans/trans/mir/did.rs

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Code for translating references to other items (DefIds).
12+
13+
use syntax::codemap::DUMMY_SP;
14+
use rustc::front::map;
15+
use rustc::middle::ty::{self, Ty, HasTypeFlags};
16+
use rustc::middle::subst::Substs;
17+
use rustc::middle::const_eval;
18+
use rustc::middle::def_id::DefId;
19+
use rustc::middle::subst;
20+
use rustc::middle::traits;
21+
use rustc::mir::repr::ItemKind;
22+
use trans::common::{Block, fulfill_obligation};
23+
use trans::base;
24+
use trans::expr;
25+
use trans::monomorphize;
26+
use trans::meth;
27+
use trans::inline;
28+
29+
use super::MirContext;
30+
use super::operand::{OperandRef, OperandValue};
31+
32+
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
33+
/// Translate reference to item.
34+
pub fn trans_item_ref(&mut self,
35+
bcx: Block<'bcx, 'tcx>,
36+
ty: Ty<'tcx>,
37+
kind: ItemKind,
38+
substs: &'tcx Substs<'tcx>,
39+
did: DefId)
40+
-> OperandRef<'tcx> {
41+
match kind {
42+
ItemKind::Function |
43+
ItemKind::Struct |
44+
ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did),
45+
ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
46+
ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
47+
ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)
48+
},
49+
ItemKind::Constant => {
50+
let did = inline::maybe_instantiate_inline(bcx.ccx(), did);
51+
let expr = const_eval::lookup_const_by_id(bcx.tcx(), did, None)
52+
.expect("def was const, but lookup_const_by_id failed");
53+
// FIXME: this is falling back to translating from HIR. This is not easy to fix,
54+
// because we would have somehow adapt const_eval to work on MIR rather than HIR.
55+
let d = expr::trans(bcx, expr);
56+
OperandRef::from_rvalue_datum(d.datum.to_rvalue_datum(d.bcx, "").datum)
57+
}
58+
}
59+
}
60+
61+
/// Translates references to a function-like items.
62+
///
63+
/// That includes regular functions, non-static methods, struct and enum variant constructors,
64+
/// closures and possibly more.
65+
///
66+
/// This is an adaptation of callee::trans_fn_ref_with_substs.
67+
pub fn trans_fn_ref(&mut self,
68+
bcx: Block<'bcx, 'tcx>,
69+
ty: Ty<'tcx>,
70+
substs: &'tcx Substs<'tcx>,
71+
did: DefId)
72+
-> OperandRef<'tcx> {
73+
let did = inline::maybe_instantiate_inline(bcx.ccx(), did);
74+
75+
if !substs.types.is_empty() || is_named_tuple_constructor(bcx.tcx(), did) {
76+
let (val, fn_ty, _) = monomorphize::monomorphic_fn(bcx.ccx(), did, substs, None);
77+
// FIXME: cast fnptr to proper type if necessary
78+
OperandRef {
79+
ty: fn_ty,
80+
val: OperandValue::Immediate(val)
81+
}
82+
} else {
83+
let val = if let Some(node_id) = bcx.tcx().map.as_local_node_id(did) {
84+
base::get_item_val(bcx.ccx(), node_id)
85+
} else {
86+
base::trans_external_path(bcx.ccx(), did, ty)
87+
};
88+
// FIXME: cast fnptr to proper type if necessary
89+
OperandRef {
90+
ty: ty,
91+
val: OperandValue::Immediate(val)
92+
}
93+
}
94+
}
95+
96+
/// Translates references to static methods.
97+
///
98+
/// This is an adaptation of meth::trans_static_method_callee
99+
pub fn trans_static_method(&mut self,
100+
bcx: Block<'bcx, 'tcx>,
101+
ty: Ty<'tcx>,
102+
method_id: DefId,
103+
trait_id: DefId,
104+
substs: &'tcx Substs<'tcx>)
105+
-> OperandRef<'tcx> {
106+
let ccx = bcx.ccx();
107+
let tcx = bcx.tcx();
108+
let mname = tcx.item_name(method_id);
109+
let subst::SeparateVecsPerParamSpace {
110+
types: rcvr_type,
111+
selfs: rcvr_self,
112+
fns: rcvr_method
113+
} = substs.clone().types.split();
114+
let trait_substs = Substs::erased(
115+
subst::VecPerParamSpace::new(rcvr_type, rcvr_self, Vec::new())
116+
);
117+
let trait_substs = tcx.mk_substs(trait_substs);
118+
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, trait_substs));
119+
let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref);
120+
match vtbl {
121+
traits::VtableImpl(traits::VtableImplData { impl_def_id, substs: imp_substs, .. }) => {
122+
assert!(!imp_substs.types.needs_infer());
123+
let subst::SeparateVecsPerParamSpace {
124+
types: impl_type,
125+
selfs: impl_self,
126+
fns: _
127+
} = imp_substs.types.split();
128+
let callee_substs = Substs::erased(
129+
subst::VecPerParamSpace::new(impl_type, impl_self, rcvr_method)
130+
);
131+
let mth = tcx.get_impl_method(impl_def_id, callee_substs, mname);
132+
let mthsubsts = tcx.mk_substs(mth.substs);
133+
self.trans_fn_ref(bcx, ty, mthsubsts, mth.method.def_id)
134+
},
135+
traits::VtableObject(ref data) => {
136+
let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id);
137+
OperandRef::from_rvalue_datum(
138+
meth::trans_object_shim(ccx, data.upcast_trait_ref.clone(), method_id, idx)
139+
)
140+
}
141+
_ => {
142+
tcx.sess.bug(&format!("static call to invalid vtable: {:?}", vtbl));
143+
}
144+
}
145+
}
146+
}
147+
148+
fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool {
149+
let node_id = match tcx.map.as_local_node_id(def_id) {
150+
Some(n) => n,
151+
None => { return false; }
152+
};
153+
match tcx.map.find(node_id).expect("local item should be in ast map") {
154+
map::NodeVariant(v) => {
155+
v.node.data.is_tuple()
156+
}
157+
map::NodeStructCtor(_) => true,
158+
_ => false
159+
}
160+
}

src/librustc_trans/trans/mir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,4 @@ mod lvalue;
192192
mod rvalue;
193193
mod operand;
194194
mod statement;
195+
mod did;

0 commit comments

Comments
 (0)