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
This commit is contained in:
commit
4eadabd9f8
14 changed files with 490 additions and 28 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
|
|
@ -514,16 +515,39 @@ 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) => {
|
||||
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,
|
||||
kind: ItemKind::Constant,
|
||||
substs: substs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def::DefStatic(node_id, _) =>
|
||||
ExprKind::StaticRef {
|
||||
|
|
|
|||
|
|
@ -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<Literal<'tcx>> {
|
||||
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)
|
||||
|
|
@ -132,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),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,21 +124,19 @@ 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::Array(id, _) | ConstVal::Repeat(id, _) => {
|
||||
let expr = bcx.tcx().map.expect_expr(id);
|
||||
expr::trans(bcx, expr).datum.val
|
||||
},
|
||||
ConstVal::Function(_) => {
|
||||
unimplemented!()
|
||||
},
|
||||
ConstVal::Array(..) => {
|
||||
unimplemented!()
|
||||
},
|
||||
ConstVal::Repeat(..) => {
|
||||
unimplemented!()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -472,7 +472,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,
|
||||
|
|
|
|||
|
|
@ -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,14 +25,12 @@ 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 = 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());
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
160
src/librustc_trans/trans/mir/did.rs
Normal file
160
src/librustc_trans/trans/mir/did.rs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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");
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
}
|
||||
|
|
@ -192,3 +192,4 @@ mod lvalue;
|
|||
mod rvalue;
|
||||
mod operand;
|
||||
mod statement;
|
||||
mod did;
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
28
src/test/auxiliary/mir_external_refs.rs
Normal file
28
src/test/auxiliary/mir_external_refs.rs
Normal file
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 }
|
||||
218
src/test/run-pass/mir_refs_correct.rs
Normal file
218
src/test/run-pass/mir_refs_correct.rs
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 }
|
||||
}
|
||||
|
||||
trait F<U> {
|
||||
fn f(self, other: U) -> u64;
|
||||
}
|
||||
|
||||
impl F<u32> for u32 {
|
||||
fn f(self, other: u32) -> u64 { self as u64 + other as u64 }
|
||||
}
|
||||
|
||||
impl F<u64> for u32 {
|
||||
fn f(self, other: u64) -> u64 { self as u64 - other }
|
||||
}
|
||||
|
||||
impl F<u64> for u64 {
|
||||
fn f(self, other: u64) -> u64 { self * other }
|
||||
}
|
||||
|
||||
impl F<u32> for u64 {
|
||||
fn f(self, other: u32) -> u64 { self ^ other as u64 }
|
||||
}
|
||||
|
||||
trait T<I, O> {
|
||||
fn staticmeth(i: I, o: O) -> (I, O) { (i, o) }
|
||||
}
|
||||
|
||||
impl<I, O> T<I, O> for O {}
|
||||
|
||||
impl X for S {}
|
||||
|
||||
enum E {
|
||||
U(u8)
|
||||
}
|
||||
|
||||
const C: u8 = 84;
|
||||
const C2: [u8; 5] = [42; 5];
|
||||
const C3: [u8; 3] = [42, 41, 40];
|
||||
|
||||
fn regular() -> u8 {
|
||||
21
|
||||
}
|
||||
|
||||
fn parametric<T>(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 {
|
||||
<S as X>::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 {
|
||||
<ext::S as ext::X>::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 t13_2() -> [u8; 3] {
|
||||
C3
|
||||
}
|
||||
|
||||
#[rustc_mir]
|
||||
fn t14() -> fn()-> u8 {
|
||||
<S as X>::hoy2
|
||||
}
|
||||
|
||||
#[rustc_mir]
|
||||
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) {
|
||||
<u32 as T<_, _>>::staticmeth
|
||||
}
|
||||
|
||||
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), <S as X>::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), <ext::S as ext::X>::hoy(&sext));
|
||||
|
||||
let p = parametric::<u8>;
|
||||
assert!(::std::mem::transmute::<_, *mut ()>(t11()) ==
|
||||
::std::mem::transmute::<_, *mut ()>(p));
|
||||
|
||||
assert_eq!(t12(), C);
|
||||
assert_eq!(t13(), C2);
|
||||
assert_eq!(t13_2(), C3);
|
||||
|
||||
assert_eq!(t14()(), <S as X>::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), <u32 as T<_, _>>::staticmeth(123, 38));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue