Skip to content

Commit

Permalink
Auto merge of #49620 - kennytm:rollup, r=kennytm
Browse files Browse the repository at this point in the history
Rollup of 14 pull requests

Successful merges:

 - #49179 (Handle future deprecation annotations )
 - #49512 (Add support for variant and types fields for intra links)
 - #49516 (Add missing anchor for union type fields)
 - #49532 (Add test for rustdoc ignore test)
 - #49533 (Add #[must_use] to a few standard library methods)
 - #49570 (avoid IdxSets containing garbage above the universe length)
 - #49594 (Add some performance guidance to std::fs and std::io docs)
 - #49599 (Fix typo)
 - #49603 (Fix url for intra link provided method)
 - #49609 (run-pass/attr-stmt-expr: expand test cases)
 - #49612 (Fix "since" version for getpid feature.)
 - #49618 (Fix build error when compiling libcore for 16bit targets)
 - #49619 (tweak core::fmt docs)
 - #49623 (update mdbook)

Failed merges:
  • Loading branch information
bors committed Apr 3, 2018
2 parents 637ac17 + fa5d2e2 commit f6419b1
Show file tree
Hide file tree
Showing 25 changed files with 541 additions and 30 deletions.
211 changes: 211 additions & 0 deletions src/Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/liballoc/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub trait ToOwned {
/// let vv: Vec<i32> = v.to_owned();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "cloning is often expensive and is not expected to have side effects"]
fn to_owned(&self) -> Self::Owned;

/// Uses borrowed data to replace owned data, usually by cloning.
Expand Down
1 change: 1 addition & 0 deletions src/libcore/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub trait Clone : Sized {
/// assert_eq!("Hello", hello.clone());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "cloning is often expensive and is not expected to have side effects"]
fn clone(&self) -> Self;

/// Performs copy-assignment from `source`.
Expand Down
11 changes: 5 additions & 6 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,19 +401,18 @@ impl<'a> Arguments<'a> {
/// safely be done, so no constructors are given and the fields are private
/// to prevent modification.
///
/// The [`format_args!`] macro will safely create an instance of this structure
/// and pass it to a function or closure, passed as the first argument. The
/// macro validates the format string at compile-time so usage of the [`write`]
/// and [`format`] functions can be safely performed.
/// The [`format_args!`] macro will safely create an instance of this structure.
/// The macro validates the format string at compile-time so usage of the
/// [`write`] and [`format`] functions can be safely performed.
///
/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
/// and `Display` contexts as seen below. The example also shows that `Debug`
/// and `Display` format to the same thing: the interpolated format string
/// in `format_args!`.
///
/// ```rust
/// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
/// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2));
/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
/// assert_eq!("1 foo 2", display);
/// assert_eq!(display, debug);
/// ```
Expand Down
1 change: 1 addition & 0 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,7 @@ pub trait Iterator {
/// [`Result`]: ../../std/result/enum.Result.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized {
FromIterator::from_iter(self)
}
Expand Down
1 change: 1 addition & 0 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ macro_rules! try_from_unbounded {
}

// unsigned to signed (only positive bound)
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
macro_rules! try_from_upper_bounded {
($($target:ty),*) => {$(
impl PrivateTryFromUsize for $target {
Expand Down
38 changes: 36 additions & 2 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,30 @@ pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor());
}

/// Check whether an item marked with `deprecated(since="X")` is currently
/// deprecated (i.e. whether X is not greater than the current rustc version).
pub fn deprecation_in_effect(since: &str) -> bool {
fn parse_version(ver: &str) -> Vec<u32> {
// We ignore non-integer components of the version (e.g. "nightly").
ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect()
}

if let Some(rustc) = option_env!("CFG_RELEASE") {
let since: Vec<u32> = parse_version(since);
let rustc: Vec<u32> = parse_version(rustc);
// We simply treat invalid `since` attributes as relating to a previous
// Rust version, thus always displaying the warning.
if since.len() != 3 {
return true;
}
since <= rustc
} else {
// By default, a deprecation warning applies to
// the current version of the compiler.
true
}
}

struct Checker<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
Expand Down Expand Up @@ -559,9 +583,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// Deprecated attributes apply in-crate and cross-crate.
if let Some(id) = id {
if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) {
// If the deprecation is scheduled for a future Rust
// version, then we should display no warning message.
let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since {
let since = sym.as_str();
!deprecation_in_effect(&since)
} else {
false
};

let parent_def_id = self.hir.local_def_id(self.hir.get_parent(id));
let skip = self.lookup_deprecation_entry(parent_def_id)
.map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
let skip = deprecated_in_future_version ||
self.lookup_deprecation_entry(parent_def_id)
.map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
if !skip {
lint_deprecated(def_id, id, depr_entry.attr.note);
}
Expand Down
74 changes: 73 additions & 1 deletion src/librustc_data_structures/indexed_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ impl<T: Idx> IdxSetBuf<T> {

/// Creates set holding every element whose index falls in range 0..universe_size.
pub fn new_filled(universe_size: usize) -> Self {
Self::new(!0, universe_size)
let mut result = Self::new(!0, universe_size);
result.trim_to(universe_size);
result
}

/// Creates set holding no elements.
Expand Down Expand Up @@ -168,6 +170,36 @@ impl<T: Idx> IdxSet<T> {
}
}

/// Sets all elements up to `universe_size`
pub fn set_up_to(&mut self, universe_size: usize) {
for b in &mut self.bits {
*b = !0;
}
self.trim_to(universe_size);
}

/// Clear all elements above `universe_size`.
fn trim_to(&mut self, universe_size: usize) {
let word_bits = mem::size_of::<Word>() * 8;

// `trim_block` is the first block where some bits have
// to be cleared.
let trim_block = universe_size / word_bits;

// all the blocks above it have to be completely cleared.
if trim_block < self.bits.len() {
for b in &mut self.bits[trim_block+1..] {
*b = 0;
}

// at that block, the `universe_size % word_bits` lsbs
// should remain.
let remaining_bits = universe_size % word_bits;
let mask = (1<<remaining_bits)-1;
self.bits[trim_block] &= mask;
}
}

/// Removes `elem` from the set `self`; returns true iff this changed `self`.
pub fn remove(&mut self, elem: &T) -> bool {
self.bits.clear_bit(elem.index())
Expand Down Expand Up @@ -252,3 +284,43 @@ impl<'a, T: Idx> Iterator for Iter<'a, T> {
}
}
}

#[test]
fn test_trim_to() {
use std::cmp;

for i in 0..256 {
let mut idx_buf: IdxSetBuf<usize> = IdxSetBuf::new_filled(128);
idx_buf.trim_to(i);

let elems: Vec<usize> = idx_buf.iter().collect();
let expected: Vec<usize> = (0..cmp::min(i, 128)).collect();
assert_eq!(elems, expected);
}
}

#[test]
fn test_set_up_to() {
for i in 0..128 {
for mut idx_buf in
vec![IdxSetBuf::new_empty(128), IdxSetBuf::new_filled(128)]
.into_iter()
{
idx_buf.set_up_to(i);

let elems: Vec<usize> = idx_buf.iter().collect();
let expected: Vec<usize> = (0..i).collect();
assert_eq!(elems, expected);
}
}
}

#[test]
fn test_new_filled() {
for i in 0..128 {
let mut idx_buf = IdxSetBuf::new_filled(i);
let elems: Vec<usize> = idx_buf.iter().collect();
let expected: Vec<usize> = (0..i).collect();
assert_eq!(elems, expected);
}
}
2 changes: 1 addition & 1 deletion src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ newtype_index!(ScopeId);
/// macro (and methods below) makes working with `BlockAnd` much more
/// convenient.

#[must_use] // if you don't use one of these results, you're leaving a dangling edge
#[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
struct BlockAnd<T>(BasicBlock, T);

trait BlockAndExtension {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/dataflow/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
// sets on_entry bits for Arg places
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
// set all bits to 1 (uninit) before gathering counterevidence
for e in entry_set.words_mut() { *e = !0; }
entry_set.set_up_to(self.bits_per_block());

drop_flag_effects_for_function_entry(
self.tcx, self.mir, self.mdpe,
Expand Down Expand Up @@ -443,7 +443,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc

// sets on_entry bits for Arg places
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
for e in entry_set.words_mut() { *e = 0; }
entry_set.clear();

drop_flag_effects_for_function_entry(
self.tcx, self.mir, self.mdpe,
Expand Down
33 changes: 29 additions & 4 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,8 +1074,7 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
let ty = cx.resolver.borrow_mut()
.with_scope(*id,
|resolver| {
resolver.resolve_str_path_error(DUMMY_SP,
&path, false)
resolver.resolve_str_path_error(DUMMY_SP, &path, false)
})?;
match ty.def {
Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => {
Expand All @@ -1090,7 +1089,27 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
};
Ok((ty.def, Some(format!("{}.{}", out, item_name))))
} else {
Err(())
let is_enum = match ty.def {
Def::Enum(_) => true,
_ => false,
};
let elem = if is_enum {
cx.tcx.adt_def(did).all_fields().find(|item| item.name == item_name)
} else {
cx.tcx.adt_def(did)
.non_enum_variant()
.fields
.iter()
.find(|item| item.name == item_name)
};
if let Some(item) = elem {
Ok((ty.def,
Some(format!("{}.{}",
if is_enum { "variant" } else { "structfield" },
item.name))))
} else {
Err(())
}
}
}
Def::Trait(did) => {
Expand All @@ -1101,7 +1120,13 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
let kind = match item.kind {
ty::AssociatedKind::Const if is_val => "associatedconstant",
ty::AssociatedKind::Type if !is_val => "associatedtype",
ty::AssociatedKind::Method if is_val => "tymethod",
ty::AssociatedKind::Method if is_val => {
if item.defaultness.has_value() {
"method"
} else {
"tymethod"
}
}
_ => return Err(())
};

Expand Down
31 changes: 25 additions & 6 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2113,9 +2113,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
} else {
String::new()
};
let text = format!("Deprecated{}{}",
since,
MarkdownHtml(&deprecated_reason));
let text = if stability::deprecation_in_effect(&stab.deprecated_since) {
format!("Deprecated{}{}",
since,
MarkdownHtml(&deprecated_reason))
} else {
format!("Deprecating in {}{}",
Escape(&stab.deprecated_since),
MarkdownHtml(&deprecated_reason))
};
stability.push(format!("<div class='stab deprecated'>{}</div>", text))
};

Expand Down Expand Up @@ -2165,7 +2171,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
String::new()
};

let text = format!("Deprecated{}{}", since, MarkdownHtml(&note));
let text = if stability::deprecation_in_effect(&depr.since) {
format!("Deprecated{}{}",
since,
MarkdownHtml(&note))
} else {
format!("Deprecating in {}{}",
Escape(&depr.since),
MarkdownHtml(&note))
};
stability.push(format!("<div class='stab deprecated'>{}</div>", text))
}

Expand Down Expand Up @@ -2801,10 +2815,15 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
write!(w, "<h2 id='fields' class='fields small-section-header'>
Fields<a href='#fields' class='anchor'></a></h2>")?;
for (field, ty) in fields {
write!(w, "<span id='{shortty}.{name}' class=\"{shortty}\"><code>{name}: {ty}</code>
let name = field.name.as_ref().expect("union field name");
let id = format!("{}.{}", ItemType::StructField, name);
write!(w, "<span id=\"{id}\" class=\"{shortty} small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\"></a>\
<span class='invisible'><code>{name}: {ty}</code></span>\
</span>",
id = id,
name = name,
shortty = ItemType::StructField,
name = field.name.as_ref().unwrap(),
ty = ty)?;
if let Some(stability_class) = field.stability_class() {
write!(w, "<span class='stab {stab}'></span>",
Expand Down
8 changes: 6 additions & 2 deletions src/libstd/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ fn initial_buffer_size(file: &File) -> usize {
/// Read the entire contents of a file into a bytes vector.
///
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
/// with fewer imports and without an intermediate variable.
/// with fewer imports and without an intermediate variable. It pre-allocates a
/// buffer based on the file size when available, so it is generally faster than
/// reading into a vector created with `Vec::new()`.
///
/// [`File::open`]: struct.File.html#method.open
/// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end
Expand Down Expand Up @@ -270,7 +272,9 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
/// Read the entire contents of a file into a string.
///
/// This is a convenience function for using [`File::open`] and [`read_to_string`]
/// with fewer imports and without an intermediate variable.
/// with fewer imports and without an intermediate variable. It pre-allocates a
/// buffer based on the file size when available, so it is generally faster than
/// reading into a string created with `String::new()`.
///
/// [`File::open`]: struct.File.html#method.open
/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
Expand Down
14 changes: 13 additions & 1 deletion src/libstd/io/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ use memchr;
/// results in a system call. A `BufReader` performs large, infrequent reads on
/// the underlying [`Read`] and maintains an in-memory buffer of the results.
///
/// `BufReader` can improve the speed of programs that make *small* and
/// *repeated* read calls to the same file or network socket. It does not
/// help when reading very large amounts at once, or reading just one or a few
/// times. It also provides no advantage when reading from a source that is
/// already in memory, like a `Vec<u8>`.
///
/// [`Read`]: ../../std/io/trait.Read.html
/// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
Expand Down Expand Up @@ -180,7 +186,7 @@ impl<R: Read> BufReader<R> {
///
/// # Examples
///
/// ```no_ru
/// ```no_run
/// # #![feature(bufreader_buffer)]
/// use std::io::{BufReader, BufRead};
/// use std::fs::File;
Expand Down Expand Up @@ -359,6 +365,12 @@ impl<R: Seek> Seek for BufReader<R> {
/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying
/// writer in large, infrequent batches.
///
/// `BufWriter` can improve the speed of programs that make *small* and
/// *repeated* write calls to the same file or network socket. It does not
/// help when writing very large amounts at once, or writing just one or a few
/// times. It also provides no advantage when writing to a destination that is
/// in memory, like a `Vec<u8>`.
///
/// When the `BufWriter` is dropped, the contents of its buffer will be written
/// out. However, any errors that happen in the process of flushing the buffer
/// when the writer is dropped will be ignored. Code that wishes to handle such
Expand Down
Loading

0 comments on commit f6419b1

Please sign in to comment.