Auto merge of #35163 - sanxiyn:rollup, r=sanxiyn

Rollup of 8 pull requests

- Successful merges: #34802, #35033, #35085, #35114, #35134, #35140, #35141, #35157
- Failed merges:
This commit is contained in:
bors 2016-08-01 08:57:32 -07:00 committed by GitHub
commit 28ce3e8a55
121 changed files with 372 additions and 474 deletions

View File

@ -7,6 +7,7 @@ services:
# 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

View File

@ -23,11 +23,5 @@ RUN apt-get update && apt-get -y install \
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

View File

@ -49,7 +49,6 @@
#![feature(specialization)]
#![feature(staged_api)]
#![feature(step_by)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]

View File

@ -577,15 +577,13 @@ impl<T> [T] {
///
/// # 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]

View File

@ -31,7 +31,6 @@
#![feature(step_by)]
#![feature(test)]
#![feature(try_from)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]

View File

@ -867,7 +867,7 @@ pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
}
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)]
pub struct IdRange {
pub min: NodeId,
pub max: NodeId,
@ -893,6 +893,7 @@ impl IdRange {
self.min = cmp::min(self.min, id);
self.max = cmp::max(self.max, id + 1);
}
}

View File

@ -32,6 +32,7 @@ use hir::print as pprust;
use arena::TypedArena;
use std::cell::RefCell;
use std::cmp;
use std::io;
use std::mem;
@ -127,7 +128,10 @@ impl<'ast> MapEntry<'ast> {
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
EntryTyParam(id, _) => id,
_ => return None
NotPresent |
RootCrate |
RootInlinedParent(_) => return None,
})
}
@ -196,6 +200,10 @@ pub struct Map<'ast> {
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> {
@ -550,6 +558,13 @@ 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) {
@ -649,6 +664,10 @@ impl<'ast> Map<'ast> {
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> {
@ -765,13 +784,37 @@ pub trait FoldOps {
}
/// 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 {
@ -802,11 +845,14 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
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
}
}
@ -818,7 +864,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
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) => {
@ -835,6 +881,12 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
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(),

View File

@ -120,12 +120,6 @@ pub struct ChildItem {
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
@ -250,7 +244,10 @@ pub trait CrateStore<'tcx> {
// 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;
@ -447,7 +444,16 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
// 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 {

View File

@ -12,6 +12,7 @@ use target::{Target, TargetResult};
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();

View File

@ -12,6 +12,7 @@ use target::{Target, TargetResult};
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());

View File

@ -12,6 +12,7 @@ use target::{Target, TargetResult};
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());

View File

@ -17,7 +17,7 @@ use self::EvalHint::*;
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;
@ -142,13 +142,13 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
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 {
@ -163,7 +163,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
_ => 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)))
},
@ -198,8 +198,8 @@ fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
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,

View File

@ -31,7 +31,6 @@
#![feature(set_stdio)]
#![feature(staged_api)]
#![feature(question_mark)]
#![feature(unboxed_closures)]
extern crate arena;
extern crate flate;

View File

@ -88,8 +88,9 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
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);
@ -186,6 +187,10 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
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))
@ -279,9 +284,23 @@ fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
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| {
@ -322,10 +341,12 @@ impl Folder for NestedItemsDropper {
// 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)))
@ -339,7 +360,9 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
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 {
@ -361,8 +384,18 @@ impl tr for Def {
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) }
@ -1361,7 +1394,7 @@ fn test_simplification() {
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(&quote_item!(&cx,
fn new_int_alist<B>() -> alist<isize, B> {
return alist {eq_fn: eq_int, data: Vec::new()};

View File

@ -14,7 +14,7 @@ use decoder;
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;
@ -482,12 +482,146 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
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)
@ -634,3 +768,4 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
visible_parent_map
}
}

View File

@ -25,7 +25,7 @@ use rustc::dep_graph::DepGraph;
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};
@ -96,6 +96,13 @@ pub struct CrateMetadata {
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>>>,
@ -105,6 +112,8 @@ pub struct CStore {
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>>,
}
@ -119,6 +128,8 @@ impl CStore {
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()),
}
}

View File

@ -30,7 +30,7 @@ use rustc::util::nodemap::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};
@ -755,6 +755,12 @@ pub fn maybe_get_item_name(cdata: Cmd, id: DefIndex) -> Option<ast::Name> {
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);

