# our configure script, so disable auto submodule management.
git:
submodules: false
+ depth: 1
before_install:
- docker build -t rust -f src/etc/Dockerfile src/etc
libedit-dev zlib1g-dev \
llvm-3.7-tools cmake
-# When we compile compiler-rt we pass it the llvm-config we just installed on
-# the system, but unfortunately it doesn't infer correctly where
-# LLVMConfig.cmake is so we need to coerce it a bit...
-RUN mkdir -p /usr/lib/llvm-3.7/build/share/llvm
-RUN ln -s /usr/share/llvm-3.7/cmake /usr/lib/llvm-3.7/build/share/llvm/cmake
-
RUN mkdir /build
WORKDIR /build
#![feature(specialization)]
#![feature(staged_api)]
#![feature(step_by)]
-#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]
///
/// # Example
///
- /// Print the slice two elements at a time (i.e. `[1,2]`,
- /// `[3,4]`, `[5]`):
- ///
- /// ```rust
- /// let v = &[1, 2, 3, 4, 5];
- ///
- /// for chunk in v.chunks(2) {
- /// println!("{:?}", chunk);
- /// }
+ /// ```
+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
+ /// let mut iter = slice.chunks(2);
+ /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+ /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+ /// assert_eq!(iter.next().unwrap(), &['m']);
+ /// assert!(iter.next().is_none());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#![feature(step_by)]
#![feature(test)]
#![feature(try_from)]
-#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
}
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)]
pub struct IdRange {
pub min: NodeId,
pub max: NodeId,
self.min = cmp::min(self.min, id);
self.max = cmp::max(self.max, id + 1);
}
+
}
use arena::TypedArena;
use std::cell::RefCell;
+use std::cmp;
use std::io;
use std::mem;
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
EntryTyParam(id, _) => id,
- _ => return None
+
+ NotPresent |
+ RootCrate |
+ RootInlinedParent(_) => return None,
})
}
map: RefCell<Vec<MapEntry<'ast>>>,
definitions: RefCell<Definitions>,
+
+ /// All NodeIds that are numerically greater or equal to this value come
+ /// from inlined items.
+ local_node_id_watermark: NodeId,
}
impl<'ast> Map<'ast> {
}
}
+ pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
+ match self.find_entry(id) {
+ Some(RootInlinedParent(inlined_item)) => inlined_item,
+ _ => bug!("expected inlined item, found {}", self.node_to_string(id)),
+ }
+ }
+
/// Returns the name associated with the given NodeId's AST.
pub fn name(&self, id: NodeId) -> Name {
match self.get(id) {
pub fn node_to_user_string(&self, id: NodeId) -> String {
node_id_to_string(self, id, false)
}
+
+ pub fn is_inlined(&self, id: NodeId) -> bool {
+ id >= self.local_node_id_watermark
+ }
}
pub struct NodesMatchingSuffix<'a, 'ast:'a> {
}
/// A Folder that updates IDs and Span's according to fold_ops.
-struct IdAndSpanUpdater<F> {
- fold_ops: F
+pub struct IdAndSpanUpdater<F> {
+ fold_ops: F,
+ min_id_assigned: NodeId,
+ max_id_assigned: NodeId,
+}
+
+impl<F: FoldOps> IdAndSpanUpdater<F> {
+ pub fn new(fold_ops: F) -> IdAndSpanUpdater<F> {
+ IdAndSpanUpdater {
+ fold_ops: fold_ops,
+ min_id_assigned: ::std::u32::MAX,
+ max_id_assigned: ::std::u32::MIN,
+ }
+ }
+
+ pub fn id_range(&self) -> intravisit::IdRange {
+ intravisit::IdRange {
+ min: self.min_id_assigned,
+ max: self.max_id_assigned + 1,
+ }
+ }
}
impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
fn new_id(&mut self, id: NodeId) -> NodeId {
- self.fold_ops.new_id(id)
+ let id = self.fold_ops.new_id(id);
+
+ self.min_id_assigned = cmp::min(self.min_id_assigned, id);
+ self.max_id_assigned = cmp::max(self.max_id_assigned, id);
+
+ id
}
fn new_span(&mut self, span: Span) -> Span {
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
}
+ let local_node_id_watermark = map.len() as NodeId;
+
Map {
forest: forest,
dep_graph: forest.dep_graph.clone(),
map: RefCell::new(map),
definitions: RefCell::new(definitions),
+ local_node_id_watermark: local_node_id_watermark
}
}
ii: InlinedItem,
fold_ops: F)
-> &'ast InlinedItem {
- let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
+ let mut fld = IdAndSpanUpdater::new(fold_ops);
let ii = match ii {
II::Item(i) => II::Item(i.map(|i| fld.fold_item(i))),
II::TraitItem(d, ti) => {
let ii = map.forest.inlined_items.alloc(ii);
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
+ // Assert that the ii_parent_id is the last NodeId in our reserved range
+ assert!(ii_parent_id == fld.max_id_assigned);
+ // Assert that we did not violate the invariant that all inlined HIR items
+ // have NodeIds greater than or equal to `local_node_id_watermark`
+ assert!(fld.min_id_assigned >= map.local_node_id_watermark);
+
let defs = &mut *map.definitions.borrow_mut();
let mut def_collector = DefCollector::extend(ii_parent_id,
parent_def_path.clone(),
pub vis: ty::Visibility,
}
-pub enum FoundAst<'ast> {
- Found(&'ast InlinedItem),
- FoundParent(DefId, &'ast hir::Item),
- NotFound,
-}
-
#[derive(Copy, Clone, Debug)]
pub struct ExternCrate {
/// def_id of an `extern crate` in the current crate that caused
// misc. metadata
fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> FoundAst<'tcx>;
+ -> Option<(&'tcx InlinedItem, ast::NodeId)>;
+ fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
+ fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
+
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<Mir<'tcx>>;
fn is_item_mir_available(&self, def: DefId) -> bool;
// misc. metadata
fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> FoundAst<'tcx> { bug!("maybe_get_item_ast") }
+ -> Option<(&'tcx InlinedItem, ast::NodeId)> {
+ bug!("maybe_get_item_ast")
+ }
+ fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
+ bug!("local_node_for_inlined_defid")
+ }
+ fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
+ bug!("defid_for_inlined_node")
+ }
+
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
fn is_item_mir_available(&self, def: DefId) -> bool {
pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
+ base.cpu = "x86-64".to_string();
base.pre_link_args.push("-m64".to_string());
base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
base.ar = "x86_64-rumprun-netbsd-ar".to_string();
pub fn target() -> TargetResult {
let mut base = super::bitrig_base::opts();
+ base.cpu = "x86-64".to_string();
base.max_atomic_width = 64;
base.pre_link_args.push("-m64".to_string());
pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
+ base.cpu = "x86-64".to_string();
base.max_atomic_width = 64;
base.pre_link_args.push("-m64".to_string());
use rustc::hir::map as ast_map;
use rustc::hir::map::blocks::FnLikeNode;
-use rustc::middle::cstore::{self, InlinedItem};
+use rustc::middle::cstore::InlinedItem;
use rustc::traits;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def_id::DefId;
}
let mut used_substs = false;
let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
- cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
+ Some((&InlinedItem::Item(ref item), _)) => match item.node {
hir::ItemConst(ref ty, ref const_expr) => {
Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
},
_ => None
},
- cstore::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
+ Some((&InlinedItem::TraitItem(trait_id, ref ti), _)) => match ti.node {
hir::ConstTraitItem(_, _) => {
used_substs = true;
if let Some(substs) = substs {
}
_ => None
},
- cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
+ Some((&InlinedItem::ImplItem(_, ref ii), _)) => match ii.node {
hir::ImplItemKind::Const(ref ty, ref expr) => {
Some((&**expr, tcx.ast_ty_to_prim_ty(ty)))
},
}
let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
- cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => Some(item.id),
- cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref item)) => Some(item.id),
+ Some((&InlinedItem::Item(ref item), _)) => Some(item.id),
+ Some((&InlinedItem::ImplItem(_, ref item), _)) => Some(item.id),
_ => None
};
tcx.extern_const_fns.borrow_mut().insert(def_id,
#![feature(set_stdio)]
#![feature(staged_api)]
#![feature(question_mark)]
-#![feature(unboxed_closures)]
extern crate arena;
extern crate flate;
rbml_w.writer.seek(SeekFrom::Current(0)));
// Folding could be avoided with a smarter encoder.
- let ii = simplify_ast(ii);
+ let (ii, expected_id_range) = simplify_ast(ii);
let id_range = inlined_item_id_range(&ii);
+ assert_eq!(expected_id_range, id_range);
rbml_w.start_tag(c::tag_ast as usize);
id_range.encode(rbml_w);
pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
// from_id_range should be non-empty
assert!(!self.from_id_range.empty());
+ // Make sure that translating the NodeId will actually yield a
+ // meaningful result
+ assert!(self.from_id_range.contains(id));
+
// Use wrapping arithmetic because otherwise it introduces control flow.
// Maybe we should just have the control flow? -- aatch
(id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min))
rbml_w.end_tag();
}
-struct NestedItemsDropper;
+struct NestedItemsDropper {
+ id_range: IdRange
+}
impl Folder for NestedItemsDropper {
+
+ // The unit tests below run on HIR with NodeIds not properly assigned. That
+ // causes an integer overflow. So we just don't track the id_range when
+ // building the unit tests.
+ #[cfg(not(test))]
+ fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
+ // Record the range of NodeIds we are visiting, so we can do a sanity
+ // check later
+ self.id_range.add(id);
+ id
+ }
+
fn fold_block(&mut self, blk: P<hir::Block>) -> P<hir::Block> {
blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| {
let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
// As it happens, trans relies on the fact that we do not export
// nested items, as otherwise it would get confused when translating
// inlined items.
-fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
- let mut fld = NestedItemsDropper;
+fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) {
+ let mut fld = NestedItemsDropper {
+ id_range: IdRange::max()
+ };
- match ii {
+ let ii = match ii {
// HACK we're not dropping items.
InlinedItemRef::Item(i) => {
InlinedItem::Item(P(fold::noop_fold_item(i.clone(), &mut fld)))
InlinedItemRef::Foreign(i) => {
InlinedItem::Foreign(P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
}
- }
+ };
+
+ (ii, fld.id_range)
}
fn decode_ast(item_doc: rbml::Doc) -> InlinedItem {
match *self {
Def::Fn(did) => Def::Fn(did.tr(dcx)),
Def::Method(did) => Def::Method(did.tr(dcx)),
- Def::SelfTy(opt_did, impl_id) => { Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
- impl_id.map(|id| dcx.tr_id(id))) }
+ Def::SelfTy(opt_did, impl_id) => {
+ // Since the impl_id will never lie within the reserved range of
+ // imported NodeIds, it does not make sense to translate it.
+ // The result would not make any sense within the importing crate.
+ // We also don't allow for impl items to be inlined (just their
+ // members), so even if we had a DefId here, we wouldn't be able
+ // to do much with it.
+ // So, we set the id to DUMMY_NODE_ID. That way we make it
+ // explicit that this is no usable NodeId.
+ Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
+ impl_id.map(|_| ast::DUMMY_NODE_ID))
+ }
Def::Mod(did) => { Def::Mod(did.tr(dcx)) }
Def::ForeignMod(did) => { Def::ForeignMod(did.tr(dcx)) }
Def::Static(did, m) => { Def::Static(did.tr(dcx), m) }
with_testing_context(|lcx| {
let hir_item = lcx.lower_item(&item);
let item_in = InlinedItemRef::Item(&hir_item);
- let item_out = simplify_ast(item_in);
+ let (item_out, _) = simplify_ast(item_in);
let item_exp = InlinedItem::Item(P(lcx.lower_item("e_item!(&cx,
fn new_int_alist<B>() -> alist<isize, B> {
return alist {eq_fn: eq_int, data: Vec::new()};
use encoder;
use loader;
-use middle::cstore::{CrateStore, CrateSource, ChildItem, ExternCrate, FoundAst, DefLike};
+use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike};
use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
use rustc::hir::def;
use middle::lang_items;
result
}
- fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> FoundAst<'tcx>
+ fn maybe_get_item_ast<'a>(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> Option<(&'tcx InlinedItem, ast::NodeId)>
{
- self.dep_graph.read(DepNode::MetaData(def));
- let cdata = self.get_crate_data(def.krate);
- decoder::maybe_get_item_ast(&cdata, tcx, def.index)
+ self.dep_graph.read(DepNode::MetaData(def_id));
+
+ match self.inlined_item_cache.borrow().get(&def_id) {
+ Some(&None) => {
+ return None; // Not inlinable
+ }
+ Some(&Some(ref cached_inlined_item)) => {
+ // Already inline
+ debug!("maybe_get_item_ast({}): already inline as node id {}",
+ tcx.item_path_str(def_id), cached_inlined_item.item_id);
+ return Some((tcx.map.expect_inlined_item(cached_inlined_item.inlined_root),
+ cached_inlined_item.item_id));
+ }
+ None => {
+ // Not seen yet
+ }
+ }
+
+ debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id));
+
+ let cdata = self.get_crate_data(def_id.krate);
+ let inlined = decoder::maybe_get_item_ast(&cdata, tcx, def_id.index);
+
+ let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| {
+ let cache_entry = cstore::CachedInlinedItem {
+ inlined_root: inlined_root_node_id,
+ item_id: inlined_item_id,
+ };
+ self.inlined_item_cache
+ .borrow_mut()
+ .insert(original_def_id, Some(cache_entry));
+ self.defid_for_inlined_node
+ .borrow_mut()
+ .insert(inlined_item_id, original_def_id);
+ };
+
+ let find_inlined_item_root = |inlined_item_id| {
+ let mut node = inlined_item_id;
+ let mut path = Vec::with_capacity(10);
+
+ // If we can't find the inline root after a thousand hops, we can
+ // be pretty sure there's something wrong with the HIR map.
+ for _ in 0 .. 1000 {
+ path.push(node);
+ let parent_node = tcx.map.get_parent_node(node);
+ if parent_node == node {
+ return node;
+ }
+ node = parent_node;
+ }
+ bug!("cycle in HIR map parent chain")
+ };
+
+ match inlined {
+ decoder::FoundAst::NotFound => {
+ self.inlined_item_cache
+ .borrow_mut()
+ .insert(def_id, None);
+ }
+ decoder::FoundAst::Found(&InlinedItem::Item(ref item)) => {
+ let inlined_root_node_id = find_inlined_item_root(item.id);
+ cache_inlined_item(def_id, item.id, inlined_root_node_id);
+ }
+ decoder::FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
+ let inlined_root_node_id = find_inlined_item_root(item.id);
+ cache_inlined_item(def_id, item.id, inlined_root_node_id);
+ }
+ decoder::FoundAst::FoundParent(parent_did, item) => {
+ let inlined_root_node_id = find_inlined_item_root(item.id);
+ cache_inlined_item(parent_did, item.id, inlined_root_node_id);
+
+ match item.node {
+ hir::ItemEnum(ref ast_def, _) => {
+ let ast_vs = &ast_def.variants;
+ let ty_vs = &tcx.lookup_adt_def(parent_did).variants;
+ assert_eq!(ast_vs.len(), ty_vs.len());
+ for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
+ cache_inlined_item(ty_v.did,
+ ast_v.node.data.id(),
+ inlined_root_node_id);
+ }
+ }
+ hir::ItemStruct(ref struct_def, _) => {
+ if struct_def.is_struct() {
+ bug!("instantiate_inline: called on a non-tuple struct")
+ } else {
+ cache_inlined_item(def_id,
+ struct_def.id(),
+ inlined_root_node_id);
+ }
+ }
+ _ => bug!("instantiate_inline: item has a \
+ non-enum, non-struct parent")
+ }
+ }
+ decoder::FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
+ let inlined_root_node_id = find_inlined_item_root(trait_item.id);
+ cache_inlined_item(def_id, trait_item.id, inlined_root_node_id);
+
+ // Associated consts already have to be evaluated in `typeck`, so
+ // the logic to do that already exists in `middle`. In order to
+ // reuse that code, it needs to be able to look up the traits for
+ // inlined items.
+ let ty_trait_item = tcx.impl_or_trait_item(def_id).clone();
+ let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
+ tcx.impl_or_trait_items.borrow_mut()
+ .insert(trait_item_def_id, ty_trait_item);
+ }
+ decoder::FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
+ let inlined_root_node_id = find_inlined_item_root(impl_item.id);
+ cache_inlined_item(def_id, impl_item.id, inlined_root_node_id);
+ }
+ }
+
+ // We can be sure to hit the cache now
+ return self.maybe_get_item_ast(tcx, def_id);
+ }
+
+ fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
+ assert!(!def_id.is_local());
+ match self.inlined_item_cache.borrow().get(&def_id) {
+ Some(&Some(ref cached_inlined_item)) => {
+ Some(cached_inlined_item.item_id)
+ }
+ Some(&None) => {
+ None
+ }
+ _ => {
+ bug!("Trying to lookup inlined NodeId for unexpected item");
+ }
+ }
+ }
+
+ fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
+ self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x)
}
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
visible_parent_map
}
}
+
use rustc::hir::def_id::{DefIndex, DefId};
use rustc::hir::map::DefKey;
use rustc::hir::svh::Svh;
-use rustc::middle::cstore::{ExternCrate};
+use rustc::middle::cstore::ExternCrate;
use rustc::session::config::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
pub explicitly_linked: Cell<bool>,
}
+pub struct CachedInlinedItem {
+ /// The NodeId of the RootInlinedParent HIR map entry
+ pub inlined_root: ast::NodeId,
+ /// The local NodeId of the inlined entity
+ pub item_id: ast::NodeId,
+}
+
pub struct CStore {
pub dep_graph: DepGraph,
metas: RefCell<FnvHashMap<ast::CrateNum, Rc<CrateMetadata>>>,
used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>,
used_link_args: RefCell<Vec<String>>,
statically_included_foreign_items: RefCell<NodeSet>,
+ pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
+ pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
}
used_link_args: RefCell::new(Vec::new()),
statically_included_foreign_items: RefCell::new(NodeSet()),
visible_parent_map: RefCell::new(FnvHashMap()),
+ inlined_item_cache: RefCell::new(FnvHashMap()),
+ defid_for_inlined_node: RefCell::new(FnvHashMap()),
}
}
use rustc::hir;
use rustc::session::config::PanicStrategy;
-use middle::cstore::{FoundAst, InlinedItem, LinkagePreference};
+use middle::cstore::{InlinedItem, LinkagePreference};
use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, DefIndex};
maybe_item_name(cdata.lookup_item(id))
}
+pub enum FoundAst<'ast> {
+ Found(&'ast InlinedItem),
+ FoundParent(DefId, &'ast hir::Item),
+ NotFound,
+}
+
pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
-> FoundAst<'tcx> {
debug!("Looking up item: {:?}", id);
inlined_vid: ast::NodeId)
-> ty::VariantDef<'tcx>
{
-
let ctor_ty = ccx.tcx().node_id_to_type(inlined_vid);
debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty,
inlined_vid);
}), ..}) => ty,
_ => ctor_ty
}.ty_adt_def().unwrap();
- let inlined_vid_def_id = ccx.tcx().map.local_def_id(inlined_vid);
- adt_def.variants.iter().find(|v| {
- inlined_vid_def_id == v.did ||
- ccx.external().borrow().get(&v.did) == Some(&Some(inlined_vid))
- }).unwrap_or_else(|| {
- bug!("no variant for {:?}::{}", adt_def, inlined_vid)
- })
+ let variant_def_id = if ccx.tcx().map.is_inlined(inlined_vid) {
+ ccx.defid_for_inlined_node(inlined_vid).unwrap()
+ } else {
+ ccx.tcx().map.local_def_id(inlined_vid)
+ };
+
+ adt_def.variants
+ .iter()
+ .find(|v| variant_def_id == v.did)
+ .unwrap_or_else(|| {
+ bug!("no variant for {:?}::{}", adt_def, inlined_vid)
+ })
}
// To avoid UB from LLVM, these two functions mask RHS with an
.get(TransItem::Static(id))
.expect("Local statics should always be in the SymbolMap");
// Make sure that this is never executed for something inlined.
- assert!(!ccx.external_srcs().borrow().contains_key(&id));
+ assert!(!ccx.tcx().map.is_inlined(id));
let defined_in_current_codegen_unit = ccx.codegen_unit()
.items()
use session::config;
use symbol_map::SymbolMap;
use util::sha2::Sha256;
-use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+use util::nodemap::{NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
- /// Track mapping of external ids to local items imported for inlining
- external: RefCell<DefIdMap<Option<ast::NodeId>>>,
- /// Backwards version of the `external` map (inlined items to where they
- /// came from)
- external_srcs: RefCell<NodeMap<DefId>>,
/// Cache instances of monomorphic and polymorphic items
instances: RefCell<FnvHashMap<Instance<'tcx>, ValueRef>>,
monomorphizing: RefCell<DefIdMap<usize>>,
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
fn_pointer_shims: RefCell::new(FnvHashMap()),
drop_glues: RefCell::new(FnvHashMap()),
- external: RefCell::new(DefIdMap()),
- external_srcs: RefCell::new(NodeMap()),
instances: RefCell::new(FnvHashMap()),
monomorphizing: RefCell::new(DefIdMap()),
vtables: RefCell::new(FnvHashMap()),
&self.local().drop_glues
}
- pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
- &self.local().external
+ pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option<ast::NodeId> {
+ self.sess().cstore.local_node_for_inlined_defid(def_id)
}
- pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<DefId>> {
- &self.local().external_srcs
+ pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> {
+ self.sess().cstore.defid_for_inlined_node(node_id)
}
pub fn instances<'a>(&'a self) -> &'a RefCell<FnvHashMap<Instance<'tcx>, ValueRef>> {
// First, find out the 'real' def_id of the type. Items inlined from
// other crates have to be mapped back to their source.
let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
- match cx.external_srcs().borrow().get(&node_id).cloned() {
- Some(source_def_id) => {
- // The given def_id identifies the inlined copy of a
- // type definition, let's take the source of the copy.
- source_def_id
- }
- None => def_id
+ if cx.tcx().map.is_inlined(node_id) {
+ // The given def_id identifies the inlined copy of a
+ // type definition, let's take the source of the copy.
+ cx.defid_for_inlined_node(node_id).unwrap()
+ } else {
+ def_id
}
} else {
def_id
// crate should already contain debuginfo for it. More importantly, the
// global might not even exist in un-inlined form anywhere which would lead
// to a linker errors.
- if cx.external_srcs().borrow().contains_key(&node_id) {
+ if cx.tcx().map.is_inlined(node_id) {
return;
}
});
// Try to get some span information, if we have an inlined item.
- let definition_span = match cx.external().borrow().get(&instance.def) {
- Some(&Some(node_id)) => cx.tcx().map.span(node_id),
- _ => cx.tcx().map.def_id_span(instance.def, syntax_pos::DUMMY_SP)
- };
+ let definition_span = cx.tcx()
+ .map
+ .def_id_span(instance.def, syntax_pos::DUMMY_SP);
(containing_scope, definition_span)
}
});
// Try to get some span information, if we have an inlined item.
- let definition_span = match cx.external().borrow().get(&def_id) {
- Some(&Some(node_id)) => cx.tcx().map.span(node_id),
- _ => cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP)
- };
+ let definition_span = cx.tcx().map.def_id_span(def_id, syntax_pos::DUMMY_SP);
(containing_scope, definition_span)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::cstore::{FoundAst, InlinedItem};
use rustc::hir::def_id::DefId;
use base::push_ctxt;
use common::*;
use monomorphize::Instance;
use rustc::dep_graph::DepNode;
-use rustc::hir;
fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
debug!("instantiate_inline({:?})", fn_id);
let tcx = ccx.tcx();
let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
- match ccx.external().borrow().get(&fn_id) {
- Some(&Some(node_id)) => {
- // Already inline
- debug!("instantiate_inline({}): already inline as node id {}",
- tcx.item_path_str(fn_id), node_id);
- let node_def_id = tcx.map.local_def_id(node_id);
- return Some(node_def_id);
- }
- Some(&None) => {
- return None; // Not inlinable
- }
- None => {
- // Not seen yet
- }
- }
-
- let inlined = tcx.sess.cstore.maybe_get_item_ast(tcx, fn_id);
- let inline_id = match inlined {
- FoundAst::NotFound => {
- ccx.external().borrow_mut().insert(fn_id, None);
- return None;
- }
- FoundAst::Found(&InlinedItem::Item(ref item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(item.id));
- ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
-
- ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
- item.id
- }
- FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(item.id));
- ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
- item.id
- }
- FoundAst::FoundParent(parent_id, item) => {
- ccx.external().borrow_mut().insert(parent_id, Some(item.id));
- ccx.external_srcs().borrow_mut().insert(item.id, parent_id);
-
- let mut my_id = 0;
- match item.node {
- hir::ItemEnum(ref ast_def, _) => {
- let ast_vs = &ast_def.variants;
- let ty_vs = &tcx.lookup_adt_def(parent_id).variants;
- assert_eq!(ast_vs.len(), ty_vs.len());
- for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
- if ty_v.did == fn_id { my_id = ast_v.node.data.id(); }
- ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.data.id()));
- ccx.external_srcs().borrow_mut().insert(ast_v.node.data.id(), ty_v.did);
- }
- }
- hir::ItemStruct(ref struct_def, _) => {
- if struct_def.is_struct() {
- bug!("instantiate_inline: called on a \
- non-tuple struct")
- } else {
- ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
- ccx.external_srcs().borrow_mut().insert(struct_def.id(), fn_id);
- my_id = struct_def.id();
- }
- }
- _ => bug!("instantiate_inline: item has a \
- non-enum, non-struct parent")
- }
- my_id
- }
- FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
- ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id);
-
- ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
- // Associated consts already have to be evaluated in `typeck`, so
- // the logic to do that already exists in `middle`. In order to
- // reuse that code, it needs to be able to look up the traits for
- // inlined items.
- let ty_trait_item = tcx.impl_or_trait_item(fn_id).clone();
- let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
- tcx.impl_or_trait_items.borrow_mut()
- .insert(trait_item_def_id, ty_trait_item);
-
- // If this is a default method, we can't look up the
- // impl type. But we aren't going to translate anyways, so
- // don't.
- trait_item.id
- }
- FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
- ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
- ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);
-
- ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-
- impl_item.id
- }
- };
-
- let inline_def_id = tcx.map.local_def_id(inline_id);
- Some(inline_def_id)
+ tcx.sess
+ .cstore
+ .maybe_get_item_ast(tcx, fn_id)
+ .map(|(_, inline_id)| {
+ tcx.map.local_def_id(inline_id)
+ })
}
pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
// After this point, bcx is the block for the call to panic.
bcx = panic_block.build();
+ debug_loc.apply_to_bcx(&bcx);
// Get the location information.
let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
// item is declared.
let bound = match (&ty.sty, ty_path_def) {
(_, Def::SelfTy(Some(trait_did), Some(impl_id))) => {
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems
+ // here. But we should never run into an impl from another crate
+ // in this pass.
+ assert!(impl_id != ast::DUMMY_NODE_ID);
+
// `Self` in an impl of a trait - we have a concrete self type and a
// trait reference.
let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
}
Def::SelfTy(_, Some(impl_id)) => {
// Self in impl (we know the concrete type).
+
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems
+ // here. But we should never run into an impl from another crate
+ // in this pass.
+ assert!(impl_id != ast::DUMMY_NODE_ID);
+
tcx.prohibit_type_params(base_segments);
let ty = tcx.node_id_to_type(impl_id);
if let Some(free_substs) = self.get_free_substs() {
/// to `trait_id` (this only cares about the trait, not the specific
/// method that is called)
pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) {
- let tcx = ccx.tcx;
- let did = Some(trait_id);
- let li = &tcx.lang_items;
-
- if did == li.drop_trait() {
- span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
- } else if !tcx.sess.features.borrow().unboxed_closures {
- // the #[feature(unboxed_closures)] feature isn't
- // activated so we need to enforce the closure
- // restrictions.
-
- let method = if did == li.fn_trait() {
- "call"
- } else if did == li.fn_mut_trait() {
- "call_mut"
- } else if did == li.fn_once_trait() {
- "call_once"
- } else {
- return // not a closure method, everything is OK.
- };
-
- struct_span_err!(tcx.sess, span, E0174,
- "explicit use of unboxed closure method `{}` is experimental",
- method)
- .help("add `#![feature(unboxed_closures)]` to the crate \
- attributes to enable")
- .emit();
+ if ccx.tcx.lang_items.drop_trait() == Some(trait_id) {
+ span_err!(ccx.tcx.sess, span, E0040, "explicit use of destructor method");
}
}
https://doc.rust-lang.org/book/traits.html
"##,
-E0174: r##"
-This error occurs because of the explicit use of unboxed closure methods
-that are an experimental feature in current Rust version.
-
-Example of erroneous code:
-
-```compile_fail
-fn foo<F: Fn(&str)>(mut f: F) {
- f.call(("call",));
- // error: explicit use of unboxed closure method `call`
- f.call_mut(("call_mut",));
- // error: explicit use of unboxed closure method `call_mut`
- f.call_once(("call_once",));
- // error: explicit use of unboxed closure method `call_once`
-}
-
-fn bar(text: &str) {
- println!("Calling {} it works!", text);
-}
-
-fn main() {
- foo(bar);
-}
-```
-
-Rust's implementation of closures is a bit different than other languages.
-They are effectively syntax sugar for traits `Fn`, `FnMut` and `FnOnce`.
-To understand better how the closures are implemented see here:
-https://doc.rust-lang.org/book/closures.html#closure-implementation
-
-To fix this you can call them using parenthesis, like this: `foo()`.
-When you execute the closure with parenthesis, under the hood you are executing
-the method `call`, `call_mut` or `call_once`. However, using them explicitly is
-currently an experimental feature.
-
-Example of an implicit call:
-
-```
-fn foo<F: Fn(&str)>(f: F) {
- f("using ()"); // Calling using () it works!
-}
-
-fn bar(text: &str) {
- println!("Calling {} it works!", text);
-}
-
-fn main() {
- foo(bar);
-}
-```
-
-To enable the explicit calls you need to add `#![feature(unboxed_closures)]`.
-
-This feature is still unstable so you will also need to add
-`#![feature(fn_traits)]`.
-More details about this issue here:
-https://github.com/rust-lang/rust/issues/29625
-
-Example of use:
-
-```
-#![feature(fn_traits)]
-#![feature(unboxed_closures)]
-
-fn foo<F: Fn(&str)>(mut f: F) {
- f.call(("call",)); // Calling 'call' it works!
- f.call_mut(("call_mut",)); // Calling 'call_mut' it works!
- f.call_once(("call_once",)); // Calling 'call_once' it works!
-}
-
-fn bar(text: &str) {
- println!("Calling '{}' it works!", text);
-}
-
-fn main() {
- foo(bar);
-}
-```
-
-To see more about closures take a look here:
-https://doc.rust-lang.org/book/closures.html`
-"##,
-
E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.
E0167,
// E0168,
// E0173, // manual implementations of unboxed closure traits are experimental
+// E0174,
E0182,
E0183,
// E0187, // can't infer the kind of the closure
Def::Static(i, _) => (i, TypeStatic),
Def::Variant(i, _) => (i, TypeEnum),
Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
- Def::SelfTy(_, Some(impl_id)) => return cx.map.local_def_id(impl_id),
+ Def::SelfTy(_, Some(impl_id)) => {
+ // For Def::SelfTy() values inlined from another crate, the
+ // impl_id will be DUMMY_NODE_ID, which would cause problems.
+ // But we should never run into an impl from another crate here.
+ return cx.map.local_def_id(impl_id)
+ }
_ => return def.def_id()
};
if did.is_local() { return did }
#![allow(dead_code)]
#![feature(rustc_attrs)]
-#![feature(unboxed_closures)]
#![deny(hr_lifetime_in_assoc_type)]
trait Foo<'a> {
#![allow(dead_code, unused_variables)]
#![deny(hr_lifetime_in_assoc_type)]
-#![feature(unboxed_closures)]
use std::str::Chars;
// Ensure that invoking a closure counts as a unique immutable borrow
-#![feature(unboxed_closures)]
-
type Fn<'a> = Box<FnMut() + 'a>;
struct Test<'a> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(overloaded_calls, unboxed_closures)]
-
fn a<F:Fn(isize, isize) -> isize>(mut f: F) {
let g = &mut f;
f(1, 2); //~ ERROR cannot borrow `f` as immutable
#![allow(dead_code)]
fn foo<F: Fn()>(mut f: F) {
- f.call(()); //~ ERROR explicit use of unboxed closure method `call`
- f.call_mut(()); //~ ERROR explicit use of unboxed closure method `call_mut`
- f.call_once(()); //~ ERROR explicit use of unboxed closure method `call_once`
+ f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
+ f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
+ f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
}
fn main() {}
#![allow(dead_code)]
-fn foo<F: Fn()>(mut f: F, mut g: F) {
- Fn::call(&g, ()); //~ ERROR explicit use of unboxed closure method `call`
- FnMut::call_mut(&mut g, ()); //~ ERROR explicit use of unboxed closure method `call_mut`
- FnOnce::call_once(g, ()); //~ ERROR explicit use of unboxed closure method `call_once`
+fn foo<F: Fn()>(mut f: F) {
+ Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+ FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+ FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
#![feature(box_syntax)]
fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(overloaded_calls, unboxed_closures)]
-
// Make sure we don't ICE when making an overloaded call with the
// wrong arity.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(overloaded_calls)]
-
fn f<'r>(p: &'r mut fn(p: &mut ())) {
(*p)(()) //~ ERROR mismatched types
//~| expected type `&mut ()`
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
bar.call((
&(), //~ ERROR borrowed value does not live long enough
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::marker;
struct B<T>(marker::PhantomData<T>);
// when a type error or unconstrained type variable propagates
// into it.
-#![feature(unboxed_closures)]
-
fn main() {
(return)((),());
//~^ ERROR the type of this value must be known
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn main() {
"".homura()(); //~ ERROR no method named `homura` found
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
#![allow(dead_code)]
type foo = fn(&u8, &u8) -> &u8; //~ ERROR missing lifetime specifier
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn id<T>(t: T) -> T { t }
fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
// bound must be noncopyable. For details see
// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
-#![feature(unboxed_closures)]
-
struct R<'a> {
// This struct is needed to create the
// otherwise infinite type of a fn that
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures, overloaded_calls)]
-
use std::ops::FnMut;
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn with_int(f: &mut FnMut(&isize)) {
}
// Test that closures cannot subvert aliasing restrictions
-#![feature(overloaded_calls, unboxed_closures)]
-
fn main() {
// Unboxed closure case
{
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
struct closure_box<'a> {
cl: Box<FnMut() + 'a>,
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
// Test that even unboxed closures that are capable of mutating their
// environment cannot mutate captured variables that have not been
// declared mutable (#18335)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
// Test that an unboxed closure that captures a free variable by
// reference cannot escape the region of that variable.
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR trait `Nonexist` is not in scope
type Typedef = isize;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
// Test that an unboxed closure that mutates a free variable will
// cause borrow conflicts.
// That a closure whose expected argument types include two distinct
// bound regions.
-#![feature(unboxed_closures)]
-
use std::cell::Cell;
fn doit<T,F>(val: T, f: &F)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
fn main() {
let mut zero = || {};
let () = zero.call_mut(());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
pub fn main() {
// Tests that unsafe extern fn pointers do not implement any Fn traits.
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
unsafe fn square(x: &isize) -> isize { (*x) * (*x) }
// Tests that unsafe extern fn pointers do not implement any Fn traits.
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
extern "C" fn square(x: &isize) -> isize { (*x) * (*x) }
// Tests that unsafe extern fn pointers do not implement any Fn traits.
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
unsafe fn square(x: isize) -> isize { x * x }
// lldb-check:[...]$2 = 5
#![allow(unused_variables)]
-#![feature(unboxed_closures, box_syntax)]
+#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
// lldb-command:print *owned
// lldb-check:[...]$9 = 6
-#![feature(unboxed_closures, box_syntax)]
+#![feature(box_syntax)]
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
// making method calls, but only if there aren't any matches without
// it.
-
-#![feature(unboxed_closures)]
-
trait iterable<A> {
fn iterate<F>(&self, blk: F) -> bool where F: FnMut(&A) -> bool;
}
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
#![no_implicit_prelude]
use std::marker::Sized;
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
#![no_implicit_prelude]
use std::marker::Sized;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
#![crate_type = "rlib"]
pub fn inner<F>(f: F) -> F {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::Add;
#[inline]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_f<F:FnMut()>(mut f: F) {
#![allow(unknown_features)]
#![feature(box_syntax)]
-#![feature(unboxed_closures)]
pub fn main() {
let bar: Box<_> = box 3;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) {
for val in x {
f(val)
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
use std::sync::mpsc::channel;
fn foo<F:FnOnce()+Send>(blk: F) {
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-#![feature(unboxed_closures)]
-
fn call_it<F>(f: F)
where F : FnOnce(String) -> String
{
// except according to those terms.
#![allow(unknown_features)]
-#![feature(unboxed_closures, std_misc)]
+#![feature(std_misc)]
/**
A somewhat reduced test case to expose some Valgrind issues.
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
#![allow(unused_variables)]
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
// Test that `F : Fn(isize) -> isize + Send` is interpreted as two
// distinct bounds on `F`.
// pretty-expanded FIXME #23616
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
// Test that `Fn(isize) -> isize + 'static` parses as `(Fn(isize) -> isize) +
// 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
// A basic test of using a higher-ranked trait bound.
trait FnLike<A,R> {
// Test HRTB used with the `Fn` trait.
-#![feature(unboxed_closures)]
-
fn foo<F:Fn(&isize)>(f: F) {
let x = 22;
f(&x);
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn f<F:FnOnce()>(p: F) {
p();
}
// ignore-emscripten no threads support
-#![feature(unboxed_closures)]
-
use std::thread;
use std::mem;
// ignore-pretty
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
struct Parser<'a, I, O> {
parse: Box<FnMut(I) -> Result<O, String> + 'a>
#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(box_patterns)]
-#![feature(unboxed_closures)]
use std::ops::{Deref, DerefMut};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::marker::PhantomData;
fn main() {
// once closure as an optimization by trans. This used to hit an
// incorrect assert.
-
-#![feature(unboxed_closures)]
-
fn main() {
let x = 2u8;
let y = 3u8;
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
trait Tr {
fn foo(&self);
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
// aux-build:issue-18711.rs
extern crate issue_18711 as issue;
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn foo<T, F: FnOnce(T) -> T>(f: F) {}
fn id<'a>(input: &'a u8) -> &'a u8 { input }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::marker::PhantomData;
#[derive(Debug)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(rustc_attrs, unboxed_closures, fn_traits)]
+#![feature(rustc_attrs, fn_traits)]
#[rustc_mir]
fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
use std::time::Duration;
use std::thread::{self, Builder};
+const TARGET_CNT: usize = 200;
+
fn main() {
// This test has a chance to time out, try to not let it time out
thread::spawn(move|| -> () {
});
let (tx, rx) = channel();
+
let mut spawned_cnt = 0;
- for _ in 0..1000 {
+ for _ in 0..TARGET_CNT {
let tx = tx.clone();
let res = Builder::new().stack_size(64 * 1024).spawn(move|| {
match TcpStream::connect(addr) {
for _ in 0..spawned_cnt {
rx.recv().unwrap();
}
- assert_eq!(spawned_cnt, 1000);
+ assert_eq!(spawned_cnt, TARGET_CNT);
process::exit(0);
}
#![allow(unknown_features)]
#![feature(box_syntax, std_misc)]
-#![feature(unboxed_closures)]
use std::sync::Arc;
use std::sync::mpsc::channel;
// Also acts as a regression test for an ICE (issue #19791)
-#![feature(unboxed_closures, core)]
+#![feature(core)]
use std::any::{Any, TypeId};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize {
f(1, 2)
// Test that you can supply `&F` where `F: FnMut()`.
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
fn a<F:FnMut() -> i32>(mut f: F) -> i32 {
f()
// Test that you can supply `&F` where `F: Fn()`.
-
-#![feature(lang_items, unboxed_closures)]
+#![feature(lang_items)]
fn a<F:Fn() -> i32>(f: F) -> i32 {
f()
#![allow(unknown_features)]
#![feature(box_syntax)]
-#![feature(unboxed_closures)]
use std::ops::FnMut;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
// Test by-ref capture of environment in unboxed closure types
fn call_fn<F: Fn()>(f: F) {
// Test that the call operator autoderefs when calling a bounded type parameter.
-
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_with_2(x: &fn(isize) -> isize) -> isize
// Test that the call operator autoderefs when calling a bounded type parameter.
-
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_with_2<F>(x: &mut F) -> isize
// Test that the call operator autoderefs when calling to an object type.
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
use std::ops::FnMut;
// except according to those terms.
#![allow(unknown_features)]
-#![feature(unboxed_closures)]
use std::ops::FnMut;
// Test that we mutate a counter on the stack only when we expect to.
-
fn call<F>(f: F) where F : FnOnce() {
f();
}
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn main() {
let mut unboxed = || {};
unboxed();
// A battery of tests to ensure destructors of unboxed closure environments
// run at the right times.
-
-#![feature(unboxed_closures)]
-
static mut DROP_COUNT: usize = 0;
fn drop_count() -> usize {
// Checks that extern fn pointers implement the full range of Fn traits.
-
-#![feature(unboxed_closures)]
-#![feature(unboxed_closures)]
-
use std::ops::{Fn,FnMut,FnOnce};
fn square(x: isize) -> isize { x * x }
// Checks that the Fn trait hierarchy rules permit
// any Fn trait to be used where Fn is implemented.
-
#![feature(unboxed_closures, fn_traits)]
use std::ops::{Fn,FnMut,FnOnce};
// Checks that the Fn trait hierarchy rules permit
// FnMut or FnOnce to be used where FnMut is implemented.
-
#![feature(unboxed_closures, fn_traits)]
struct S;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
fn call_it<F:FnMut(i32,i32)->i32>(y: i32, mut f: F) -> i32 {
// Test that we are able to infer a suitable kind for this closure
// that is just called (`FnMut`).
-
fn main() {
let mut counter = 0;
// Test that we are able to infer a suitable kind for this `move`
// closure that is just called (`FnMut`).
-
fn main() {
let mut counter = 0;
// Test that we are able to infer a suitable kind for this closure
// that is just called (`FnMut`).
-
fn main() {
let mut counter = 0;
// Test that we can infer the "kind" of an unboxed closure based on
// the expected type.
-
-#![feature(unboxed_closures)]
-
// Test by-ref capture of environment in unboxed closure types
fn call_fn<F: Fn()>(f: F) {
// Test that the type variable in the type(`Vec<_>`) of a closed over
// variable does not interfere with type inference.
-
fn f<F: FnMut()>(mut f: F) {
f();
}
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
#![deny(unused_mut)]
// Test that mutating a mutable upvar in a capture-by-value unboxed
// Test that in a by-ref once closure we move some variables even as
// we capture others by mutable reference.
-
fn call<F>(f: F) where F : FnOnce() {
f();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(unboxed_closures)]
-
use std::ops::FnMut;
pub fn main() {
// Ensures that single-word environments work right in unboxed closures.
// These take a different path in codegen.
-
-#![feature(unboxed_closures)]
-
fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize {
f(1, 2)
}
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn main() {
let onetime = |x| x;
onetime(0);
// Test unboxed closure sugar used in object types.
-
#![allow(dead_code)]
-#![feature(unboxed_closures)]
struct Foo<T,U> {
t: T, u: U
//
// compile-flags: -g
-
-#![feature(unboxed_closures)]
-
use std::ptr;
pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T {
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
fn main() {
let mut zero = || {};
let () = zero();
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures)]
-
struct Bencher;
// ICE