From 59e6b20cf2c504dee56e20665bf71fb2d9f0030c Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 16 Nov 2015 21:45:44 +0200 Subject: [PATCH 1/4] Const-eval more constants during MIR building --- src/librustc_mir/hair/cx/expr.rs | 20 ++++++++++++++++---- src/librustc_mir/hair/cx/mod.rs | 7 +++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 08826013ebc37..d3844b89b063f 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -514,17 +514,29 @@ fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm< fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> { let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs); - match cx.tcx.def_map.borrow()[&expr.id].full_def() { + // Otherwise there may be def_map borrow conflicts + let def = cx.tcx.def_map.borrow()[&expr.id].full_def(); + match def { def::DefVariant(_, def_id, false) | def::DefStruct(def_id) | def::DefFn(def_id, _) | - def::DefConst(def_id) | - def::DefMethod(def_id) | - def::DefAssociatedConst(def_id) => + def::DefMethod(def_id) => ExprKind::Literal { literal: Literal::Item { def_id: def_id, substs: substs } }, + def::DefConst(def_id) | + def::DefAssociatedConst(def_id) => { + if let Some(v) = cx.try_const_eval_literal(expr) { + ExprKind::Literal { literal: v } + } else { + ExprKind::Literal { + literal: Literal::Item { def_id: def_id, substs: substs } + } + } + } + + def::DefStatic(node_id, _) => ExprKind::StaticRef { id: node_id, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 8c19e620e46ac..5528f2de57737 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -76,6 +76,13 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> { Literal::Value { value: const_eval::eval_const_expr(self.tcx, e) } } + pub fn try_const_eval_literal(&mut self, e: &hir::Expr) -> Option> { + let hint = const_eval::EvalHint::ExprTypeChecked; + const_eval::eval_const_expr_partial(self.tcx, e, hint, None) + .ok() + .map(|v| Literal::Value { value: v }) + } + pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { let eq_def_id = self.tcx.lang_items.eq_trait().unwrap(); self.cmp_method_ref(eq_def_id, "eq", ty) From a5e7a61c490ce619010f585006880b84f3174cd4 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 16 Nov 2015 19:57:57 +0200 Subject: [PATCH 2/4] Implement references to functions and constants --- src/librustc/mir/repr.rs | 10 ++ src/librustc_mir/build/misc.rs | 1 + src/librustc_mir/hair/cx/expr.rs | 22 +++- src/librustc_mir/hair/cx/mod.rs | 1 + src/librustc_mir/hair/cx/pattern.rs | 6 +- src/librustc_mir/hair/mod.rs | 3 +- src/librustc_trans/trans/meth.rs | 2 +- src/librustc_trans/trans/mir/constant.rs | 14 +- src/librustc_trans/trans/mir/did.rs | 158 +++++++++++++++++++++++ src/librustc_trans/trans/mir/mod.rs | 1 + src/librustc_trans/trans/mir/operand.rs | 10 ++ src/test/auxiliary/mir_external_refs.rs | 28 ++++ src/test/run-pass/mir_refs_correct.rs | 155 ++++++++++++++++++++++ 13 files changed, 395 insertions(+), 16 deletions(-) create mode 100644 src/librustc_trans/trans/mir/did.rs create mode 100644 src/test/auxiliary/mir_external_refs.rs create mode 100644 src/test/run-pass/mir_refs_correct.rs diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 049063f73a5bf..e83fe60f419a6 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -698,10 +698,20 @@ pub struct Constant<'tcx> { pub literal: Literal<'tcx>, } +#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] +pub enum ItemKind { + Constant, + Function, + Struct, + Variant, + Method, +} + #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Literal<'tcx> { Item { def_id: DefId, + kind: ItemKind, substs: &'tcx Substs<'tcx>, }, Value { diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index bdcb183c0acfb..5d040bcb40ad8 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -66,6 +66,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { -> Operand<'tcx> { let literal = Literal::Item { def_id: item_ref.def_id, + kind: item_ref.kind, substs: item_ref.substs, }; self.literal_operand(span, item_ref.ty, literal) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index d3844b89b063f..d1455e7016524 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -480,6 +480,7 @@ fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, kind: ExprKind::Literal { literal: Literal::Item { def_id: callee.def_id, + kind: ItemKind::Method, substs: callee.substs, }, }, @@ -520,18 +521,29 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) def::DefVariant(_, def_id, false) | def::DefStruct(def_id) | def::DefFn(def_id, _) | - def::DefMethod(def_id) => + def::DefMethod(def_id) => { + let kind = match def { + def::DefVariant(..) => ItemKind::Variant, + def::DefStruct(..) => ItemKind::Struct, + def::DefFn(..) => ItemKind::Function, + def::DefMethod(..) => ItemKind::Method, + _ => panic!() + }; ExprKind::Literal { - literal: Literal::Item { def_id: def_id, substs: substs } - }, - + literal: Literal::Item { def_id: def_id, kind: kind, substs: substs } + } + }, def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { if let Some(v) = cx.try_const_eval_literal(expr) { ExprKind::Literal { literal: v } } else { ExprKind::Literal { - literal: Literal::Item { def_id: def_id, substs: substs } + literal: Literal::Item { + def_id: def_id, + kind: ItemKind::Constant, + substs: substs + } } } } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 5528f2de57737..d6cfd1a2c6ecf 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -139,6 +139,7 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> { let method_ty = method_ty.ty.subst(self.tcx, &substs); return ItemRef { ty: method_ty, + kind: ItemKind::Method, def_id: method.def_id, substs: self.tcx.mk_substs(substs), }; diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 74fef68400656..c32efcd1a7dab 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -97,7 +97,11 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { Literal::Value { value: value } } else { let substs = self.cx.tcx.mk_substs(Substs::empty()); - Literal::Item { def_id: def_id, substs: substs } + Literal::Item { + def_id: def_id, + kind: ItemKind::Constant, + substs: substs + } }; PatternKind::Constant { value: literal } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 9a774ff3f5712..99e6d6633f288 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -14,7 +14,7 @@ //! unit-tested and separated from the Rust source and compiler data //! structures. -use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp}; +use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind}; use rustc::middle::def_id::DefId; use rustc::middle::region::CodeExtent; use rustc::middle::subst::Substs; @@ -29,6 +29,7 @@ pub mod cx; #[derive(Clone, Debug)] pub struct ItemRef<'tcx> { pub ty: Ty<'tcx>, + pub kind: ItemKind, pub def_id: DefId, pub substs: &'tcx Substs<'tcx>, } diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 123bd9f9c3765..9c10721cf8b16 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -473,7 +473,7 @@ fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// /// In fact, all virtual calls can be thought of as normal trait calls /// that go through this shim function. -fn trans_object_shim<'a, 'tcx>( +pub fn trans_object_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, upcast_trait_ref: ty::PolyTraitRef<'tcx>, method_id: DefId, diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index 9c23d330136ee..cbcc1c3c47db9 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -14,7 +14,8 @@ use rustc::mir::repr as mir; use trans::consts; use trans::common::{self, Block}; -use super::operand::OperandRef; + +use super::operand::{OperandRef, OperandValue}; use super::MirContext; impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { @@ -24,8 +25,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { ty: Ty<'tcx>) -> OperandRef<'tcx> { - use super::operand::OperandValue::{Ref, Immediate}; - let ccx = bcx.ccx(); let val = consts::trans_constval(ccx, cv, ty, bcx.fcx.param_substs); let val = if common::type_is_immediate(ccx, ty) { @@ -47,13 +46,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { constant: &mir::Constant<'tcx>) -> OperandRef<'tcx> { - let constant_ty = bcx.monomorphize(&constant.ty); + let ty = bcx.monomorphize(&constant.ty); match constant.literal { - mir::Literal::Item { .. } => { - unimplemented!() - } + mir::Literal::Item { def_id, kind, substs } => + self.trans_item_ref(bcx, ty, kind, substs, def_id), mir::Literal::Value { ref value } => { - self.trans_constval(bcx, value, constant_ty) + self.trans_constval(bcx, value, ty) } } } diff --git a/src/librustc_trans/trans/mir/did.rs b/src/librustc_trans/trans/mir/did.rs new file mode 100644 index 0000000000000..28a7ca3f72f49 --- /dev/null +++ b/src/librustc_trans/trans/mir/did.rs @@ -0,0 +1,158 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Code for translating references to other items (DefIds). + +use syntax::codemap::DUMMY_SP; +use rustc::front::map; +use rustc::middle::ty::{self, Ty, HasTypeFlags}; +use rustc::middle::subst::Substs; +use rustc::middle::const_eval; +use rustc::middle::def_id::DefId; +use rustc::middle::subst; +use rustc::middle::traits; +use rustc::mir::repr::ItemKind; +use trans::common::{Block, fulfill_obligation}; +use trans::base; +use trans::expr; +use trans::monomorphize; +use trans::meth; +use trans::inline; + +use super::MirContext; +use super::operand::{OperandRef, OperandValue}; + +impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + /// Translate reference to item. + pub fn trans_item_ref(&mut self, + bcx: Block<'bcx, 'tcx>, + ty: Ty<'tcx>, + kind: ItemKind, + substs: &'tcx Substs<'tcx>, + did: DefId) + -> OperandRef<'tcx> { + match kind { + ItemKind::Function | + ItemKind::Struct | + ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did), + ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() { + ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did), + ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs) + }, + ItemKind::Constant => { + let did = inline::maybe_instantiate_inline(bcx.ccx(), did); + let expr = const_eval::lookup_const_by_id(bcx.tcx(), did, None) + .expect("def was const, but lookup_const_by_id failed"); + let d = expr::trans(bcx, expr); + OperandRef::from_rvalue_datum(d.datum.to_rvalue_datum(d.bcx, "").datum) + } + } + } + + /// Translates references to a function-like items. + /// + /// That includes regular functions, non-static methods, struct and enum variant constructors, + /// closures and possibly more. + /// + /// This is an adaptation of callee::trans_fn_ref_with_substs. + pub fn trans_fn_ref(&mut self, + bcx: Block<'bcx, 'tcx>, + ty: Ty<'tcx>, + substs: &'tcx Substs<'tcx>, + did: DefId) + -> OperandRef<'tcx> { + let did = inline::maybe_instantiate_inline(bcx.ccx(), did); + + if !substs.types.is_empty() || is_named_tuple_constructor(bcx.tcx(), did) { + let (val, fn_ty, _) = monomorphize::monomorphic_fn(bcx.ccx(), did, substs, None); + // FIXME: cast fnptr to proper type if necessary + OperandRef { + ty: fn_ty, + val: OperandValue::Immediate(val) + } + } else { + let val = if let Some(node_id) = bcx.tcx().map.as_local_node_id(did) { + base::get_item_val(bcx.ccx(), node_id) + } else { + base::trans_external_path(bcx.ccx(), did, ty) + }; + // FIXME: cast fnptr to proper type if necessary + OperandRef { + ty: ty, + val: OperandValue::Immediate(val) + } + } + } + + /// Translates references to static methods. + /// + /// This is an adaptation of meth::trans_static_method_callee + pub fn trans_static_method(&mut self, + bcx: Block<'bcx, 'tcx>, + ty: Ty<'tcx>, + method_id: DefId, + trait_id: DefId, + substs: &'tcx Substs<'tcx>) + -> OperandRef<'tcx> { + let ccx = bcx.ccx(); + let tcx = bcx.tcx(); + let mname = tcx.item_name(method_id); + let subst::SeparateVecsPerParamSpace { + types: rcvr_type, + selfs: rcvr_self, + fns: rcvr_method + } = substs.clone().types.split(); + let trait_substs = Substs::erased( + subst::VecPerParamSpace::new(rcvr_type, rcvr_self, Vec::new()) + ); + let trait_substs = tcx.mk_substs(trait_substs); + let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, trait_substs)); + let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref); + match vtbl { + traits::VtableImpl(traits::VtableImplData { impl_def_id, substs: imp_substs, .. }) => { + assert!(!imp_substs.types.needs_infer()); + let subst::SeparateVecsPerParamSpace { + types: impl_type, + selfs: impl_self, + fns: _ + } = imp_substs.types.split(); + let callee_substs = Substs::erased( + subst::VecPerParamSpace::new(impl_type, impl_self, rcvr_method) + ); + let mth = tcx.get_impl_method(impl_def_id, callee_substs, mname); + let mthsubsts = tcx.mk_substs(mth.substs); + self.trans_fn_ref(bcx, ty, mthsubsts, mth.method.def_id) + }, + traits::VtableObject(ref data) => { + let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id); + OperandRef::from_rvalue_datum( + meth::trans_object_shim(ccx, data.upcast_trait_ref.clone(), method_id, idx) + ) + } + _ => { + tcx.sess.bug(&format!("static call to invalid vtable: {:?}", vtbl)); + } + } + } +} + +fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool { + let node_id = match tcx.map.as_local_node_id(def_id) { + Some(n) => n, + None => { return false; } + }; + match tcx.map.find(node_id).expect("local item should be in ast map") { + map::NodeVariant(v) => { + v.node.data.is_tuple() + } + map::NodeStructCtor(_) => true, + _ => false + } +} diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs index 27c9feaad3525..0ed76ebeb4362 100644 --- a/src/librustc_trans/trans/mir/mod.rs +++ b/src/librustc_trans/trans/mir/mod.rs @@ -192,3 +192,4 @@ mod lvalue; mod rvalue; mod operand; mod statement; +mod did; diff --git a/src/librustc_trans/trans/mir/operand.rs b/src/librustc_trans/trans/mir/operand.rs index 106c1d05ab7f1..3a3087b478852 100644 --- a/src/librustc_trans/trans/mir/operand.rs +++ b/src/librustc_trans/trans/mir/operand.rs @@ -76,6 +76,16 @@ impl<'tcx> OperandRef<'tcx> { } } } + + pub fn from_rvalue_datum(datum: datum::Datum<'tcx, datum::Rvalue>) -> OperandRef { + OperandRef { + ty: datum.ty, + val: match datum.kind.mode { + datum::RvalueMode::ByRef => OperandValue::Ref(datum.val), + datum::RvalueMode::ByValue => OperandValue::Immediate(datum.val), + } + } + } } impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { diff --git a/src/test/auxiliary/mir_external_refs.rs b/src/test/auxiliary/mir_external_refs.rs new file mode 100644 index 0000000000000..4cad98004d7e4 --- /dev/null +++ b/src/test/auxiliary/mir_external_refs.rs @@ -0,0 +1,28 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +pub struct S(pub u8); + +impl S { + pub fn hey() -> u8 { 24 } +} + +pub trait X { + fn hoy(&self) -> u8 { 25 } +} + +impl X for S {} + +pub enum E { + U(u8) +} + +pub fn regular_fn() -> u8 { 12 } diff --git a/src/test/run-pass/mir_refs_correct.rs b/src/test/run-pass/mir_refs_correct.rs new file mode 100644 index 0000000000000..32aea5c5e3c89 --- /dev/null +++ b/src/test/run-pass/mir_refs_correct.rs @@ -0,0 +1,155 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(rustc_attrs)] +// aux-build:mir_external_refs.rs + + +extern crate mir_external_refs as ext; + +struct S(u8); + +impl S { + fn hey() -> u8 { 42 } + fn hey2(&self) -> u8 { 44 } +} + +trait X { + fn hoy(&self) -> u8 { 43 } + fn hoy2() -> u8 { 45 } +} + +impl X for S {} + +enum E { + U(u8) +} + +const C: u8 = 84; +const C2: [u8; 5] = [42; 5]; + +fn regular() -> u8 { + 21 +} + +fn parametric(u: T) -> T { + u +} + +#[rustc_mir] +fn t1() -> fn()->u8 { + regular +} + +#[rustc_mir] +fn t2() -> fn(u8)->E { + E::U +} + +#[rustc_mir] +fn t3() -> fn(u8)->S { + S +} + +#[rustc_mir] +fn t4() -> fn()->u8 { + S::hey +} + +#[rustc_mir] +fn t5() -> fn(&S)-> u8 { + ::hoy +} + + +#[rustc_mir] +fn t6() -> fn()->u8{ + ext::regular_fn +} + +#[rustc_mir] +fn t7() -> fn(u8)->ext::E { + ext::E::U +} + +#[rustc_mir] +fn t8() -> fn(u8)->ext::S { + ext::S +} + +#[rustc_mir] +fn t9() -> fn()->u8 { + ext::S::hey +} + +#[rustc_mir] +fn t10() -> fn(&ext::S)->u8 { + ::hoy +} + +#[rustc_mir] +fn t11() -> fn(u8)->u8 { + parametric +} + +#[rustc_mir] +fn t12() -> u8 { + C +} + +#[rustc_mir] +fn t13() -> [u8; 5] { + C2 +} + +#[rustc_mir] +fn t14() -> fn()-> u8 { + ::hoy2 +} + +#[rustc_mir] +fn t15() -> fn(&S)-> u8 { + S::hey2 +} + +fn main(){ + unsafe { + assert_eq!(t1()(), regular()); + + assert!(::std::mem::transmute::<_, *mut ()>(t2()) == + ::std::mem::transmute::<_, *mut ()>(E::U)); + assert!(::std::mem::transmute::<_, *mut ()>(t3()) == + ::std::mem::transmute::<_, *mut ()>(S)); + + assert_eq!(t4()(), S::hey()); + let s = S(42); + assert_eq!(t5()(&s), ::hoy(&s)); + + + assert_eq!(t6()(), ext::regular_fn()); + assert!(::std::mem::transmute::<_, *mut ()>(t7()) == + ::std::mem::transmute::<_, *mut ()>(ext::E::U)); + assert!(::std::mem::transmute::<_, *mut ()>(t8()) == + ::std::mem::transmute::<_, *mut ()>(ext::S)); + + assert_eq!(t9()(), ext::S::hey()); + let sext = ext::S(6); + assert_eq!(t10()(&sext), ::hoy(&sext)); + + let p = parametric::; + assert!(::std::mem::transmute::<_, *mut ()>(t11()) == + ::std::mem::transmute::<_, *mut ()>(p)); + + assert_eq!(t12(), C); + assert_eq!(t13(), C2); + + assert_eq!(t14()(), ::hoy2()); + assert_eq!(t15()(&s), S::hey2(&s)); + } +} From b3720ea93342e02fe288eee6b5eb232c063eb0b9 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 5 Dec 2015 20:35:00 +0200 Subject: [PATCH 3/4] Implement translation for ConstVal::{Array,Repeat} --- src/librustc_trans/trans/consts.rs | 15 +++++++-------- src/librustc_trans/trans/mir/constant.rs | 6 +++--- src/librustc_trans/trans/mir/did.rs | 2 ++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 5284911340bd7..406eaafb3f5e5 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -108,12 +108,13 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit) } } -pub fn trans_constval<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, +pub fn trans_constval<'blk, 'tcx>(bcx: common::Block<'blk, 'tcx>, cv: &ConstVal, ty: Ty<'tcx>, param_substs: &'tcx Substs<'tcx>) -> ValueRef { + let ccx = bcx.ccx(); let llty = type_of::type_of(ccx, ty); match *cv { ConstVal::Float(v) => C_floating_f64(v, llty), @@ -123,19 +124,17 @@ pub fn trans_constval<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()), ConstVal::ByteStr(ref v) => addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"), ConstVal::Struct(id) | ConstVal::Tuple(id) => { - let expr = ccx.tcx().map.expect_expr(id); + let expr = bcx.tcx().map.expect_expr(id); match const_expr(ccx, expr, param_substs, None, TrueConst::Yes) { Ok((val, _)) => val, Err(e) => panic!("const eval failure: {}", e.description()), } }, - ConstVal::Function(_) => { - unimplemented!() - }, - ConstVal::Array(..) => { - unimplemented!() + ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => { + let expr = ccx.tcx().map.expect_expr(id); + expr::trans(bcx, expr).datum.val }, - ConstVal::Repeat(..) => { + ConstVal::Function(_) => { unimplemented!() }, } diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index cbcc1c3c47db9..38fab1dbf07f9 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -26,11 +26,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { -> OperandRef<'tcx> { let ccx = bcx.ccx(); - let val = consts::trans_constval(ccx, cv, ty, bcx.fcx.param_substs); + let val = consts::trans_constval(bcx, cv, ty, bcx.fcx.param_substs); let val = if common::type_is_immediate(ccx, ty) { - Immediate(val) + OperandValue::Immediate(val) } else { - Ref(val) + OperandValue::Ref(val) }; assert!(!ty.has_erasable_regions()); diff --git a/src/librustc_trans/trans/mir/did.rs b/src/librustc_trans/trans/mir/did.rs index 28a7ca3f72f49..368708d470bef 100644 --- a/src/librustc_trans/trans/mir/did.rs +++ b/src/librustc_trans/trans/mir/did.rs @@ -50,6 +50,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let did = inline::maybe_instantiate_inline(bcx.ccx(), did); let expr = const_eval::lookup_const_by_id(bcx.tcx(), did, None) .expect("def was const, but lookup_const_by_id failed"); + // FIXME: this is falling back to translating from HIR. This is not easy to fix, + // because we would have somehow adapt const_eval to work on MIR rather than HIR. let d = expr::trans(bcx, expr); OperandRef::from_rvalue_datum(d.datum.to_rvalue_datum(d.bcx, "").datum) } From 7dd95799c2d31cd7b1ab573936b5ed26757fd08c Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 5 Dec 2015 20:35:46 +0200 Subject: [PATCH 4/4] Test generic methods --- src/librustc_trans/trans/consts.rs | 2 +- src/test/run-pass/mir_refs_correct.rs | 63 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 406eaafb3f5e5..0c5c6b2723694 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -131,7 +131,7 @@ pub fn trans_constval<'blk, 'tcx>(bcx: common::Block<'blk, 'tcx>, } }, ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => { - let expr = ccx.tcx().map.expect_expr(id); + let expr = bcx.tcx().map.expect_expr(id); expr::trans(bcx, expr).datum.val }, ConstVal::Function(_) => { diff --git a/src/test/run-pass/mir_refs_correct.rs b/src/test/run-pass/mir_refs_correct.rs index 32aea5c5e3c89..2da1a75870964 100644 --- a/src/test/run-pass/mir_refs_correct.rs +++ b/src/test/run-pass/mir_refs_correct.rs @@ -25,6 +25,32 @@ trait X { fn hoy2() -> u8 { 45 } } +trait F { + fn f(self, other: U) -> u64; +} + +impl F for u32 { + fn f(self, other: u32) -> u64 { self as u64 + other as u64 } +} + +impl F for u32 { + fn f(self, other: u64) -> u64 { self as u64 - other } +} + +impl F for u64 { + fn f(self, other: u64) -> u64 { self * other } +} + +impl F for u64 { + fn f(self, other: u32) -> u64 { self ^ other as u64 } +} + +trait T { + fn staticmeth(i: I, o: O) -> (I, O) { (i, o) } +} + +impl T for O {} + impl X for S {} enum E { @@ -33,6 +59,7 @@ enum E { const C: u8 = 84; const C2: [u8; 5] = [42; 5]; +const C3: [u8; 3] = [42, 41, 40]; fn regular() -> u8 { 21 @@ -108,6 +135,11 @@ fn t13() -> [u8; 5] { C2 } +#[rustc_mir] +fn t13_2() -> [u8; 3] { + C3 +} + #[rustc_mir] fn t14() -> fn()-> u8 { ::hoy2 @@ -118,6 +150,31 @@ fn t15() -> fn(&S)-> u8 { S::hey2 } +#[rustc_mir] +fn t16() -> fn(u32, u32)->u64 { + F::f +} + +#[rustc_mir] +fn t17() -> fn(u32, u64)->u64 { + F::f +} + +#[rustc_mir] +fn t18() -> fn(u64, u64)->u64 { + F::f +} + +#[rustc_mir] +fn t19() -> fn(u64, u32)->u64 { + F::f +} + +#[rustc_mir] +fn t20() -> fn(u64, u32)->(u64, u32) { + >::staticmeth +} + fn main(){ unsafe { assert_eq!(t1()(), regular()); @@ -148,8 +205,14 @@ fn main(){ assert_eq!(t12(), C); assert_eq!(t13(), C2); + assert_eq!(t13_2(), C3); assert_eq!(t14()(), ::hoy2()); assert_eq!(t15()(&s), S::hey2(&s)); + assert_eq!(t16()(10u32, 20u32), F::f(10u32, 20u32)); + assert_eq!(t17()(30u32, 10u64), F::f(30u32, 10u64)); + assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64)); + assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32)); + assert_eq!(t20()(123u64, 38u32), >::staticmeth(123, 38)); } }