View File

@ -1235,7 +1235,6 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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);
@ -1245,13 +1244,18 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}), ..}) => 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

View File

@ -1026,7 +1026,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
.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()

View File

@ -37,7 +37,7 @@ use session::Session;
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};
@ -102,11 +102,6 @@ pub struct LocalCrateContext<'tcx> {
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>>,
@ -630,8 +625,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
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()),
@ -825,12 +818,12 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&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>> {

View File

@ -326,13 +326,12 @@ impl<'tcx> TypeMap<'tcx> {
// 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
@ -1846,7 +1845,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
// 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;
}

View File

@ -438,10 +438,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
});
// 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)
}

View File

@ -86,10 +86,7 @@ pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
});
// 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)
}

View File

@ -8,14 +8,12 @@
// 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);
@ -23,104 +21,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
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)

View File

@ -284,6 +284,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
// 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);

View File

@ -1313,6 +1313,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// 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();
@ -1518,6 +1524,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
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() {

View File

@ -27,33 +27,8 @@ use rustc::hir;
/// 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");
}
}

View File

@ -1944,89 +1944,6 @@ To learn more about traits, take a look at the Book:
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.
@ -4049,6 +3966,7 @@ register_diagnostics! {
E0167,
// E0168,
// E0173, // manual implementations of unboxed closure traits are experimental
// E0174,
E0182,
E0183,
// E0187, // can't infer the kind of the closure

View File

@ -2691,7 +2691,12 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
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 }

View File

@ -12,7 +12,6 @@
#![allow(dead_code)]
#![feature(rustc_attrs)]
#![feature(unboxed_closures)]
#![deny(hr_lifetime_in_assoc_type)]
trait Foo<'a> {

View File

@ -13,7 +13,6 @@
#![allow(dead_code, unused_variables)]
#![deny(hr_lifetime_in_assoc_type)]
#![feature(unboxed_closures)]
use std::str::Chars;

View File

@ -10,8 +10,6 @@
// Ensure that invoking a closure counts as a unique immutable borrow
#![feature(unboxed_closures)]
type Fn<'a> = Box<FnMut() + 'a>;
struct Test<'a> {

View File

@ -8,8 +8,6 @@
// 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

View File

@ -11,9 +11,9 @@
#![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() {}

View File

@ -10,10 +10,10 @@
#![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() {}

View File

@ -8,7 +8,6 @@
// 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 {}

View File

@ -8,8 +8,6 @@
// 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.

View File

@ -8,8 +8,6 @@
// 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 ()`

View File

@ -8,8 +8,6 @@
// 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

View File

@ -8,8 +8,6 @@
// 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>);

View File

@ -12,8 +12,6 @@
// 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

View File

@ -8,8 +8,6 @@
// 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
}

View File

@ -8,7 +8,6 @@
// 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

View File

@ -8,8 +8,6 @@
// 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> {

View File

@ -12,8 +12,6 @@
// 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

View File

@ -8,8 +8,6 @@
// 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() {

View File

@ -8,8 +8,6 @@
// 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)) {
}

View File

@ -10,8 +10,6 @@
// Test that closures cannot subvert aliasing restrictions
#![feature(overloaded_calls, unboxed_closures)]
fn main() {
// Unboxed closure case
{

View File

@ -8,8 +8,6 @@
// 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>,
}

View File

@ -8,8 +8,6 @@
// 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)

View File

@ -8,8 +8,6 @@
// 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() {

View File

@ -8,8 +8,6 @@
// 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;

View File

@ -8,8 +8,6 @@
// 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.

View File

@ -11,8 +11,6 @@
// 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)

View File

@ -8,8 +8,6 @@
// 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(());

View File

@ -8,8 +8,6 @@
// 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() {

View File

@ -10,8 +10,6 @@
// 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) }

View File

@ -10,8 +10,6 @@
// 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) }

View File

@ -10,8 +10,6 @@
// 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 }

View File

@ -40,7 +40,7 @@
// 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]

View File

@ -69,7 +69,7 @@
// 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]

View File

@ -12,9 +12,6 @@
// 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;
}

View File

@ -14,7 +14,7 @@
// 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;

View File

@ -14,7 +14,7 @@
// 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;

View File

@ -8,7 +8,6 @@
// 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 {

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(unboxed_closures)]
use std::ops::Add;
#[inline]

View File

