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:
commit
28ce3e8a55
@ -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
|
||||
|
@ -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
|
||||
|
@ -49,7 +49,6 @@
|
||||
#![feature(specialization)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(step_by)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
#![feature(unsafe_no_drop_flag)]
|
||||
|
@ -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]
|
||||
|
@ -31,7 +31,6 @@
|
||||
#![feature(step_by)]
|
||||
#![feature(test)]
|
||||
#![feature(try_from)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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,
|
||||
|
@ -31,7 +31,6 @@
|
||||
#![feature(set_stdio)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(question_mark)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
extern crate arena;
|
||||
extern crate flate;
|
||||
|
@ -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("e_item!(&cx,
|
||||
fn new_int_alist<B>() -> alist<isize, B> {
|
||||
return alist {eq_fn: eq_int, data: Vec::new()};
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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>> {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![deny(hr_lifetime_in_assoc_type)]
|
||||
|
||||
trait Foo<'a> {
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#![allow(dead_code, unused_variables)]
|
||||
#![deny(hr_lifetime_in_assoc_type)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::str::Chars;
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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() {}
|
||||
|
@ -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 {}
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 ()`
|
||||
|
@ -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
|
||||
|
@ -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>);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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)) {
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// Test that closures cannot subvert aliasing restrictions
|
||||
|
||||
#![feature(overloaded_calls, unboxed_closures)]
|
||||
|
||||
fn main() {
|
||||
// Unboxed closure case
|
||||
{
|
||||
|
@ -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>,
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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(());
|
||||
|
@ -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() {
|
||||
|
@ -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) }
|
||||
|
@ -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) }
|
||||
|
@ -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 }
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
||||
|
@ -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) {
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
pub fn main() {
|
||||
let bar: Box<_> = box 3;
|
||||
|
@ -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)
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
fn foo<F:FnOnce()+Send>(blk: F) {
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
@ -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`.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
fn f<F:FnOnce()>(p: F) {
|
||||
p();
|
||||
}
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// ignore-emscripten no threads support
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::thread;
|
||||
use std::mem;
|
||||
|
||||
|
@ -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>
|
||||
|
@ -12,7 +12,6 @@
|
||||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
|
@ -13,8 +13,6 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
trait Tr {
|
||||
fn foo(&self);
|
||||
|
||||
|
@ -13,8 +13,6 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
// aux-build:issue-18711.rs
|
||||
extern crate issue_18711 as issue;
|
||||
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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]) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax, std_misc)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::channel;
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use std::ops::FnMut;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user