mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #23337 - Manishearth:rollup, r=Manishearth
r? @Manishearth
This commit is contained in:
commit
9eb69abad8
@ -44,10 +44,10 @@ $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger
|
||||
touch -r $$@.start_time $$@ && rm $$@.start_time
|
||||
|
||||
ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1)
|
||||
LLVM_STDCPP_LOCATION_$(1) = $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
|
||||
-print-file-name=libstdc++.a)
|
||||
LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
|
||||
-print-file-name=libstdc++.a))"
|
||||
else
|
||||
LLVM_STDCPP_LOCATION_$(1) =
|
||||
LLVM_STDCPP_RUSTFLAGS_$(1) =
|
||||
endif
|
||||
|
||||
|
||||
|
@ -30,8 +30,8 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
|
||||
CFG_DISABLE_UNSTABLE_FEATURES=1
|
||||
endif
|
||||
ifeq ($(CFG_RELEASE_CHANNEL),beta)
|
||||
CFG_RELEASE=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION)
|
||||
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta(CFG_PRERELEASE_VERSION)
|
||||
CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
|
||||
CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
|
||||
CFG_DISABLE_UNSTABLE_FEATURES=1
|
||||
endif
|
||||
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
|
||||
|
@ -85,7 +85,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
|
||||
$$(RUST_LIB_FLAGS_ST$(1)) \
|
||||
-L "$$(RT_OUTPUT_DIR_$(2))" \
|
||||
-L "$$(LLVM_LIBDIR_$(2))" \
|
||||
-L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
|
||||
$$(LLVM_STDCPP_RUSTFLAGS_$(2)) \
|
||||
$$(RUSTFLAGS_$(4)) \
|
||||
--out-dir $$(@D) \
|
||||
-C extra-filename=-$$(CFG_FILENAME_EXTRA) \
|
||||
|
@ -85,9 +85,11 @@ Hello, world!
|
||||
Bam! We build our project with `cargo build`, and run it with
|
||||
`./target/debug/hello_world`. This hasn't bought us a whole lot over our simple use
|
||||
of `rustc`, but think about the future: when our project has more than one
|
||||
file, we would need to call `rustc` more than once, and pass it a bunch of options to
|
||||
file, we would need to call `rustc` more than once and pass it a bunch of options to
|
||||
tell it to build everything together. With Cargo, as our project grows, we can
|
||||
just `cargo build` and it'll work the right way. When you're project is finally ready for release, you can use `cargo build --release` to compile your crates with optimizations.
|
||||
just `cargo build`, and it'll work the right way. When your project is finally
|
||||
ready for release, you can use `cargo build --release` to compile your crates with
|
||||
optimizations.
|
||||
|
||||
You'll also notice that Cargo has created a new file: `Cargo.lock`.
|
||||
|
||||
|
@ -27,9 +27,18 @@ def rust_pretty_printer_lookup_function(val):
|
||||
if type_code == gdb.TYPE_CODE_STRUCT:
|
||||
struct_kind = classify_struct(val.type)
|
||||
|
||||
if struct_kind == STRUCT_KIND_SLICE:
|
||||
return RustSlicePrinter(val)
|
||||
|
||||
if struct_kind == STRUCT_KIND_STR_SLICE:
|
||||
return RustStringSlicePrinter(val)
|
||||
|
||||
if struct_kind == STRUCT_KIND_STD_VEC:
|
||||
return RustStdVecPrinter(val)
|
||||
|
||||
if struct_kind == STRUCT_KIND_STD_STRING:
|
||||
return RustStdStringPrinter(val)
|
||||
|
||||
if struct_kind == STRUCT_KIND_TUPLE:
|
||||
return RustTuplePrinter(val)
|
||||
|
||||
@ -172,6 +181,28 @@ class RustTupleStructPrinter:
|
||||
def display_hint(self):
|
||||
return "array"
|
||||
|
||||
class RustSlicePrinter:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def display_hint(self):
|
||||
return "array"
|
||||
|
||||
def to_string(self):
|
||||
length = int(self.val["length"])
|
||||
return self.val.type.tag + ("(len: %i)" % length)
|
||||
|
||||
def children(self):
|
||||
cs = []
|
||||
length = int(self.val["length"])
|
||||
data_ptr = self.val["data_ptr"]
|
||||
assert data_ptr.type.code == gdb.TYPE_CODE_PTR
|
||||
pointee_type = data_ptr.type.target()
|
||||
|
||||
for index in range(0, length):
|
||||
cs.append((str(index), (data_ptr + index).dereference()))
|
||||
|
||||
return cs
|
||||
|
||||
class RustStringSlicePrinter:
|
||||
def __init__(self, val):
|
||||
@ -181,6 +212,35 @@ class RustStringSlicePrinter:
|
||||
slice_byte_len = self.val["length"]
|
||||
return '"%s"' % self.val["data_ptr"].string(encoding="utf-8", length=slice_byte_len)
|
||||
|
||||
class RustStdVecPrinter:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def display_hint(self):
|
||||
return "array"
|
||||
|
||||
def to_string(self):
|
||||
length = int(self.val["len"])
|
||||
cap = int(self.val["cap"])
|
||||
return self.val.type.tag + ("(len: %i, cap: %i)" % (length, cap))
|
||||
|
||||
def children(self):
|
||||
cs = []
|
||||
(length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val)
|
||||
pointee_type = data_ptr.type.target()
|
||||
|
||||
for index in range(0, length):
|
||||
cs.append((str(index), (data_ptr + index).dereference()))
|
||||
return cs
|
||||
|
||||
class RustStdStringPrinter:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def to_string(self):
|
||||
(length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val["vec"])
|
||||
return '"%s"' % data_ptr.string(encoding="utf-8", length=length)
|
||||
|
||||
|
||||
class RustCStyleEnumPrinter:
|
||||
def __init__(self, val):
|
||||
@ -204,19 +264,38 @@ STRUCT_KIND_TUPLE = 2
|
||||
STRUCT_KIND_TUPLE_VARIANT = 3
|
||||
STRUCT_KIND_STRUCT_VARIANT = 4
|
||||
STRUCT_KIND_CSTYLE_VARIANT = 5
|
||||
STRUCT_KIND_STR_SLICE = 6
|
||||
STRUCT_KIND_SLICE = 6
|
||||
STRUCT_KIND_STR_SLICE = 7
|
||||
STRUCT_KIND_STD_VEC = 8
|
||||
STRUCT_KIND_STD_STRING = 9
|
||||
|
||||
|
||||
def classify_struct(type):
|
||||
# print("\nclassify_struct: tag=%s\n" % type.tag)
|
||||
if type.tag == "&str":
|
||||
return STRUCT_KIND_STR_SLICE
|
||||
|
||||
if type.tag.startswith("&[") and type.tag.endswith("]"):
|
||||
return STRUCT_KIND_SLICE
|
||||
|
||||
fields = list(type.fields())
|
||||
field_count = len(fields)
|
||||
|
||||
if field_count == 0:
|
||||
return STRUCT_KIND_REGULAR_STRUCT
|
||||
|
||||
if (field_count == 3 and
|
||||
fields[0].name == "ptr" and
|
||||
fields[1].name == "len" and
|
||||
fields[2].name == "cap" and
|
||||
type.tag.startswith("Vec<")):
|
||||
return STRUCT_KIND_STD_VEC
|
||||
|
||||
if (field_count == 1 and
|
||||
fields[0].name == "vec" and
|
||||
type.tag == "String"):
|
||||
return STRUCT_KIND_STD_STRING
|
||||
|
||||
if fields[0].name == "RUST$ENUM$DISR":
|
||||
if field_count == 1:
|
||||
return STRUCT_KIND_CSTYLE_VARIANT
|
||||
@ -254,3 +333,11 @@ def get_field_at_index(val, index):
|
||||
return field
|
||||
i += 1
|
||||
return None
|
||||
|
||||
def extract_length_and_data_ptr_from_std_vec(vec_val):
|
||||
length = int(vec_val["len"])
|
||||
vec_ptr_val = vec_val["ptr"]
|
||||
unique_ptr_val = vec_ptr_val[first_field(vec_ptr_val)]
|
||||
data_ptr = unique_ptr_val[first_field(unique_ptr_val)]
|
||||
assert data_ptr.type.code == gdb.TYPE_CODE_PTR
|
||||
return (length, data_ptr)
|
@ -198,6 +198,7 @@ mod imp {
|
||||
extern {}
|
||||
|
||||
extern {
|
||||
#[allocator]
|
||||
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
|
||||
fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
|
||||
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
|
||||
|
@ -69,6 +69,7 @@
|
||||
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
#![feature(allocator)]
|
||||
#![feature(lang_items, unsafe_destructor)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
@ -70,9 +70,7 @@ mod sip;
|
||||
/// A hashable type.
|
||||
///
|
||||
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
|
||||
/// to compute the hash. Specific implementations of this trait may specialize
|
||||
/// for particular instances of `H` in order to be able to optimize the hashing
|
||||
/// behavior.
|
||||
/// to compute the hash.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Hash {
|
||||
/// Feeds this value into the state given, updating the hasher as necessary.
|
||||
|
@ -33,31 +33,34 @@
|
||||
//! let my_speed_ptr: *mut i32 = &mut my_speed;
|
||||
//! ```
|
||||
//!
|
||||
//! To get a pointer to a boxed value, dereference the box:
|
||||
//!
|
||||
//! ```
|
||||
//! let my_num: Box<i32> = Box::new(10);
|
||||
//! let my_num_ptr: *const i32 = &*my_num;
|
||||
//! let mut my_speed: Box<i32> = Box::new(88);
|
||||
//! let my_speed_ptr: *mut i32 = &mut *my_speed;
|
||||
//! ```
|
||||
//!
|
||||
//! This does not take ownership of the original allocation
|
||||
//! and requires no resource management later,
|
||||
//! but you must not use the pointer after its lifetime.
|
||||
//!
|
||||
//! ## 2. Transmute an owned box (`Box<T>`).
|
||||
//! ## 2. Consume a box (`Box<T>`).
|
||||
//!
|
||||
//! The `transmute` function takes, by value, whatever it's given
|
||||
//! and returns it as whatever type is requested, as long as the
|
||||
//! types are the same size. Because `Box<T>` and `*mut T` have the same
|
||||
//! representation they can be trivially,
|
||||
//! though unsafely, transformed from one type to the other.
|
||||
//! The `into_raw` function consumes a box and returns
|
||||
//! the raw pointer. It doesn't destroy `T` or deallocate any memory.
|
||||
//!
|
||||
//! ```
|
||||
//! use std::mem;
|
||||
//! use std::boxed;
|
||||
//!
|
||||
//! unsafe {
|
||||
//! let my_num: Box<i32> = Box::new(10);
|
||||
//! let my_num: *const i32 = mem::transmute(my_num);
|
||||
//! let my_speed: Box<i32> = Box::new(88);
|
||||
//! let my_speed: *mut i32 = mem::transmute(my_speed);
|
||||
//! let my_speed: *mut i32 = boxed::into_raw(my_speed);
|
||||
//!
|
||||
//! // By taking ownership of the original `Box<T>` though
|
||||
//! // we are obligated to transmute it back later to be destroyed.
|
||||
//! drop(mem::transmute::<_, Box<i32>>(my_speed));
|
||||
//! drop(mem::transmute::<_, Box<i32>>(my_num));
|
||||
//! // we are obligated to put it together later to be destroyed.
|
||||
//! drop(Box::from_raw(my_speed));
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
@ -411,3 +411,8 @@ pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) ->
|
||||
let cdata = cstore.get_crate_data(trait_def_id.krate);
|
||||
decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
|
||||
}
|
||||
|
||||
pub fn is_default_impl(cstore: &cstore::CStore, impl_did: ast::DefId) -> bool {
|
||||
let cdata = cstore.get_crate_data(impl_did.krate);
|
||||
decoder::is_default_impl(&*cdata, impl_did.node)
|
||||
}
|
||||
|
@ -1537,13 +1537,18 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_defaulted_trait<'tcx>(cdata: Cmd, trait_id: ast::NodeId) -> bool {
|
||||
pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
|
||||
let trait_doc = lookup_item(trait_id, cdata.data());
|
||||
assert!(item_family(trait_doc) == Family::Trait);
|
||||
let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
|
||||
reader::doc_as_u8(defaulted_doc) != 0
|
||||
}
|
||||
|
||||
pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool {
|
||||
let impl_doc = lookup_item(impl_id, cdata.data());
|
||||
item_family(impl_doc) == Family::DefaultImpl
|
||||
}
|
||||
|
||||
pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
|
||||
let crate_doc = rbml::Doc::new(metadata);
|
||||
let cm_doc = reader::get_doc(crate_doc, tag_codemap);
|
||||
|
@ -47,6 +47,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
|
||||
struct_has_extern_repr: bool,
|
||||
ignore_non_const_paths: bool,
|
||||
inherited_pub_visibility: bool,
|
||||
ignore_variant_stack: Vec<ast::NodeId>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
@ -59,6 +60,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
struct_has_extern_repr: false,
|
||||
ignore_non_const_paths: false,
|
||||
inherited_pub_visibility: false,
|
||||
ignore_variant_stack: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +81,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
def::DefPrimTy(_) => (),
|
||||
def::DefVariant(enum_id, variant_id, _) => {
|
||||
self.check_def_id(enum_id);
|
||||
self.check_def_id(variant_id);
|
||||
if !self.ignore_variant_stack.contains(&variant_id.node) {
|
||||
self.check_def_id(variant_id);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.check_def_id(def.def_id());
|
||||
@ -278,6 +282,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
||||
visit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, arm: &ast::Arm) {
|
||||
if arm.pats.len() == 1 {
|
||||
let pat = &*arm.pats[0];
|
||||
let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
|
||||
|
||||
// Inside the body, ignore constructions of variants
|
||||
// necessary for the pattern to match. Those construction sites
|
||||
// can't be reached unless the variant is constructed elsewhere.
|
||||
let len = self.ignore_variant_stack.len();
|
||||
self.ignore_variant_stack.push_all(&*variants);
|
||||
visit::walk_arm(self, arm);
|
||||
self.ignore_variant_stack.truncate(len);
|
||||
} else {
|
||||
visit::walk_arm(self, arm);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &ast::Pat) {
|
||||
let def_map = &self.tcx.def_map;
|
||||
match pat.node {
|
||||
@ -397,6 +418,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
|
||||
worklist.push(*id);
|
||||
}
|
||||
for id in reachable_symbols {
|
||||
// Reachable variants can be dead, because we warn about
|
||||
// variants never constructed, not variants never used.
|
||||
if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
|
||||
continue;
|
||||
}
|
||||
worklist.push(*id);
|
||||
}
|
||||
|
||||
|
@ -155,3 +155,27 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
|
||||
span: DUMMY_SP,
|
||||
})
|
||||
}
|
||||
|
||||
/// Return variants that are necessary to exist for the pattern to match.
|
||||
pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
|
||||
let mut variants = vec![];
|
||||
walk_pat(pat, |p| {
|
||||
match p.node {
|
||||
ast::PatEnum(_, _) |
|
||||
ast::PatIdent(_, _, None) |
|
||||
ast::PatStruct(..) => {
|
||||
match dm.borrow().get(&p.id) {
|
||||
Some(&PathResolution {base_def: DefVariant(_, id, _), ..}) => {
|
||||
variants.push(id.node);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
true
|
||||
});
|
||||
variants.sort();
|
||||
variants.dedup();
|
||||
variants
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ use super::ModuleTranslation;
|
||||
use back::link::{mangle_exported_name};
|
||||
use back::{link, abi};
|
||||
use lint;
|
||||
use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
|
||||
use llvm::{AttrHelper, BasicBlockRef, Linkage, ValueRef, Vector, get_param};
|
||||
use llvm;
|
||||
use metadata::{csearch, encoder, loader};
|
||||
use middle::astencode;
|
||||
@ -456,6 +456,9 @@ pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: Val
|
||||
llvm::FunctionIndex as c_uint,
|
||||
llvm::ColdAttribute as uint64_t)
|
||||
},
|
||||
"allocator" => {
|
||||
llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
|
||||
}
|
||||
_ => used = false,
|
||||
}
|
||||
if used {
|
||||
@ -903,8 +906,10 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
ccx.sess().bug("unexpected intrinsic in trans_external_path")
|
||||
}
|
||||
_ => {
|
||||
foreign::register_foreign_item_fn(ccx, fn_ty.abi, t,
|
||||
&name[..])
|
||||
let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, &name[..]);
|
||||
let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
|
||||
set_llvm_fn_attrs(ccx, &attrs, llfn);
|
||||
llfn
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2841,7 +2846,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
|
||||
let abi = ccx.tcx().map.get_foreign_abi(id);
|
||||
let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
|
||||
let name = foreign::link_name(&*ni);
|
||||
foreign::register_foreign_item_fn(ccx, abi, ty, &name)
|
||||
let llfn = foreign::register_foreign_item_fn(ccx, abi, ty, &name);
|
||||
set_llvm_fn_attrs(ccx, &ni.attrs, llfn);
|
||||
llfn
|
||||
}
|
||||
ast::ForeignItemStatic(..) => {
|
||||
foreign::register_static(ccx, &*ni)
|
||||
|
@ -470,8 +470,8 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
|
||||
"foreign fn's sty isn't a bare_fn_ty?")
|
||||
}
|
||||
|
||||
register_foreign_item_fn(ccx, abi, ty,
|
||||
&lname);
|
||||
let llfn = register_foreign_item_fn(ccx, abi, ty, &lname);
|
||||
base::set_llvm_fn_attrs(ccx, &foreign_item.attrs, llfn);
|
||||
// Unlike for other items, we shouldn't call
|
||||
// `base::update_linkage` here. Foreign items have
|
||||
// special linkage requirements, which are handled
|
||||
|
@ -259,26 +259,43 @@ fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
|
||||
impls.into_iter().filter_map(|a| a).collect()
|
||||
}
|
||||
|
||||
fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
|
||||
fn build_impl(cx: &DocContext,
|
||||
tcx: &ty::ctxt,
|
||||
did: ast::DefId) -> Option<clean::Item> {
|
||||
if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) {
|
||||
return None
|
||||
}
|
||||
|
||||
let attrs = load_attrs(cx, tcx, did);
|
||||
let associated_trait = csearch::get_impl_trait(tcx, did);
|
||||
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline it.
|
||||
match associated_trait {
|
||||
Some(ref t) => {
|
||||
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
||||
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
|
||||
return None
|
||||
}
|
||||
if let Some(ref t) = associated_trait {
|
||||
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline
|
||||
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
||||
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
|
||||
return None
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
let attrs = load_attrs(cx, tcx, did);
|
||||
let ty = ty::lookup_item_type(tcx, did);
|
||||
// If this is a defaulted impl, then bail out early here
|
||||
if csearch::is_default_impl(&tcx.sess.cstore, did) {
|
||||
return Some(clean::Item {
|
||||
inner: clean::DefaultImplItem(clean::DefaultImpl {
|
||||
// FIXME: this should be decoded
|
||||
unsafety: ast::Unsafety::Normal,
|
||||
trait_: match associated_trait.as_ref().unwrap().clean(cx) {
|
||||
clean::TraitBound(polyt, _) => polyt.trait_,
|
||||
clean::RegionBound(..) => unreachable!(),
|
||||
},
|
||||
}),
|
||||
source: clean::Span::empty(),
|
||||
name: None,
|
||||
attrs: attrs,
|
||||
visibility: Some(ast::Inherited),
|
||||
stability: stability::lookup(tcx, did).clean(cx),
|
||||
def_id: did,
|
||||
});
|
||||
}
|
||||
|
||||
let predicates = ty::lookup_predicates(tcx, did);
|
||||
let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
|
||||
.iter()
|
||||
@ -330,8 +347,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
|
||||
}
|
||||
}).collect();
|
||||
let polarity = csearch::get_impl_polarity(tcx, did);
|
||||
let ty = ty::lookup_item_type(tcx, did);
|
||||
return Some(clean::Item {
|
||||
inner: clean::ImplItem(clean::Impl {
|
||||
unsafety: ast::Unsafety::Normal, // FIXME: this should be decoded
|
||||
derived: clean::detect_derived(&attrs),
|
||||
trait_: associated_trait.clean(cx).map(|bound| {
|
||||
match bound {
|
||||
|
@ -337,6 +337,7 @@ pub enum ItemEnum {
|
||||
MacroItem(Macro),
|
||||
PrimitiveItem(PrimitiveType),
|
||||
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
|
||||
DefaultImplItem(DefaultImpl),
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
@ -367,6 +368,7 @@ impl Clean<Item> for doctree::Module {
|
||||
items.extend(self.traits.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.impls.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.macros.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
|
||||
|
||||
// determine if we should display the inner contents or
|
||||
// the outer `mod` item for the source code.
|
||||
@ -2079,6 +2081,7 @@ impl Clean<ImplPolarity> for ast::ImplPolarity {
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Impl {
|
||||
pub unsafety: ast::Unsafety,
|
||||
pub generics: Generics,
|
||||
pub trait_: Option<Type>,
|
||||
pub for_: Type,
|
||||
@ -2101,6 +2104,7 @@ impl Clean<Item> for doctree::Impl {
|
||||
visibility: self.vis.clean(cx),
|
||||
stability: self.stab.clean(cx),
|
||||
inner: ImplItem(Impl {
|
||||
unsafety: self.unsafety,
|
||||
generics: self.generics.clean(cx),
|
||||
trait_: self.trait_.clean(cx),
|
||||
for_: self.for_.clean(cx),
|
||||
@ -2112,6 +2116,29 @@ impl Clean<Item> for doctree::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct DefaultImpl {
|
||||
pub unsafety: ast::Unsafety,
|
||||
pub trait_: Type,
|
||||
}
|
||||
|
||||
impl Clean<Item> for doctree::DefaultImpl {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
name: None,
|
||||
attrs: self.attrs.clean(cx),
|
||||
source: self.whence.clean(cx),
|
||||
def_id: ast_util::local_def(self.id),
|
||||
visibility: Some(ast::Public),
|
||||
stability: None,
|
||||
inner: DefaultImplItem(DefaultImpl {
|
||||
unsafety: self.unsafety,
|
||||
trait_: self.trait_.clean(cx),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for doctree::ExternCrate {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
|
@ -202,6 +202,8 @@ pub struct DefaultImpl {
|
||||
pub unsafety: ast::Unsafety,
|
||||
pub trait_: ast::TraitRef,
|
||||
pub id: ast::NodeId,
|
||||
pub attrs: Vec<ast::Attribute>,
|
||||
pub whence: Span,
|
||||
}
|
||||
|
||||
pub struct Macro {
|
||||
|
@ -64,6 +64,7 @@ impl ItemType {
|
||||
clean::MacroItem(..) => ItemType::Macro,
|
||||
clean::PrimitiveItem(..) => ItemType::Primitive,
|
||||
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
|
||||
clean::DefaultImplItem(..) => ItemType::Impl,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
clean::ImplItem(..) => {}
|
||||
clean::DefaultImplItem(..) | clean::ImplItem(..) => {}
|
||||
|
||||
// tymethods/macros have no control over privacy
|
||||
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
|
||||
|
@ -362,7 +362,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
let i = DefaultImpl {
|
||||
unsafety: unsafety,
|
||||
trait_: trait_ref.clone(),
|
||||
id: item.id
|
||||
id: item.id,
|
||||
attrs: item.attrs.clone(),
|
||||
whence: item.span,
|
||||
};
|
||||
om.def_traits.push(i);
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
|
||||
("box_syntax", "1.0.0", Active),
|
||||
("on_unimplemented", "1.0.0", Active),
|
||||
("simd_ffi", "1.0.0", Active),
|
||||
("allocator", "1.0.0", Active),
|
||||
|
||||
("if_let", "1.0.0", Accepted),
|
||||
("while_let", "1.0.0", Accepted),
|
||||
@ -230,6 +231,8 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
|
||||
("rustc_on_unimplemented", Gated("on_unimplemented",
|
||||
"the `#[rustc_on_unimplemented]` attribute \
|
||||
is an experimental feature")),
|
||||
("allocator", Gated("allocator",
|
||||
"the `#[allocator]` attribute is an experimental feature")),
|
||||
("rustc_variance", Gated("rustc_attrs",
|
||||
"the `#[rustc_variance]` attribute \
|
||||
is an experimental feature")),
|
||||
|
@ -754,7 +754,6 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) ->
|
||||
mod test {
|
||||
use super::*;
|
||||
use std::rc::Rc;
|
||||
use serialize::json;
|
||||
use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION};
|
||||
use owned_slice::OwnedSlice;
|
||||
use ast;
|
||||
|
@ -121,6 +121,7 @@ impl fmt::Display for TestName {
|
||||
#[derive(Clone, Copy)]
|
||||
enum NamePadding {
|
||||
PadNone,
|
||||
#[allow(dead_code)]
|
||||
PadOnLeft,
|
||||
PadOnRight,
|
||||
}
|
||||
|
42
src/test/compile-fail/lint-dead-code-variant.rs
Normal file
42
src/test/compile-fail/lint-dead-code-variant.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
||||
#[derive(Copy)]
|
||||
enum Enum {
|
||||
Variant1, //~ ERROR: variant is never used
|
||||
Variant2,
|
||||
Variant3,
|
||||
}
|
||||
|
||||
fn copy(e: Enum) -> Enum {
|
||||
use Enum::*;
|
||||
match e {
|
||||
Variant1 => Variant1,
|
||||
Variant2 => Variant2,
|
||||
Variant3 => Variant3,
|
||||
}
|
||||
}
|
||||
|
||||
fn max(e: Enum) -> Enum {
|
||||
use Enum::*;
|
||||
match e {
|
||||
Variant1 => Variant3,
|
||||
Variant2 => Variant3,
|
||||
Variant3 => Variant3,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let e = Enum::Variant2;
|
||||
copy(e);
|
||||
max(e);
|
||||
}
|
60
src/test/debuginfo/gdb-pretty-std.rs
Normal file
60
src/test/debuginfo/gdb-pretty-std.rs
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-windows failing on win32 bot
|
||||
// ignore-freebsd: gdb package too new
|
||||
// ignore-tidy-linelength
|
||||
// ignore-lldb
|
||||
// ignore-android: FIXME(#10381)
|
||||
// compile-flags:-g
|
||||
// min-gdb-version 7.7
|
||||
|
||||
// gdb-command: run
|
||||
|
||||
// gdb-command: print slice
|
||||
// gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3}
|
||||
|
||||
// gdb-command: print vec
|
||||
// gdb-check:$2 = Vec<u64>(len: 4, cap: [...]) = {4, 5, 6, 7}
|
||||
|
||||
// gdb-command: print str_slice
|
||||
// gdb-check:$3 = "IAMA string slice!"
|
||||
|
||||
// gdb-command: print string
|
||||
// gdb-check:$4 = "IAMA string!"
|
||||
|
||||
// gdb-command: print some
|
||||
// gdb-check:$5 = Some = {8}
|
||||
|
||||
// gdb-command: print none
|
||||
// gdb-check:$6 = None
|
||||
|
||||
fn main() {
|
||||
|
||||
// &[]
|
||||
let slice: &[i32] = &[0, 1, 2, 3];
|
||||
|
||||
// Vec
|
||||
let vec = vec![4u64, 5, 6, 7];
|
||||
|
||||
// &str
|
||||
let str_slice = "IAMA string slice!";
|
||||
|
||||
// String
|
||||
let string = "IAMA string!".to_string();
|
||||
|
||||
// Option
|
||||
let some = Some(8i16);
|
||||
let none: Option<i64> = None;
|
||||
|
||||
zzz(); // #break
|
||||
}
|
||||
|
||||
fn zzz() { () }
|
5
src/test/run-make/rustdoc-default-impl/Makefile
Normal file
5
src/test/run-make/rustdoc-default-impl/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all: foo.rs bar.rs
|
||||
$(RUSTC) foo.rs --crate-type lib
|
||||
$(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc bar.rs -L $(TMPDIR)
|
17
src/test/run-make/rustdoc-default-impl/bar.rs
Normal file
17
src/test/run-make/rustdoc-default-impl/bar.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate foo;
|
||||
|
||||
pub use foo::bar;
|
||||
|
||||
pub fn wut<T: bar::Bar>() {
|
||||
}
|
||||
|
33
src/test/run-make/rustdoc-default-impl/foo.rs
Normal file
33
src/test/run-make/rustdoc-default-impl/foo.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub mod bar {
|
||||
use std::marker;
|
||||
|
||||
pub trait Bar: marker::MarkerTrait + 'static {}
|
||||
|
||||
impl Bar for .. {}
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
pub fn test<T: Bar>(&self) {}
|
||||
}
|
||||
|
||||
pub struct TypeId;
|
||||
|
||||
impl TypeId {
|
||||
pub fn of<T: Bar + ?Sized>() -> TypeId {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user