From c51da6233d00471200847c050654865a06f01884 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Tue, 29 Oct 2013 03:01:08 -0400 Subject: [PATCH] introduce a magical KindMimic type Closes #9509 --- src/librustc/middle/lang_items.rs | 12 ++++++++++-- src/librustc/middle/ty.rs | 17 +++++++++++------ src/librustc/middle/typeck/collect.rs | 3 +++ src/libstd/kinds.rs | 9 +++++++++ src/libstd/rc.rs | 19 +++++++++++++++---- src/test/compile-fail/kind_mimic.rs | 25 +++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 src/test/compile-fail/kind_mimic.rs diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 6c15dc019ea34..e65446e719e2b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -81,16 +81,18 @@ pub enum LangItem { TyDescStructLangItem, // 36 TyVisitorTraitLangItem, // 37 OpaqueStructLangItem, // 38 + + KindMimicLangItem, // 39 } pub struct LanguageItems { - items: [Option, ..39] + items: [Option, ..40] } impl LanguageItems { pub fn new() -> LanguageItems { LanguageItems { - items: [ None, ..39 ] + items: [ None, ..40 ] } } @@ -145,6 +147,8 @@ impl LanguageItems { 37 => "ty_visitor", 38 => "opaque", + 39 => "kind_mimic", + _ => "???" } } @@ -292,6 +296,9 @@ impl LanguageItems { pub fn opaque(&self) -> Option { self.items[OpaqueStructLangItem as uint] } + pub fn kind_mimic(&self) -> Option { + self.items[KindMimicLangItem as uint] + } } struct LanguageItemCollector<'self> { @@ -374,6 +381,7 @@ impl<'self> LanguageItemCollector<'self> { item_refs.insert("ty_desc", TyDescStructLangItem as uint); item_refs.insert("ty_visitor", TyVisitorTraitLangItem as uint); item_refs.insert("opaque", OpaqueStructLangItem as uint); + item_refs.insert("kind_mimic", KindMimicLangItem as uint); LanguageItemCollector { crate: crate, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 39aa6c5e39637..7d38ad94ab022 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2129,13 +2129,18 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { ty_struct(did, ref substs) => { let flds = struct_fields(cx, did, substs); - let mut res = flds.iter().fold( - TC_NONE, - |tc, f| tc + tc_mt(cx, f.mt, cache)); - if ty::has_dtor(cx, did) { - res = res + TC_DTOR; + let mimic_item = cx.lang_items.kind_mimic(); + if mimic_item.map_default(false, |x| did == x) { + tc_ty(cx, substs.tps[0], cache) + } else { + let mut res = flds.iter().fold( + TC_NONE, + |tc, f| tc + tc_mt(cx, f.mt, cache)); + if ty::has_dtor(cx, did) { + res = res + TC_DTOR; + } + apply_tc_attr(cx, did, res) } - apply_tc_attr(cx, did, res) } ty_tup(ref tys) => { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 9c69e6fd85cc7..694651ce2e7b7 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -91,6 +91,9 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: &ast::Crate) { match ccx.tcx.lang_items.opaque() { Some(id) => { collect_intrinsic_type(ccx, id); } None => {} } + match ccx.tcx.lang_items.kind_mimic() { + Some(id) => { collect_intrinsic_type(ccx, id); } None => {} + } let mut visitor = CollectItemTypesVisitor{ ccx: ccx }; visit::walk_crate(&mut visitor, crate, ()); diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index 6a48e18a3cc2a..5bef5e09e2d1e 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -37,3 +37,12 @@ pub trait Freeze { pub trait Sized { // Empty. } + +/// A special zero-size type with the kinds of the type parameter. +/// +/// It can be used to define new low-level types like smart pointers or dynamic +/// arrays with the correct kinds, since raw pointers are *always* `Send` and +/// `Freeze`. +#[lang="kind_mimic"] +#[unstable] +pub struct KindMimic; diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs index 41e834cf37c39..7dcceb4940aec 100644 --- a/src/libstd/rc.rs +++ b/src/libstd/rc.rs @@ -23,7 +23,7 @@ reference is a unique handle and the type is marked as non-`Freeze`. use ptr::RawPtr; use unstable::intrinsics::transmute; use ops::Drop; -use kinds::{Freeze, Send}; +use kinds::{Freeze, Send, KindMimic}; use clone::{Clone, DeepClone}; struct RcBox { @@ -35,7 +35,8 @@ struct RcBox { #[unsafe_no_drop_flag] #[no_send] pub struct Rc { - priv ptr: *mut RcBox + priv ptr: *mut RcBox, + priv mimic: KindMimic // bubble up lack of a `Freeze` kind } impl Rc { @@ -48,6 +49,16 @@ impl Rc { } } +impl Rc { + /// Construct a new reference-counted box from a `Send` value + #[inline] + pub fn from_send(value: T) -> Rc { + unsafe { + Rc::new_unchecked(value) + } + } +} + impl Rc { /// Unsafety construct a new reference-counted box from any value. /// @@ -56,7 +67,7 @@ impl Rc { /// managed pointers. #[inline] pub unsafe fn new_unchecked(value: T) -> Rc { - Rc{ptr: transmute(~RcBox{value: value, count: 1})} + Rc{ptr: transmute(~RcBox{value: value, count: 1}), mimic: KindMimic} } /// Borrow the value contained in the reference-counted box @@ -71,7 +82,7 @@ impl Clone for Rc { fn clone(&self) -> Rc { unsafe { (*self.ptr).count += 1; - Rc{ptr: self.ptr} + Rc{ptr: self.ptr, mimic: KindMimic} } } } diff --git a/src/test/compile-fail/kind_mimic.rs b/src/test/compile-fail/kind_mimic.rs new file mode 100644 index 0000000000000..81ae3b9c51a2e --- /dev/null +++ b/src/test/compile-fail/kind_mimic.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::kinds::KindMimic; + +#[no_send] +struct Bar; + +#[no_freeze] +struct Baz; + +fn bar(_: T) {} +fn baz(_: T) {} + +fn main() { + bar(KindMimic::); //~ ERROR instantiating a type parameter with an incompatible type `std::kinds::KindMimic`, which does not fulfill `Send` + baz(KindMimic::); //~ ERROR instantiating a type parameter with an incompatible type `std::kinds::KindMimic`, which does not fulfill `Freeze` +}