diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 1749f8e3f6f..264ad3c7c57 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1121,13 +1121,13 @@ pub fn do_spill_noroot(cx: @mut Block, v: ValueRef) -> ValueRef { pub fn spill_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { let _icx = push_ctxt("spill_if_immediate"); - if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); } + if type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); } return v; } pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { let _icx = push_ctxt("load_if_immediate"); - if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); } + if type_is_immediate(cx.tcx(), t) { return Load(cx, v); } return v; } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 322050331a2..f030fb4996b 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -15,7 +15,7 @@ use driver::session; use driver::session::Session; use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef}; use lib::llvm::{True, False, Bool}; -use lib::llvm::{llvm}; +use lib::llvm::llvm; use lib; use middle::lang_items::LangItem; use middle::trans::base; @@ -28,17 +28,17 @@ use middle::ty::substs; use middle::ty; use middle::typeck; use middle::borrowck::root_map_key; -use util::ppaux::{Repr}; +use util::ppaux::Repr; use middle::trans::type_::Type; use std::c_str::ToCStr; use std::cast::transmute; use std::cast; -use std::hashmap::{HashMap}; +use std::hashmap::HashMap; use std::libc::{c_uint, c_longlong, c_ulonglong, c_char}; use std::vec; -use syntax::ast::{Name,Ident}; +use syntax::ast::{Name, Ident}; use syntax::ast_map::{path, path_elt, path_pretty_name}; use syntax::codemap::Span; use syntax::parse::token; @@ -46,6 +46,25 @@ use syntax::{ast, ast_map}; pub use middle::trans::context::CrateContext; +fn type_is_newtype_immediate(cx: ty::ctxt, ty: ty::t) -> bool { + match ty::get(ty).sty { + ty::ty_struct(def_id, ref substs) => { + let fields = ty::struct_fields(cx, def_id, substs); + fields.len() == 1 && + fields[0].ident.name == token::special_idents::unnamed_field.name && + type_is_immediate(cx, fields[0].mt.ty) + } + _ => false + } +} + +pub fn type_is_immediate(cx: ty::ctxt, ty: ty::t) -> bool { + ty::type_is_scalar(ty) || ty::type_is_boxed(ty) || + ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) || + type_is_newtype_immediate(cx, ty) || + ty::type_is_simd(cx, ty) +} + pub fn gensym_name(name: &str) -> (Ident, path_elt) { let name = token::gensym(name); let ident = Ident::new(name); diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 8ee38b950bf..e48174b04f8 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -197,7 +197,7 @@ pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode { if ty::type_is_voidish(ty) { ByValue - } else if ty::type_is_immediate(tcx, ty) { + } else if type_is_immediate(tcx, ty) { ByValue } else { ByRef(RevokeClean) @@ -667,7 +667,7 @@ impl Datum { ByValue => { // Actually, this case cannot happen right // now, because enums are never immediate. - assert!(ty::type_is_immediate(bcx.tcx(), ty)); + assert!(type_is_immediate(bcx.tcx(), ty)); (Some(Datum {ty: ty, ..*self}), bcx) } }; @@ -699,7 +699,7 @@ impl Datum { ) } ByValue => { - assert!(ty::type_is_immediate(bcx.tcx(), ty)); + assert!(type_is_immediate(bcx.tcx(), ty)); ( Some(Datum { val: ExtractValue(bcx, self.val, 0), diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index a10f53ebcbc..cecea270330 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -77,19 +77,9 @@ pub fn drop_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { pub fn drop_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { let _icx = push_ctxt("drop_ty_immediate"); - match ty::get(t).sty { - ty::ty_uniq(_) - | ty::ty_evec(_, ty::vstore_uniq) - | ty::ty_estr(ty::vstore_uniq) => { - free_ty_immediate(bcx, v, t) - } - ty::ty_box(_) | ty::ty_opaque_box - | ty::ty_evec(_, ty::vstore_box) - | ty::ty_estr(ty::vstore_box) => { - decr_refcnt_maybe_free(bcx, v, None, t) - } - _ => bcx.tcx().sess.bug("drop_ty_immediate: non-box ty") - } + let vp = alloca(bcx, type_of(bcx.ccx(), t), ""); + Store(bcx, v, vp); + drop_ty(bcx, vp, t) } pub fn free_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 04ffb393b5e..7933e97a602 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -278,7 +278,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, "uninit" => { // Do nothing, this is effectively a no-op let retty = substs.tys[0]; - if ty::type_is_immediate(ccx.tcx, retty) && !ty::type_is_nil(retty) { + if type_is_immediate(ccx.tcx, retty) && !ty::type_is_nil(retty) { unsafe { Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref())); } @@ -316,7 +316,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, if !ty::type_is_voidish(out_type) { let llsrcval = get_param(decl, first_real_arg); - if ty::type_is_immediate(ccx.tcx, in_type) { + if type_is_immediate(ccx.tcx, in_type) { match fcx.llretptr { Some(llretptr) => { Store(bcx, llsrcval, PointerCast(bcx, llretptr, llintype.ptr_to())); @@ -335,7 +335,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, } } } - } else if ty::type_is_immediate(ccx.tcx, out_type) { + } else if type_is_immediate(ccx.tcx, out_type) { let llsrcptr = PointerCast(bcx, llsrcval, llouttype.ptr_to()); let ll_load = Load(bcx, llsrcptr); Ret(bcx, ll_load); diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 945d5a048bb..aab24f8365b 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -21,11 +21,11 @@ use syntax::ast; use syntax::opt_vec; pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: ty::t) -> bool { - !ty::type_is_immediate(ccx.tcx, arg_ty) + !type_is_immediate(ccx.tcx, arg_ty) } pub fn return_uses_outptr(tcx: ty::ctxt, ty: ty::t) -> bool { - !ty::type_is_immediate(tcx, ty) + !type_is_immediate(tcx, ty) } pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: ty::t) -> Type { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index bcf4de08073..ed103f66915 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1752,25 +1752,6 @@ pub fn type_is_scalar(ty: t) -> bool { } } -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); - fields.len() == 1 && - fields[0].ident.name == token::special_idents::unnamed_field.name && - 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_newtype_immediate(cx, ty) || - type_is_simd(cx, ty); -} - pub fn type_needs_drop(cx: ctxt, ty: t) -> bool { type_contents(cx, ty).needs_drop(cx) } @@ -2538,6 +2519,13 @@ pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool { }); } +pub fn type_is_trait(ty: t) -> bool { + match get(ty).sty { + ty_trait(*) => true, + _ => false + } +} + pub fn type_is_integral(ty: t) -> bool { match get(ty).sty { ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true, @@ -3289,10 +3277,10 @@ pub fn expr_kind(tcx: ctxt, ast::ExprCast(*) => { match tcx.node_types.find(&(expr.id as uint)) { Some(&t) => { - if ty::type_is_immediate(tcx, t) { - RvalueDatumExpr - } else { + if type_is_trait(t) { RvalueDpsExpr + } else { + RvalueDatumExpr } } None => { diff --git a/src/test/run-pass/issue-9446.rs b/src/test/run-pass/issue-9446.rs new file mode 100644 index 00000000000..e97960b3f02 --- /dev/null +++ b/src/test/run-pass/issue-9446.rs @@ -0,0 +1,38 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Wrapper(~str); + +impl Wrapper { + pub fn new(wrapped: ~str) -> Wrapper { + Wrapper(wrapped) + } + + pub fn say_hi(&self) { + println(fmt!("hello %s", **self)); + } +} + +impl Drop for Wrapper { + fn drop(&mut self) {} +} + +pub fn main() { + { + // This runs without complaint. + let x = Wrapper::new(~"Bob"); + x.say_hi(); + } + { + // This fails to compile, circa 0.8-89-gc635fba. + // error: internal compiler error: drop_ty_immediate: non-box ty + Wrapper::new(~"Bob").say_hi(); + } +}