@ -8,8 +8,6 @@
// 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) {

View File

@ -11,7 +11,6 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(unboxed_closures)]
pub fn main() {
let bar: Box<_> = box 3;

View File

@ -8,9 +8,6 @@
// 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)

View File

@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
#![feature(unboxed_closures)]
use std::sync::mpsc::channel;
fn foo<F:FnOnce()+Send>(blk: F) {

View File

@ -11,8 +11,6 @@
/* 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
{

View File

@ -9,7 +9,7 @@
// 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.

View File

@ -13,7 +13,6 @@
// pretty-expanded FIXME #23616
#![feature(unboxed_closures)]
#![allow(unused_variables)]
#![allow(dead_code)]

View File

@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
#![feature(unboxed_closures)]
// Test that `F : Fn(isize) -> isize + Send` is interpreted as two
// distinct bounds on `F`.

View File

@ -11,7 +11,6 @@
// 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

View File

@ -8,9 +8,6 @@
// 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> {

View File

@ -10,8 +10,6 @@
// Test HRTB used with the `Fn` trait.
#![feature(unboxed_closures)]
fn foo<F:Fn(&isize)>(f: F) {
let x = 22;
f(&x);

View File

@ -10,8 +10,6 @@
// pretty-expanded FIXME #23616
#![feature(unboxed_closures)]
fn f<F:FnOnce()>(p: F) {
p();
}

View File

@ -10,8 +10,6 @@
// ignore-emscripten no threads support
#![feature(unboxed_closures)]
use std::thread;
use std::mem;

View File

@ -11,7 +11,6 @@
// ignore-pretty
#![allow(unknown_features)]
#![feature(unboxed_closures)]
struct Parser<'a, I, O> {
parse: Box<FnMut(I) -> Result<O, String> + 'a>

View File

@ -12,7 +12,6 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(unboxed_closures)]
use std::ops::{Deref, DerefMut};

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(unboxed_closures)]
use std::marker::PhantomData;
fn main() {

View File

@ -12,9 +12,6 @@
// 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;

View File

@ -13,8 +13,6 @@
// pretty-expanded FIXME #23616
#![feature(unboxed_closures)]
trait Tr {
fn foo(&self);

View File

@ -13,8 +13,6 @@
// pretty-expanded FIXME #23616
#![feature(unboxed_closures)]
// aux-build:issue-18711.rs
extern crate issue_18711 as issue;

View File

@ -10,8 +10,6 @@
// 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 }

View File

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(unboxed_closures)]
use std::marker::PhantomData;
#[derive(Debug)]

View File

@ -8,7 +8,7 @@
// 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]) {

View File

@ -21,6 +21,8 @@ use std::sync::mpsc::channel;
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|| -> () {
@ -42,8 +44,9 @@ fn main() {
});
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) {
@ -66,6 +69,6 @@ fn main() {
for _ in 0..spawned_cnt {
rx.recv().unwrap();
}
assert_eq!(spawned_cnt, 1000);
assert_eq!(spawned_cnt, TARGET_CNT);
process::exit(0);
}

View File

@ -16,7 +16,6 @@
#![allow(unknown_features)]
#![feature(box_syntax, std_misc)]
#![feature(unboxed_closures)]
use std::sync::Arc;
use std::sync::mpsc::channel;

View File

@ -12,7 +12,7 @@
// Also acts as a regression test for an ICE (issue #19791)
#![feature(unboxed_closures, core)]
#![feature(core)]
use std::any::{Any, TypeId};

View File

@ -8,8 +8,7 @@
// 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)

View File

@ -10,8 +10,7 @@
// 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()

View File

@ -10,8 +10,7 @@
// 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()

View File

@ -10,7 +10,6 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
#![feature(unboxed_closures)]
use std::ops::FnMut;

View File

@ -8,9 +8,6 @@
// 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) {

View File

@ -10,9 +10,6 @@
// 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

View File

@ -10,9 +10,6 @@
// 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

View File

@ -11,7 +11,6 @@
// Test that the call operator autoderefs when calling to an object type.
#![allow(unknown_features)]
#![feature(unboxed_closures)]
use std::ops::FnMut;

View File

@ -9,7 +9,6 @@
// except according to those terms.
#![allow(unknown_features)]
#![feature(unboxed_closures)]
use std::ops::FnMut;

Some files were not shown because too many files have changed in this diff Show More