Skip to content

Newtype structs as immediates #6725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,13 +1036,13 @@ pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {

pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
let _icx = cx.insn_ctxt("spill_if_immediate");
if ty::type_is_immediate(t) { return do_spill(cx, v, t); }
if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
return v;
}

pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
let _icx = cx.insn_ctxt("load_if_immediate");
if ty::type_is_immediate(t) { return Load(cx, v); }
if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
return v;
}

Expand Down Expand Up @@ -1573,7 +1573,7 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
// slot where the return value of the function must go.
pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
unsafe {
if !ty::type_is_immediate(output_type) {
if !ty::type_is_immediate(fcx.ccx.tcx, output_type) {
llvm::LLVMGetParam(fcx.llfn, 0)
} else {
let lloutputtype = type_of::type_of(*fcx.ccx, output_type);
Expand Down Expand Up @@ -1614,7 +1614,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
}
};
let is_immediate = ty::type_is_immediate(substd_output_type);
let is_immediate = ty::type_is_immediate(ccx.tcx, substd_output_type);

let fcx = @mut fn_ctxt_ {
llfn: llfndecl,
Expand Down Expand Up @@ -1734,7 +1734,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
// This alloca should be optimized away by LLVM's mem-to-reg pass in
// the event it's not truly needed.
// only by value if immediate:
let llarg = if datum::appropriate_mode(arg_ty).is_by_value() {
let llarg = if datum::appropriate_mode(bcx.tcx(), arg_ty).is_by_value() {
let alloc = alloc_ty(bcx, arg_ty);
Store(bcx, raw_llarg, alloc);
alloc
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ pub fn trans_call_inner(in_cx: block,

let mut llargs = ~[];

if ty::type_is_immediate(ret_ty) {
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
unsafe {
llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8())));
}
Expand Down Expand Up @@ -559,7 +559,7 @@ pub fn trans_call_inner(in_cx: block,
// case to ignore instead of invoking the Store
// below into a scratch pointer of a mismatched
// type.
} else if ty::type_is_immediate(ret_ty) {
} else if ty::type_is_immediate(bcx.tcx(), ret_ty) {
let llscratchptr = alloc_ty(bcx, ret_ty);
Store(bcx, llresult, llscratchptr);
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
Expand All @@ -573,7 +573,7 @@ pub fn trans_call_inner(in_cx: block,
// If this is an immediate, store into the result location.
// (If this was not an immediate, the result will already be
// directly written into the output slot.)
if ty::type_is_immediate(ret_ty) {
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
Store(bcx, llresult, lldest);
}
}
Expand Down Expand Up @@ -776,7 +776,7 @@ pub fn trans_arg_expr(bcx: block,
scratch.add_clean(bcx);
temp_cleanups.push(scratch.val);

match arg_datum.appropriate_mode() {
match arg_datum.appropriate_mode(bcx.tcx()) {
ByValue => val = Load(bcx, scratch.val),
ByRef => val = scratch.val,
}
Expand Down
29 changes: 8 additions & 21 deletions src/librustc/middle/trans/datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum {
Datum { val: scratch, ty: ty, mode: ByRef, source: RevokeClean }
}

pub fn appropriate_mode(ty: ty::t) -> DatumMode {
pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
/*!
*
* Indicates the "appropriate" mode for this value,
Expand All @@ -206,7 +206,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode {

if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
ByValue
} else if ty::type_is_immediate(ty) {
} else if ty::type_is_immediate(tcx, ty) {
ByValue
} else {
ByRef
Expand Down Expand Up @@ -476,18 +476,18 @@ pub impl Datum {
}
}

fn appropriate_mode(&self) -> DatumMode {
fn appropriate_mode(&self, tcx: ty::ctxt) -> DatumMode {
/*! See the `appropriate_mode()` function */

appropriate_mode(self.ty)
appropriate_mode(tcx, self.ty)
}

fn to_appropriate_llval(&self, bcx: block) -> ValueRef {
/*!
*
* Yields an llvalue with the `appropriate_mode()`. */

match self.appropriate_mode() {
match self.appropriate_mode(bcx.tcx()) {
ByValue => self.to_value_llval(bcx),
ByRef => self.to_ref_llval(bcx)
}
Expand All @@ -498,7 +498,7 @@ pub impl Datum {
*
* Yields a datum with the `appropriate_mode()`. */

match self.appropriate_mode() {
match self.appropriate_mode(bcx.tcx()) {
ByValue => self.to_value_datum(bcx),
ByRef => self.to_ref_datum(bcx)
}
Expand Down Expand Up @@ -622,13 +622,7 @@ pub impl Datum {
ByValue => {
// Actually, this case cannot happen right
// now, because enums are never immediate.
// But in principle newtype'd immediate
// values should be immediate, and in that
// case the * would be a no-op except for
// changing the type, so I am putting this
// code in place here to do the right
// thing if this change ever goes through.
assert!(ty::type_is_immediate(ty));
assert!(ty::type_is_immediate(bcx.tcx(), ty));
(Some(Datum {ty: ty, ..*self}), bcx)
}
};
Expand Down Expand Up @@ -661,14 +655,7 @@ pub impl Datum {
)
}
ByValue => {
// Actually, this case cannot happen right now,
// because structs are never immediate. But in
// principle, newtype'd immediate values should be
// immediate, and in that case the * would be a no-op
// except for changing the type, so I am putting this
// code in place here to do the right thing if this
// change ever goes through.
assert!(ty::type_is_immediate(ty));
assert!(ty::type_is_immediate(bcx.tcx(), ty));
(Some(Datum {ty: ty, ..*self}), bcx)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx));
let scratch = scratch_datum(bcx, closure_ty, false);
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
assert_eq!(datum.appropriate_mode(), ByValue);
assert_eq!(datum.appropriate_mode(tcx), ByValue);
Store(bcx, datum.to_appropriate_llval(bcx), llfn);
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
Store(bcx, base::null_env_ptr(bcx), llenv);
Expand Down
14 changes: 7 additions & 7 deletions src/librustc/middle/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn foreign_signature(ccx: @CrateContext, fn_sig: &ty::FnSig)
LlvmSignature {
llarg_tys: llarg_tys,
llret_ty: llret_ty,
sret: !ty::type_is_immediate(fn_sig.output),
sret: !ty::type_is_immediate(ccx.tcx, fn_sig.output),
}
}

Expand Down Expand Up @@ -193,7 +193,7 @@ fn build_wrap_fn_(ccx: @CrateContext,

// Patch up the return type if it's not immediate and we're returning via
// the C ABI.
if needs_c_return && !ty::type_is_immediate(tys.fn_sig.output) {
if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
let lloutputtype = type_of::type_of(*fcx.ccx, tys.fn_sig.output);
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
lloutputtype));
Expand Down Expand Up @@ -697,7 +697,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
// is not necessary since, for intrinsics, there is no
// cleanup to concern ourselves with.
let tp_ty = substs.tys[0];
let mode = appropriate_mode(tp_ty);
let mode = appropriate_mode(ccx.tcx, tp_ty);
let src = Datum {val: get_param(decl, first_real_arg + 1u),
ty: tp_ty, mode: mode, source: RevokeClean};
bcx = src.move_to(bcx, DROP_EXISTING,
Expand All @@ -706,7 +706,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
~"move_val_init" => {
// See comments for `"move_val"`.
let tp_ty = substs.tys[0];
let mode = appropriate_mode(tp_ty);
let mode = appropriate_mode(ccx.tcx, tp_ty);
let src = Datum {val: get_param(decl, first_real_arg + 1u),
ty: tp_ty, mode: mode, source: RevokeClean};
bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
Expand Down Expand Up @@ -777,7 +777,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
let lldestptr = PointerCast(bcx, lldestptr, T_ptr(T_i8()));

let llsrcval = get_param(decl, first_real_arg);
let llsrcptr = if ty::type_is_immediate(in_type) {
let llsrcptr = if ty::type_is_immediate(ccx.tcx, in_type) {
let llsrcptr = alloca(bcx, llintype);
Store(bcx, llsrcval, llsrcptr);
llsrcptr
Expand Down Expand Up @@ -1228,7 +1228,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext,
let mut i = 0u;
let n = tys.fn_sig.inputs.len();

if !ty::type_is_immediate(tys.fn_sig.output) {
if !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
llargvals.push(llretptr);
} else {
Expand Down Expand Up @@ -1256,7 +1256,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext,
shim_types: &ShimTypes,
llargbundle: ValueRef,
llretval: ValueRef) {
if ty::type_is_immediate(shim_types.fn_sig.output) {
if ty::type_is_immediate(bcx.tcx(), shim_types.fn_sig.output) {
// Write the value into the argument bundle.
let arg_count = shim_types.fn_sig.inputs.len();
let llretptr = load_inbounds(bcx,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
pub fn declare_tydesc_addrspace(ccx: @CrateContext, t: ty::t) -> addrspace {
if !ty::type_needs_drop(ccx.tcx, t) {
return default_addrspace;
} else if ty::type_is_immediate(t) {
} else if ty::type_is_immediate(ccx.tcx, t) {
// For immediate types, we don't actually need an addrspace, because
// e.g. boxed types include pointers to their contents which are
// already correctly tagged with addrspaces.
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/trans/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use core::prelude::*;
use metadata::csearch;
use middle::astencode;
use middle::trans::base::{get_insn_ctxt};
use middle::trans::base::{impl_owned_self, impl_self, no_self};
use middle::trans::base::{impl_self, no_self};
use middle::trans::base::{trans_item, get_item_val, trans_fn};
use middle::trans::common::*;
use middle::ty;
Expand Down Expand Up @@ -109,7 +109,6 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id,
debug!("calling inline trans_fn with self_ty %s",
ty_to_str(ccx.tcx, self_ty));
match mth.explicit_self.node {
ast::sty_value => impl_owned_self(self_ty),
_ => impl_self(self_ty),
}
}
Expand Down
3 changes: 0 additions & 3 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ pub fn trans_method(ccx: @CrateContext,
base_self_ty.repr(ccx.tcx),
self_ty.repr(ccx.tcx));
match method.explicit_self.node {
ast::sty_value => {
impl_owned_self(self_ty)
}
_ => {
impl_self(self_ty)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ pub fn make_mono_id(ccx: @CrateContext,
let llty = type_of::type_of(ccx, subst);
let size = machine::llbitsize_of_real(ccx, llty);
let align = machine::llalign_of_pref(ccx, llty);
let mode = datum::appropriate_mode(subst);
let mode = datum::appropriate_mode(ccx.tcx, subst);
let data_class = mono_data_classify(subst);

// Special value for nil to prevent problems
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use util::ppaux;

use syntax::ast;

pub fn arg_is_indirect(_: @CrateContext, arg_ty: &ty::t) -> bool {
!ty::type_is_immediate(*arg_ty)
pub fn arg_is_indirect(ccx: @CrateContext, arg_ty: &ty::t) -> bool {
!ty::type_is_immediate(ccx.tcx, *arg_ty)
}

pub fn type_of_explicit_arg(ccx: @CrateContext, arg_ty: &ty::t) -> TypeRef {
Expand All @@ -42,7 +42,7 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t)

// Arg 0: Output pointer.
// (if the output type is non-immediate)
let output_is_immediate = ty::type_is_immediate(output);
let output_is_immediate = ty::type_is_immediate(cx.tcx, output);
let lloutputtype = type_of(cx, output);
if !output_is_immediate {
atys.push(T_ptr(lloutputtype));
Expand Down
20 changes: 17 additions & 3 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1706,9 +1706,23 @@ pub fn type_is_scalar(ty: t) -> bool {
}
}

pub fn type_is_immediate(ty: t) -> bool {
pub fn type_is_newtype_immediate(cx: ctxt, ty: t) -> bool {
match get(ty).sty {
ty_struct(def_id, ref substs) => {
let fields = struct_fields(cx, def_id, substs);

// Is this an immediate newtype struct?
fields.len() == 1 && fields[0].ident == special_idents::unnamed_field
&& type_is_immediate(cx, fields[0].mt.ty)
}
_ => false
}
}

pub fn type_is_immediate(cx: ctxt, ty: t) -> bool {
return type_is_scalar(ty) || type_is_boxed(ty) ||
type_is_unique(ty) || type_is_region_ptr(ty);
type_is_unique(ty) || type_is_region_ptr(ty) ||
type_is_newtype_immediate(cx, ty);
}

pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
Expand Down Expand Up @@ -3228,7 +3242,7 @@ pub fn expr_kind(tcx: ctxt,
ast::expr_cast(*) => {
match tcx.node_types.find(&(expr.id as uint)) {
Some(&t) => {
if ty::type_is_immediate(t) {
if ty::type_is_immediate(tcx, t) {
RvalueDatumExpr
} else {
RvalueDpsExpr
Expand Down
11 changes: 3 additions & 8 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,9 @@ pub impl<'self> LookupContext<'self> {
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));

let self_mode = get_mode_from_explicit_self(candidate.method_ty.explicit_self);
// XXX: We always pass self by-ref since we stuff it in the environment slot.
// Eventually that should not be the case
let self_mode = ty::ByRef;

// before we only checked whether self_ty could be a subtype
// of rcvr_ty; now we actually make it so (this may cause
Expand Down Expand Up @@ -1302,10 +1304,3 @@ pub impl<'self> LookupContext<'self> {
self.tcx().sess.bug(s)
}
}

pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMode {
match explicit_self {
sty_value => ty::ByCopy,
_ => ty::ByRef,
}
}
Binary file removed src/test/run-pass/issue-3559
Binary file not shown.
Binary file removed src/test/run-pass/issue-3702
Binary file not shown.
Binary file removed src/test/run-pass/issue-4016
Binary file not shown.
Binary file removed src/test/run-pass/issue-4092
Binary file not shown.
25 changes: 25 additions & 0 deletions src/test/run-pass/issue-5321-immediates-with-bare-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2013 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.

trait Fooable {
fn yes(self);
}

impl Fooable for uint {
fn yes(self) {
for self.times {
io::println("yes");
}
}
}

fn main() {
2.yes();
}