mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-05 11:33:04 +00:00
Auto merge of #44098 - frewsxcv:rollup, r=frewsxcv
Rollup of 7 pull requests - Successful merges: #43776, #43966, #43979, #44072, #44086, #44090, #44091 - Failed merges:
This commit is contained in:
commit
32f6056079
@ -29,7 +29,7 @@ showing the expected renderings.
|
||||
|
||||
In order to avoid one-off dependencies for this task, this script uses
|
||||
a reasonably working HTML parser and the existing XPath implementation
|
||||
from Python 2's standard library. Hopefully we won't render
|
||||
from Python's standard library. Hopefully we won't render
|
||||
non-well-formed HTML.
|
||||
|
||||
# Commands
|
||||
@ -110,11 +110,17 @@ import os.path
|
||||
import re
|
||||
import shlex
|
||||
from collections import namedtuple
|
||||
from HTMLParser import HTMLParser
|
||||
try:
|
||||
from html.parser import HTMLParser
|
||||
except ImportError:
|
||||
from HTMLParser import HTMLParser
|
||||
from xml.etree import cElementTree as ET
|
||||
|
||||
# ⇤/⇥ are not in HTML 4 but are in HTML 5
|
||||
from htmlentitydefs import entitydefs
|
||||
try:
|
||||
from html.entities import entitydefs
|
||||
except ImportError:
|
||||
from htmlentitydefs import entitydefs
|
||||
entitydefs['larrb'] = u'\u21e4'
|
||||
entitydefs['rarrb'] = u'\u21e5'
|
||||
entitydefs['nbsp'] = ' '
|
||||
@ -123,6 +129,11 @@ entitydefs['nbsp'] = ' '
|
||||
VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
|
||||
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
|
||||
|
||||
# Python 2 -> 3 compatibility
|
||||
try:
|
||||
unichr
|
||||
except NameError:
|
||||
unichr = chr
|
||||
|
||||
class CustomHTMLParser(HTMLParser):
|
||||
"""simplified HTML parser.
|
||||
@ -184,12 +195,8 @@ def concat_multi_lines(f):
|
||||
|
||||
# strip the common prefix from the current line if needed
|
||||
if lastline is not None:
|
||||
maxprefix = 0
|
||||
for i in xrange(min(len(line), len(lastline))):
|
||||
if line[i] != lastline[i]:
|
||||
break
|
||||
maxprefix += 1
|
||||
line = line[maxprefix:].lstrip()
|
||||
common_prefix = os.path.commonprefix([line, lastline])
|
||||
line = line[len(common_prefix):].lstrip()
|
||||
|
||||
firstlineno = firstlineno or lineno
|
||||
if line.endswith('\\'):
|
||||
@ -213,7 +220,7 @@ LINE_PATTERN = re.compile(r'''
|
||||
|
||||
|
||||
def get_commands(template):
|
||||
with open(template, 'rUb') as f:
|
||||
with open(template, 'rU') as f:
|
||||
for lineno, line in concat_multi_lines(f):
|
||||
m = LINE_PATTERN.search(line)
|
||||
if not m:
|
||||
@ -372,7 +379,7 @@ def check_command(c, cache):
|
||||
cache.get_file(c.args[0])
|
||||
ret = True
|
||||
except FailedCheck as err:
|
||||
cerr = err.message
|
||||
cerr = str(err)
|
||||
ret = False
|
||||
elif len(c.args) == 2: # @has/matches <path> <pat> = string test
|
||||
cerr = "`PATTERN` did not match"
|
||||
@ -413,9 +420,9 @@ def check_command(c, cache):
|
||||
|
||||
except FailedCheck as err:
|
||||
message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd)
|
||||
print_err(c.lineno, c.context, err.message, message)
|
||||
print_err(c.lineno, c.context, str(err), message)
|
||||
except InvalidCheck as err:
|
||||
print_err(c.lineno, c.context, err.message)
|
||||
print_err(c.lineno, c.context, str(err))
|
||||
|
||||
def check(target, commands):
|
||||
cache = CachedFiles(target)
|
||||
|
@ -110,7 +110,7 @@ impl Layout {
|
||||
|
||||
/// Creates a layout, bypassing all checks.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe as it does not verify that `align` is
|
||||
/// a power-of-two that is also less than or equal to 2^31, nor
|
||||
@ -485,7 +485,7 @@ pub unsafe trait Alloc {
|
||||
/// behavior, e.g. to ensure initialization to particular sets of
|
||||
/// bit patterns.)
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure that `layout` has non-zero size.
|
||||
@ -513,7 +513,7 @@ pub unsafe trait Alloc {
|
||||
|
||||
/// Deallocate the memory referenced by `ptr`.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
@ -617,7 +617,7 @@ pub unsafe trait Alloc {
|
||||
/// behavior is well-defined (though underspecified) when this
|
||||
/// constraint is violated; further discussion below.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
@ -688,7 +688,7 @@ pub unsafe trait Alloc {
|
||||
/// Behaves like `alloc`, but also ensures that the contents
|
||||
/// are set to zero before being returned.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe for the same reasons that `alloc` is.
|
||||
///
|
||||
@ -714,7 +714,7 @@ pub unsafe trait Alloc {
|
||||
/// the returned block. For some `layout` inputs, like arrays, this
|
||||
/// may include extra storage usable for additional data.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe for the same reasons that `alloc` is.
|
||||
///
|
||||
@ -736,7 +736,7 @@ pub unsafe trait Alloc {
|
||||
/// the returned block. For some `layout` inputs, like arrays, this
|
||||
/// may include extra storage usable for additional data.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe for the same reasons that `realloc` is.
|
||||
///
|
||||
@ -770,7 +770,7 @@ pub unsafe trait Alloc {
|
||||
/// memory block referenced by `ptr` has not been transferred, and
|
||||
/// the contents of the memory block are unaltered.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
@ -827,7 +827,7 @@ pub unsafe trait Alloc {
|
||||
/// the memory block has not been transferred, and the contents of
|
||||
/// the memory block are unaltered.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
@ -920,7 +920,7 @@ pub unsafe trait Alloc {
|
||||
///
|
||||
/// Captures a common usage pattern for allocators.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure both:
|
||||
@ -993,7 +993,7 @@ pub unsafe trait Alloc {
|
||||
/// The returned block is suitable for passing to the
|
||||
/// `alloc`/`realloc` methods of this allocator.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
@ -1037,7 +1037,7 @@ pub unsafe trait Alloc {
|
||||
///
|
||||
/// Captures a common usage pattern for allocators.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure both:
|
||||
|
@ -633,7 +633,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
|
||||
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
|
||||
/// closures become directly usable.)
|
||||
///
|
||||
/// ### Example
|
||||
/// # Examples
|
||||
///
|
||||
/// Here is a snippet of code which creates a hashmap full of boxed
|
||||
/// once closures and then removes them one by one, calling each
|
||||
|
@ -171,7 +171,7 @@ mod hack {
|
||||
impl<T> [T] {
|
||||
/// Returns the number of elements in the slice.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
@ -185,7 +185,7 @@ impl<T> [T] {
|
||||
|
||||
/// Returns `true` if the slice has a length of 0.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
@ -523,7 +523,7 @@ impl<T> [T] {
|
||||
|
||||
/// Reverses the order of elements in the slice, in place.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = [1, 2, 3];
|
||||
@ -580,7 +580,7 @@ impl<T> [T] {
|
||||
///
|
||||
/// Panics if `size` is 0.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let slice = ['r', 'u', 's', 't'];
|
||||
@ -613,7 +613,7 @@ impl<T> [T] {
|
||||
///
|
||||
/// Panics if `size` is 0.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let slice = ['l', 'o', 'r', 'e', 'm'];
|
||||
@ -1040,7 +1040,7 @@ impl<T> [T] {
|
||||
/// `Err` is returned, containing the index where a matching
|
||||
/// element could be inserted while maintaining sorted order.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// Looks up a series of four elements. The first is found, with a
|
||||
/// uniquely determined position; the second and third are not
|
||||
@ -1074,7 +1074,7 @@ impl<T> [T] {
|
||||
/// `Err` is returned, containing the index where a matching
|
||||
/// element could be inserted while maintaining sorted order.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// Looks up a series of four elements. The first is found, with a
|
||||
/// uniquely determined position; the second and third are not
|
||||
@ -1419,7 +1419,7 @@ impl<T> [T] {
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut dst = [0, 0, 0];
|
||||
@ -1445,7 +1445,7 @@ impl<T> [T] {
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut dst = [0, 0, 0];
|
||||
|
@ -1714,7 +1714,7 @@ impl str {
|
||||
///
|
||||
/// [`Err`]: str/trait.FromStr.html#associatedtype.Err
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage
|
||||
///
|
||||
|
@ -82,7 +82,7 @@ use boxed::Box;
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// You can create a `String` from a literal string with `String::from`:
|
||||
/// You can create a `String` from a literal string with [`String::from`]:
|
||||
///
|
||||
/// ```
|
||||
/// let hello = String::from("Hello, world!");
|
||||
@ -98,6 +98,7 @@ use boxed::Box;
|
||||
/// hello.push_str("orld!");
|
||||
/// ```
|
||||
///
|
||||
/// [`String::from`]: #method.from
|
||||
/// [`char`]: ../../std/primitive.char.html
|
||||
/// [`push`]: #method.push
|
||||
/// [`push_str`]: #method.push_str
|
||||
|
@ -998,7 +998,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
|
||||
/// A method would interfere with methods of the same name on the contents
|
||||
/// of a `RefCell` used through `Deref`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::{RefCell, Ref};
|
||||
@ -1040,7 +1040,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
|
||||
/// `RefMut::map(...)`. A method would interfere with methods of the same
|
||||
/// name on the contents of a `RefCell` used through `Deref`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::{RefCell, RefMut};
|
||||
|
@ -58,7 +58,7 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
|
||||
/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
@ -153,7 +153,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
||||
/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
@ -290,7 +290,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
|
||||
/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
@ -361,7 +361,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
|
||||
/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
@ -432,7 +432,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
|
||||
/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
|
||||
/// method.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
|
@ -901,7 +901,7 @@ impl<T> ManuallyDrop<T> {
|
||||
|
||||
/// Manually drops the contained value.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function runs the destructor of the contained value and thus the wrapped value
|
||||
/// now represents uninitialized data. It is up to the user of this method to ensure the
|
||||
|
@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
|
||||
target_family: Some("unix".to_string()),
|
||||
relro_level: RelroLevel::Full,
|
||||
linker_is_gnu: true,
|
||||
no_integrated_as: true,
|
||||
.. Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -160,21 +160,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
||||
};
|
||||
|
||||
let mut fn_warned = false;
|
||||
let maybe_def = match expr.node {
|
||||
hir::ExprCall(ref callee, _) => {
|
||||
match callee.node {
|
||||
hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)),
|
||||
_ => None
|
||||
}
|
||||
},
|
||||
hir::ExprMethodCall(..) => {
|
||||
cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
|
||||
},
|
||||
_ => { None }
|
||||
};
|
||||
if let Some(def) = maybe_def {
|
||||
let def_id = def.def_id();
|
||||
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
|
||||
if cx.tcx.sess.features.borrow().fn_must_use {
|
||||
let maybe_def = match expr.node {
|
||||
hir::ExprCall(ref callee, _) => {
|
||||
match callee.node {
|
||||
hir::ExprPath(ref qpath) => {
|
||||
Some(cx.tables.qpath_def(qpath, callee.hir_id))
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
},
|
||||
hir::ExprMethodCall(..) => {
|
||||
cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
|
||||
},
|
||||
_ => None
|
||||
};
|
||||
if let Some(def) = maybe_def {
|
||||
let def_id = def.def_id();
|
||||
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
|
||||
}
|
||||
}
|
||||
|
||||
if !(ty_warned || fn_warned) {
|
||||
|
@ -323,6 +323,10 @@ impl Item {
|
||||
pub fn is_union(&self) -> bool {
|
||||
self.type_() == ItemType::Union
|
||||
}
|
||||
pub fn is_import(&self) -> bool {
|
||||
self.type_() == ItemType::Import
|
||||
}
|
||||
|
||||
pub fn is_stripped(&self) -> bool {
|
||||
match self.inner { StrippedItem(..) => true, _ => false }
|
||||
}
|
||||
|
@ -1764,6 +1764,37 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
}
|
||||
|
||||
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
|
||||
// This call is to remove reexport duplicates in cases such as:
|
||||
//
|
||||
// ```
|
||||
// pub mod foo {
|
||||
// pub mod bar {
|
||||
// pub trait Double { fn foo(); }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pub use foo::bar::*;
|
||||
// pub use foo::*;
|
||||
// ```
|
||||
//
|
||||
// `Double` will appear twice in the generated docs.
|
||||
//
|
||||
// FIXME: This code is quite ugly and could be improved. Small issue: DefId
|
||||
// can be identical even if the elements are different (mostly in imports).
|
||||
// So in case this is an import, we keep everything by adding a "unique id"
|
||||
// (which is the position in the vector).
|
||||
indices.dedup_by_key(|i| (items[*i].def_id,
|
||||
if items[*i].name.as_ref().is_some() {
|
||||
Some(full_path(cx, &items[*i]).clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
items[*i].type_(),
|
||||
if items[*i].is_import() {
|
||||
*i
|
||||
} else {
|
||||
0
|
||||
}));
|
||||
|
||||
debug!("{:?}", indices);
|
||||
let mut curty = None;
|
||||
@ -2925,7 +2956,13 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
|
||||
fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
|
||||
render_mode: RenderMode, outer_version: Option<&str>) -> fmt::Result {
|
||||
if render_mode == RenderMode::Normal {
|
||||
write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
|
||||
let id = derive_id(match i.inner_impl().trait_ {
|
||||
Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))),
|
||||
None => "impl".to_string(),
|
||||
});
|
||||
write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>",
|
||||
id, i.inner_impl())?;
|
||||
write!(w, "<a href='#{}' class='anchor'></a>", id)?;
|
||||
write!(w, "</span><span class='out-of-band'>")?;
|
||||
let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
|
||||
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
|
||||
|
@ -445,6 +445,10 @@ a {
|
||||
.small-section-header:hover > .anchor {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
.in-band:hover > .anchor {
|
||||
display: initial;
|
||||
}
|
||||
.anchor {
|
||||
display: none;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ h1.fqn {
|
||||
h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
|
||||
border-bottom-color: #DDDDDD;
|
||||
}
|
||||
|
||||
.in-band {
|
||||
background-color: white;
|
||||
}
|
||||
@ -83,6 +84,11 @@ pre {
|
||||
}
|
||||
|
||||
:target { background: #FDFFD3; }
|
||||
|
||||
:target > .in-band {
|
||||
background: #FDFFD3;
|
||||
}
|
||||
|
||||
.content .highlighted {
|
||||
color: #000 !important;
|
||||
background-color: #ccc;
|
||||
|
@ -522,7 +522,7 @@ pub trait Read {
|
||||
/// `Read`er - the method only takes `&self` so that it can be used through
|
||||
/// trait objects.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This method is unsafe because a `Read`er could otherwise return a
|
||||
/// non-zeroing `Initializer` from another `Read` type without an `unsafe`
|
||||
@ -903,7 +903,7 @@ impl Initializer {
|
||||
|
||||
/// Returns a new `Initializer` which will not zero out buffers.
|
||||
///
|
||||
/// # Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This may only be called by `Read`ers which guarantee that they will not
|
||||
/// read from buffers passed to `Read` methods, and that the return value of
|
||||
|
@ -20,7 +20,7 @@
|
||||
/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
|
||||
/// (See benchmarks.)
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// This shows how to find the first position of a byte in a byte string.
|
||||
///
|
||||
@ -40,7 +40,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
|
||||
/// Returns the index corresponding to the last occurrence of `needle` in
|
||||
/// `haystack`, or `None` if one is not found.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// This shows how to find the last position of a byte in a byte string.
|
||||
///
|
||||
|
@ -13,7 +13,7 @@
|
||||
//! For now, this module is limited to extracting file descriptors,
|
||||
//! but its functionality will grow over time.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::fs::File;
|
||||
|
@ -13,7 +13,7 @@
|
||||
//! For now, this module is limited to extracting file descriptors,
|
||||
//! but its functionality will grow over time.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::fs::File;
|
||||
|
@ -807,7 +807,7 @@ pub fn park_timeout_ms(ms: u32) {
|
||||
/// Platforms which do not support nanosecond precision for sleeping will have
|
||||
/// `dur` rounded up to the nearest granularity of time they can sleep for.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// Waiting for the complete expiration of the timeout:
|
||||
///
|
||||
|
@ -112,8 +112,8 @@ macro_rules! declare_features {
|
||||
// was set. This is most important for knowing when a particular feature became
|
||||
// stable (active).
|
||||
//
|
||||
// NB: The featureck.py script parses this information directly out of the source
|
||||
// so take care when modifying it.
|
||||
// NB: tools/tidy/src/features.rs parses this information directly out of the
|
||||
// source, so take care when modifying it.
|
||||
|
||||
declare_features! (
|
||||
(active, asm, "1.0.0", Some(29722)),
|
||||
@ -372,6 +372,9 @@ declare_features! (
|
||||
|
||||
// #[doc(cfg(...))]
|
||||
(active, doc_cfg, "1.21.0", Some(43781)),
|
||||
|
||||
// allow `#[must_use]` on functions (RFC 1940)
|
||||
(active, fn_must_use, "1.21.0", Some(43302)),
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
@ -915,20 +918,27 @@ struct Context<'a> {
|
||||
}
|
||||
|
||||
macro_rules! gate_feature_fn {
|
||||
($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
||||
let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
|
||||
($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
|
||||
let (cx, has_feature, span,
|
||||
name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
|
||||
let has_feature: bool = has_feature(&$cx.features);
|
||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
||||
if !has_feature && !span.allows_unstable() {
|
||||
emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
|
||||
leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
|
||||
.emit();
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! gate_feature {
|
||||
($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
|
||||
gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
|
||||
}
|
||||
gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
|
||||
stringify!($feature), $explain, GateStrength::Hard)
|
||||
};
|
||||
($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
|
||||
gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
|
||||
stringify!($feature), $explain, $level)
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
@ -938,7 +948,7 @@ impl<'a> Context<'a> {
|
||||
for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
|
||||
if name == n {
|
||||
if let Gated(_, name, desc, ref has_feature) = *gateage {
|
||||
gate_feature_fn!(self, has_feature, attr.span, name, desc);
|
||||
gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
|
||||
}
|
||||
debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
|
||||
return;
|
||||
@ -1008,13 +1018,26 @@ pub enum GateIssue {
|
||||
Library(Option<u32>)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum GateStrength {
|
||||
/// A hard error. (Most feature gates should use this.)
|
||||
Hard,
|
||||
/// Only a warning. (Use this only as backwards-compatibility demands.)
|
||||
Soft,
|
||||
}
|
||||
|
||||
pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
|
||||
explain: &str) {
|
||||
feature_err(sess, feature, span, issue, explain).emit();
|
||||
}
|
||||
|
||||
pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
|
||||
explain: &str) -> DiagnosticBuilder<'a> {
|
||||
explain: &str) -> DiagnosticBuilder<'a> {
|
||||
leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
|
||||
}
|
||||
|
||||
fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
|
||||
explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
|
||||
let diag = &sess.span_diagnostic;
|
||||
|
||||
let issue = match issue {
|
||||
@ -1022,10 +1045,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
|
||||
GateIssue::Library(lib) => lib,
|
||||
};
|
||||
|
||||
let mut err = if let Some(n) = issue {
|
||||
diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
|
||||
let explanation = if let Some(n) = issue {
|
||||
format!("{} (see issue #{})", explain, n)
|
||||
} else {
|
||||
diag.struct_span_err(span, explain)
|
||||
explain.to_owned()
|
||||
};
|
||||
|
||||
let mut err = match level {
|
||||
GateStrength::Hard => diag.struct_span_err(span, &explanation),
|
||||
GateStrength::Soft => diag.struct_span_warn(span, &explanation),
|
||||
};
|
||||
|
||||
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
||||
@ -1035,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
|
||||
feature));
|
||||
}
|
||||
|
||||
// If we're on stable and only emitting a "soft" warning, add a note to
|
||||
// clarify that the feature isn't "on" (rather than being on but
|
||||
// warning-worthy).
|
||||
if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
|
||||
err.help("a nightly build of the compiler is required to enable this feature");
|
||||
}
|
||||
|
||||
err
|
||||
|
||||
}
|
||||
|
||||
const EXPLAIN_BOX_SYNTAX: &'static str =
|
||||
@ -1092,6 +1128,12 @@ macro_rules! gate_feature_post {
|
||||
if !span.allows_unstable() {
|
||||
gate_feature!(cx.context, $feature, span, $explain)
|
||||
}
|
||||
}};
|
||||
($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
|
||||
let (cx, span) = ($cx, $span);
|
||||
if !span.allows_unstable() {
|
||||
gate_feature!(cx.context, $feature, span, $explain, $level)
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
@ -1234,6 +1276,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
function may change over time, for now \
|
||||
a top-level `fn main()` is required");
|
||||
}
|
||||
if attr::contains_name(&i.attrs[..], "must_use") {
|
||||
gate_feature_post!(&self, fn_must_use, i.span,
|
||||
"`#[must_use]` on functions is experimental",
|
||||
GateStrength::Soft);
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::Struct(..) => {
|
||||
@ -1271,7 +1318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
and possibly buggy");
|
||||
}
|
||||
|
||||
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
|
||||
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
|
||||
if polarity == ast::ImplPolarity::Negative {
|
||||
gate_feature_post!(&self, optin_builtin_traits,
|
||||
i.span,
|
||||
@ -1284,6 +1331,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
i.span,
|
||||
"specialization is unstable");
|
||||
}
|
||||
|
||||
for impl_item in impl_items {
|
||||
if let ast::ImplItemKind::Method(..) = impl_item.node {
|
||||
if attr::contains_name(&impl_item.attrs[..], "must_use") {
|
||||
gate_feature_post!(&self, fn_must_use, impl_item.span,
|
||||
"`#[must_use]` on methods is experimental",
|
||||
GateStrength::Soft);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
|
||||
|
31
src/test/compile-fail/feature-gate-fn_must_use.rs
Normal file
31
src/test/compile-fail/feature-gate-fn_must_use.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
struct MyStruct;
|
||||
|
||||
impl MyStruct {
|
||||
#[must_use]
|
||||
fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental
|
||||
|
||||
|
||||
// Feature gates are tidy-required to have a specially named (or
|
||||
// comment-annotated) compile-fail test (which MUST fail), but for
|
||||
// backwards-compatibility reasons, we want `#[must_use]` on functions to be
|
||||
// compilable even if the `fn_must_use` feature is absent, thus necessitating
|
||||
// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this
|
||||
// dilemma until a superior solution can be devised.
|
||||
#[rustc_error]
|
||||
fn main() {} //~ ERROR compilation successful
|
@ -680,6 +680,7 @@ mod must_use {
|
||||
mod inner { #![must_use="1400"] }
|
||||
|
||||
#[must_use = "1400"] fn f() { }
|
||||
//~^ WARN `#[must_use]` on functions is experimental
|
||||
|
||||
#[must_use = "1400"] struct S;
|
||||
|
||||
|
24
src/test/rustdoc/remove-duplicates.rs
Normal file
24
src/test/rustdoc/remove-duplicates.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
mod foo {
|
||||
pub use bar::*;
|
||||
pub mod bar {
|
||||
pub trait Foo {
|
||||
fn foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @count foo/index.html '//*[@class="trait"]' 1
|
||||
pub use foo::bar::*;
|
||||
pub use foo::*;
|
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(fn_must_use)]
|
||||
#![warn(unused_must_use)]
|
||||
|
||||
struct MyStruct {
|
||||
|
@ -1,18 +1,18 @@
|
||||
warning: unused return value of `need_to_use_this_value` which must be used: it's important
|
||||
--> $DIR/fn_must_use.rs:30:5
|
||||
--> $DIR/fn_must_use.rs:31:5
|
||||
|
|
||||
30 | need_to_use_this_value();
|
||||
31 | need_to_use_this_value();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/fn_must_use.rs:11:9
|
||||
--> $DIR/fn_must_use.rs:12:9
|
||||
|
|
||||
11 | #![warn(unused_must_use)]
|
||||
12 | #![warn(unused_must_use)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
|
||||
--> $DIR/fn_must_use.rs:33:5
|
||||
--> $DIR/fn_must_use.rs:34:5
|
||||
|
|
||||
33 | m.need_to_use_this_method_value();
|
||||
34 | m.need_to_use_this_method_value();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user