Auto merge of #56155 - GuillaumeGomez:rollup, r=GuillaumeGomez

Rollup of 11 pull requests

Successful merges:

 - #55367 (lint if a private item has doctests)
 - #55485 (Return &T / &mut T in ManuallyDrop Deref(Mut) impl)
 - #55784 (Clarifying documentation for collections::hash_map::Entry::or_insert)
 - #55961 (Fix VecDeque pretty-printer)
 - #55980 (Suggest on closure args count mismatching with pipe span)
 - #56002 (fix #55972: Erroneous self arguments on bare functions emit subpar compilation error)
 - #56063 (Update any.rs documentation using keyword dyn)
 - #56067 (Add SGX target to rustc)
 - #56078 (Fix error message for `-C panic=xxx`.)
 - #56106 (Remove some incorrect doc comments)
 - #56126 (core/benches/num: Add `from_str/from_str_radix()` benchmarks)

Failed merges:

r? @ghost
This commit is contained in:
bors 2018-11-22 10:04:41 +00:00
commit 93fa2d76bd
33 changed files with 507 additions and 97 deletions

View file

@ -293,15 +293,23 @@ class RustStdVecDequePrinter(object):
def to_string(self):
(tail, head, data_ptr, cap) = \
rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
if head >= tail:
size = head - tail
else:
size = cap + head - tail
return (self.__val.type.get_unqualified_type_name() +
("(len: %i, cap: %i)" % (head - tail, cap)))
("(len: %i, cap: %i)" % (size, cap)))
def children(self):
(tail, head, data_ptr, cap) = \
rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
gdb_ptr = data_ptr.get_wrapped_value()
for index in xrange(tail, head):
yield (str(index), (gdb_ptr + index).dereference())
if head >= tail:
size = head - tail
else:
size = cap + head - tail
for index in xrange(0, size):
yield (str(index), (gdb_ptr + ((tail + index) % cap)).dereference())
class RustStdBTreeSetPrinter(object):

View file

@ -39,7 +39,7 @@
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//! let value_any = value as &Any;
//! let value_any = value as &dyn Any;
//!
//! // try to convert our value to a String. If successful, we want to
//! // output the String's length as well as its value. If not, it's a
@ -95,7 +95,7 @@ pub trait Any: 'static {
///
/// use std::any::{Any, TypeId};
///
/// fn is_string(s: &Any) -> bool {
/// fn is_string(s: &dyn Any) -> bool {
/// TypeId::of::<String>() == s.get_type_id()
/// }
///
@ -151,7 +151,7 @@ impl dyn Any {
/// ```
/// use std::any::Any;
///
/// fn is_string(s: &Any) {
/// fn is_string(s: &dyn Any) {
/// if s.is::<String>() {
/// println!("It's a string!");
/// } else {
@ -185,7 +185,7 @@ pub fn is<T: Any>(&self) -> bool {
/// ```
/// use std::any::Any;
///
/// fn print_if_string(s: &Any) {
/// fn print_if_string(s: &dyn Any) {
/// if let Some(string) = s.downcast_ref::<String>() {
/// println!("It's a string({}): '{}'", string.len(), string);
/// } else {
@ -218,7 +218,7 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
/// ```
/// use std::any::Any;
///
/// fn modify_if_u32(s: &mut Any) {
/// fn modify_if_u32(s: &mut dyn Any) {
/// if let Some(num) = s.downcast_mut::<u32>() {
/// *num = 42;
/// }
@ -256,7 +256,7 @@ impl dyn Any+Send {
/// ```
/// use std::any::Any;
///
/// fn is_string(s: &(Any + Send)) {
/// fn is_string(s: &(dyn Any + Send)) {
/// if s.is::<String>() {
/// println!("It's a string!");
/// } else {
@ -282,7 +282,7 @@ pub fn is<T: Any>(&self) -> bool {
/// ```
/// use std::any::Any;
///
/// fn print_if_string(s: &(Any + Send)) {
/// fn print_if_string(s: &(dyn Any + Send)) {
/// if let Some(string) = s.downcast_ref::<String>() {
/// println!("It's a string({}): '{}'", string.len(), string);
/// } else {
@ -308,7 +308,7 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
/// ```
/// use std::any::Any;
///
/// fn modify_if_u32(s: &mut (Any + Send)) {
/// fn modify_if_u32(s: &mut (dyn Any + Send)) {
/// if let Some(num) = s.downcast_mut::<u32>() {
/// *num = 42;
/// }
@ -340,7 +340,7 @@ impl dyn Any+Send+Sync {
/// ```
/// use std::any::Any;
///
/// fn is_string(s: &(Any + Send + Sync)) {
/// fn is_string(s: &(dyn Any + Send + Sync)) {
/// if s.is::<String>() {
/// println!("It's a string!");
/// } else {
@ -366,7 +366,7 @@ pub fn is<T: Any>(&self) -> bool {
/// ```
/// use std::any::Any;
///
/// fn print_if_string(s: &(Any + Send + Sync)) {
/// fn print_if_string(s: &(dyn Any + Send + Sync)) {
/// if let Some(string) = s.downcast_ref::<String>() {
/// println!("It's a string({}): '{}'", string.len(), string);
/// } else {
@ -392,7 +392,7 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
/// ```
/// use std::any::Any;
///
/// fn modify_if_u32(s: &mut (Any + Send + Sync)) {
/// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) {
/// if let Some(num) = s.downcast_mut::<u32>() {
/// *num = 42;
/// }

View file

@ -10,3 +10,108 @@
mod flt2dec;
mod dec2flt;
use test::Bencher;
use std::str::FromStr;
const ASCII_NUMBERS: [&str; 19] = [
"0",
"1",
"2",
"43",
"765",
"76567",
"987245987",
"-4aa32",
"1786235",
"8723095",
"f##5s",
"83638730",
"-2345",
"562aa43",
"-1",
"-0",
"abc",
"xyz",
"c0ffee",
];
macro_rules! from_str_bench {
($mac:ident, $t:ty) => (
#[bench]
fn $mac(b: &mut Bencher) {
b.iter(|| {
ASCII_NUMBERS
.iter()
.cycle()
.take(5_000)
.filter_map(|s| <($t)>::from_str(s).ok())
.max()
})
}
)
}
macro_rules! from_str_radix_bench {
($mac:ident, $t:ty, $radix:expr) => (
#[bench]
fn $mac(b: &mut Bencher) {
b.iter(|| {
ASCII_NUMBERS
.iter()
.cycle()
.take(5_000)
.filter_map(|s| <($t)>::from_str_radix(s, $radix).ok())
.max()
})
}
)
}
from_str_bench!(bench_u8_from_str, u8);
from_str_radix_bench!(bench_u8_from_str_radix_2, u8, 2);
from_str_radix_bench!(bench_u8_from_str_radix_10, u8, 10);
from_str_radix_bench!(bench_u8_from_str_radix_16, u8, 16);
from_str_radix_bench!(bench_u8_from_str_radix_36, u8, 36);
from_str_bench!(bench_u16_from_str, u16);
from_str_radix_bench!(bench_u16_from_str_radix_2, u16, 2);
from_str_radix_bench!(bench_u16_from_str_radix_10, u16, 10);
from_str_radix_bench!(bench_u16_from_str_radix_16, u16, 16);
from_str_radix_bench!(bench_u16_from_str_radix_36, u16, 36);
from_str_bench!(bench_u32_from_str, u32);
from_str_radix_bench!(bench_u32_from_str_radix_2, u32, 2);
from_str_radix_bench!(bench_u32_from_str_radix_10, u32, 10);
from_str_radix_bench!(bench_u32_from_str_radix_16, u32, 16);
from_str_radix_bench!(bench_u32_from_str_radix_36, u32, 36);
from_str_bench!(bench_u64_from_str, u64);
from_str_radix_bench!(bench_u64_from_str_radix_2, u64, 2);
from_str_radix_bench!(bench_u64_from_str_radix_10, u64, 10);
from_str_radix_bench!(bench_u64_from_str_radix_16, u64, 16);
from_str_radix_bench!(bench_u64_from_str_radix_36, u64, 36);
from_str_bench!(bench_i8_from_str, i8);
from_str_radix_bench!(bench_i8_from_str_radix_2, i8, 2);
from_str_radix_bench!(bench_i8_from_str_radix_10, i8, 10);
from_str_radix_bench!(bench_i8_from_str_radix_16, i8, 16);
from_str_radix_bench!(bench_i8_from_str_radix_36, i8, 36);
from_str_bench!(bench_i16_from_str, i16);
from_str_radix_bench!(bench_i16_from_str_radix_2, i16, 2);
from_str_radix_bench!(bench_i16_from_str_radix_10, i16, 10);
from_str_radix_bench!(bench_i16_from_str_radix_16, i16, 16);
from_str_radix_bench!(bench_i16_from_str_radix_36, i16, 36);
from_str_bench!(bench_i32_from_str, i32);
from_str_radix_bench!(bench_i32_from_str_radix_2, i32, 2);
from_str_radix_bench!(bench_i32_from_str_radix_10, i32, 10);
from_str_radix_bench!(bench_i32_from_str_radix_16, i32, 16);
from_str_radix_bench!(bench_i32_from_str_radix_36, i32, 36);
from_str_bench!(bench_i64_from_str, i64);
from_str_radix_bench!(bench_i64_from_str_radix_2, i64, 2);
from_str_radix_bench!(bench_i64_from_str_radix_10, i64, 10);
from_str_radix_bench!(bench_i64_from_str_radix_16, i64, 16);
from_str_radix_bench!(bench_i64_from_str_radix_36, i64, 36);

View file

@ -1016,7 +1016,7 @@ pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
impl<T: ?Sized> Deref for ManuallyDrop<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
fn deref(&self) -> &T {
&self.value
}
}
@ -1024,7 +1024,7 @@ fn deref(&self) -> &Self::Target {
#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
fn deref_mut(&mut self) -> &mut T {
&mut self.value
}
}

View file

@ -318,6 +318,12 @@
"warn about missing code example in an item's documentation"
}
declare_lint! {
pub PRIVATE_DOC_TESTS,
Allow,
"warn about doc test in private item"
}
declare_lint! {
pub WHERE_CLAUSES_OBJECT_SAFETY,
Warn,
@ -415,6 +421,7 @@ fn get_lints(&self) -> LintArray {
DUPLICATE_MACRO_EXPORTS,
INTRA_DOC_LINK_RESOLUTION_FAILURE,
MISSING_DOC_CODE_EXAMPLES,
PRIVATE_DOC_TESTS,
WHERE_CLAUSES_OBJECT_SAFETY,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE,

View file

@ -802,7 +802,7 @@ mod $mod_desc {
pub const parse_opt_uint: Option<&'static str> =
Some("a number");
pub const parse_panic_strategy: Option<&'static str> =
Some("either `panic` or `abort`");
Some("either `unwind` or `abort`");
pub const parse_relro_level: Option<&'static str> =
Some("one of: `full`, `partial`, or `off`");
pub const parse_sanitizer: Option<&'static str> =

View file

@ -1092,13 +1092,27 @@ pub fn report_arg_count_mismatch(
if let Some(found_span) = found_span {
err.span_label(found_span, format!("takes {}", found_str));
// move |_| { ... }
// ^^^^^^^^-- def_span
//
// move |_| { ... }
// ^^^^^-- prefix
let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
// move |_| { ... }
// ^^^-- pipe_span
let pipe_span = if let Some(span) = found_span.trim_start(prefix_span) {
span
} else {
found_span
};
// Suggest to take and ignore the arguments with expected_args_length `_`s if
// found arguments is empty (assume the user just wants to ignore args in this case).
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
if found_args.is_empty() && is_closure {
let underscores = vec!["_"; expected_args.len()].join(", ");
err.span_suggestion_with_applicability(
found_span,
pipe_span,
&format!(
"consider changing the closure to take and ignore the expected argument{}",
if expected_args.len() < 2 {

View file

@ -1050,6 +1050,10 @@ fn cross_lang_lto(&mut self) {
}
fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
if let Some(ref exports) = tcx.sess.target.target.options.override_export_symbols {
return exports.clone()
}
let mut symbols = Vec::new();
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);

View file

@ -8,12 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Walks the crate looking for items/impl-items/trait-items that have
//! either a `rustc_symbol_name` or `rustc_item_path` attribute and
//! generates an error giving, respectively, the symbol name or
//! item-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
use base;
use rustc::hir;
use rustc::hir::def::Def;

View file

@ -8,12 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Walks the crate looking for items/impl-items/trait-items that have
//! either a `rustc_symbol_name` or `rustc_item_path` attribute and
//! generates an error giving, respectively, the symbol name or
//! item-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
use monomorphize::Instance;
use rustc::hir;
use rustc::hir::def_id::DefId;

View file

@ -414,6 +414,8 @@ fn $module() {
("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
("aarch64-unknown-none", aarch64_unknown_none),
("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
}
/// Everything `rustc` knows about how to compile for a specific target.
@ -685,6 +687,10 @@ pub struct TargetOptions {
/// target features. This is `true` by default, and `false` for targets like
/// wasm32 where the whole program either has simd or not.
pub simd_types_indirect: bool,
/// If set, have the linker export exactly these symbols, instead of using
/// the usual logic to figure this out from the crate itself.
pub override_export_symbols: Option<Vec<String>>
}
impl Default for TargetOptions {
@ -765,6 +771,7 @@ fn default() -> TargetOptions {
emit_debug_gdb_scripts: true,
requires_uwtable: false,
simd_types_indirect: true,
override_export_symbols: None,
}
}
}
@ -900,6 +907,14 @@ macro_rules! key {
)
);
} );
($key_name:ident, opt_list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name[..]).map(|o| o.as_array()
.map(|v| base.options.$key_name = Some(v.iter()
.map(|a| a.as_string().unwrap().to_string()).collect())
)
);
} );
($key_name:ident, optional) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(o) = obj.find(&name[..]) {
@ -1046,6 +1061,7 @@ macro_rules! key {
key!(emit_debug_gdb_scripts, bool);
key!(requires_uwtable, bool);
key!(simd_types_indirect, bool);
key!(override_export_symbols, opt_list);
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) {
@ -1255,6 +1271,7 @@ macro_rules! target_option_val {
target_option_val!(emit_debug_gdb_scripts);
target_option_val!(requires_uwtable);
target_option_val!(simd_types_indirect);
target_option_val!(override_export_symbols);
if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()

View file

@ -0,0 +1,72 @@
// Copyright 2018 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.
use std::iter;
use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy};
pub fn target() -> Result<Target, String> {
const PRE_LINK_ARGS: &[&str] = &[
"-Wl,--as-needed",
"-Wl,-z,noexecstack",
"-m64",
"-fuse-ld=gold",
"-nostdlib",
"-shared",
"-Wl,-e,sgx_entry",
"-Wl,-Bstatic",
"-Wl,--gc-sections",
"-Wl,-z,text",
"-Wl,-z,norelro",
"-Wl,--rosegment",
"-Wl,--no-undefined",
"-Wl,--error-unresolved-symbols",
"-Wl,--no-undefined-version",
"-Wl,-Bsymbolic",
"-Wl,--export-dynamic",
];
const EXPORT_SYMBOLS: &[&str] = &[
"sgx_entry",
"HEAP_BASE",
"HEAP_SIZE",
"RELA",
"RELACOUNT",
"ENCLAVE_SIZE",
"CFGDATA_BASE",
"DEBUG",
];
let opts = TargetOptions {
dynamic_linking: false,
executables: true,
linker_is_gnu: true,
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
cpu: "x86-64".into(),
position_independent_executables: true,
pre_link_args: iter::once(
(LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect())
).collect(),
override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
..Default::default()
};
Ok(Target {
llvm_target: "x86_64-unknown-linux-gnu".into(),
target_endian: "little".into(),
target_pointer_width: "64".into(),
target_c_int_width: "32".into(),
target_os: "unknown".into(),
target_env: "sgx".into(),
target_vendor: "fortanix".into(),
data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(),
arch: "x86_64".into(),
linker_flavor: LinkerFlavor::Gcc,
options: opts,
})
}

View file

@ -351,13 +351,15 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
let warnings_lint_name = lint::builtin::WARNINGS.name;
let missing_docs = rustc_lint::builtin::MISSING_DOCS.name;
let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name;
let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name;
// In addition to those specific lints, we also need to whitelist those given through
// command line, otherwise they'll get ignored and we don't want that.
let mut whitelisted_lints = vec![warnings_lint_name.to_owned(),
intra_link_resolution_failure_name.to_owned(),
missing_docs.to_owned(),
missing_doc_example.to_owned()];
missing_doc_example.to_owned(),
private_doc_tests.to_owned()];
whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());

View file

@ -24,9 +24,9 @@
use core::DocContext;
use fold::DocFolder;
use html::markdown::{find_testable_code, markdown_links, ErrorCodes, LangString};
use html::markdown::markdown_links;
use passes::Pass;
use passes::{look_for_tests, Pass};
pub const COLLECT_INTRA_DOC_LINKS: Pass =
Pass::early("collect-intra-doc-links", collect_intra_doc_links,
@ -214,43 +214,6 @@ fn resolve(&self,
}
}
fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx>(
cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
dox: &str,
item: &Item,
) {
if (item.is_mod() && cx.tcx.hir.as_local_node_id(item.def_id).is_none()) ||
cx.as_local_node_id(item.def_id).is_none() {
// If non-local, no need to check anything.
return;
}
struct Tests {
found_tests: usize,
}
impl ::test::Tester for Tests {
fn add_test(&mut self, _: String, _: LangString, _: usize) {
self.found_tests += 1;
}
}
let mut tests = Tests {
found_tests: 0,
};
if find_testable_code(&dox, &mut tests, ErrorCodes::No).is_ok() {
if tests.found_tests == 0 {
let mut diag = cx.tcx.struct_span_lint_node(
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
NodeId::from_u32(0),
span_of_attrs(&item.attrs),
"Missing code example in this documentation");
diag.emit();
}
}
}
impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for LinkCollector<'a, 'tcx, 'rcx, 'cstore> {
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
let item_node_id = if item.is_mod() {
@ -313,7 +276,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
let cx = self.cx;
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
look_for_tests(&cx, &dox, &item);
look_for_tests(&cx, &dox, &item, true);
if !self.is_nightly_build {
return None;
@ -488,7 +451,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
None
}
fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
pub fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
if attrs.doc_strings.is_empty() {
return DUMMY_SP;
}

View file

@ -12,16 +12,22 @@
//! process.
use rustc::hir::def_id::DefId;
use rustc::lint as lint;
use rustc::middle::privacy::AccessLevels;
use rustc::util::nodemap::DefIdSet;
use std::mem;
use std::fmt;
use syntax::ast::NodeId;
use clean::{self, GetDefId, Item};
use core::DocContext;
use core::{DocContext, DocAccessLevels};
use fold;
use fold::StripItem;
use html::markdown::{find_testable_code, ErrorCodes, LangString};
use self::collect_intra_doc_links::span_of_attrs;
mod collapse_docs;
pub use self::collapse_docs::COLLAPSE_DOCS;
@ -43,6 +49,9 @@
mod collect_intra_doc_links;
pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
mod private_items_doc_tests;
pub use self::private_items_doc_tests::CHECK_PRIVATE_ITEMS_DOC_TESTS;
mod collect_trait_impls;
pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
@ -128,6 +137,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
/// The full list of passes.
pub const PASSES: &'static [Pass] = &[
CHECK_PRIVATE_ITEMS_DOC_TESTS,
STRIP_HIDDEN,
UNINDENT_COMMENTS,
COLLAPSE_DOCS,
@ -141,6 +151,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
/// The list of passes run by default.
pub const DEFAULT_PASSES: &'static [&'static str] = &[
"collect-trait-impls",
"check-private-items-doc-tests",
"strip-hidden",
"strip-private",
"collect-intra-doc-links",
@ -152,6 +163,7 @@ pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
/// The list of default passes run with `--document-private-items` is passed to rustdoc.
pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
"collect-trait-impls",
"check-private-items-doc-tests",
"strip-priv-imports",
"collect-intra-doc-links",
"collapse-docs",
@ -348,3 +360,49 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
}
}
}
pub fn look_for_tests<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx>(
cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
dox: &str,
item: &Item,
check_missing_code: bool,
) {
if cx.as_local_node_id(item.def_id).is_none() {
// If non-local, no need to check anything.
return;
}
struct Tests {
found_tests: usize,
}
impl ::test::Tester for Tests {
fn add_test(&mut self, _: String, _: LangString, _: usize) {
self.found_tests += 1;
}
}
let mut tests = Tests {
found_tests: 0,
};
if find_testable_code(&dox, &mut tests, ErrorCodes::No).is_ok() {
if check_missing_code == true && tests.found_tests == 0 {
let mut diag = cx.tcx.struct_span_lint_node(
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
NodeId::from_u32(0),
span_of_attrs(&item.attrs),
"Missing code example in this documentation");
diag.emit();
} else if check_missing_code == false &&
tests.found_tests > 0 &&
!cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
let mut diag = cx.tcx.struct_span_lint_node(
lint::builtin::PRIVATE_DOC_TESTS,
NodeId::from_u32(0),
span_of_attrs(&item.attrs),
"Documentation test in private item");
diag.emit();
}
}
}

View file

@ -0,0 +1,49 @@
// Copyright 2018 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.
use clean::*;
use core::DocContext;
use fold::DocFolder;
use passes::{look_for_tests, Pass};
pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass =
Pass::early("check-private-items-doc-tests", check_private_items_doc_tests,
"check private items doc tests");
struct PrivateItemDocTestLinter<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
}
impl<'a, 'tcx, 'rcx, 'cstore> PrivateItemDocTestLinter<'a, 'tcx, 'rcx, 'cstore> {
fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
PrivateItemDocTestLinter {
cx,
}
}
}
pub fn check_private_items_doc_tests(krate: Crate, cx: &DocContext) -> Crate {
let mut coll = PrivateItemDocTestLinter::new(cx);
coll.fold_crate(krate)
}
impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for PrivateItemDocTestLinter<'a, 'tcx, 'rcx, 'cstore> {
fn fold_item(&mut self, item: Item) -> Option<Item> {
let cx = self.cx;
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
look_for_tests(&cx, &dox, &item, false);
self.fold_item_recur(item)
}
}

View file

@ -2026,12 +2026,12 @@ impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
/// use std::collections::HashMap;
///
/// let mut map: HashMap<&str, u32> = HashMap::new();
/// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12);
///
/// assert_eq!(map["poneyland"], 12);
/// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3);
/// assert_eq!(map["poneyland"], 3);
///
/// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 12).1 += 10;
/// assert_eq!(map["poneyland"], 22);
/// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
/// assert_eq!(map["poneyland"], 6);
/// ```
#[unstable(feature = "hash_raw_entry", issue = "54043")]
pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V)
@ -2648,12 +2648,12 @@ impl<'a, K, V> Entry<'a, K, V> {
/// use std::collections::HashMap;
///
/// let mut map: HashMap<&str, u32> = HashMap::new();
/// map.entry("poneyland").or_insert(12);
///
/// assert_eq!(map["poneyland"], 12);
/// map.entry("poneyland").or_insert(3);
/// assert_eq!(map["poneyland"], 3);
///
/// *map.entry("poneyland").or_insert(12) += 10;
/// assert_eq!(map["poneyland"], 22);
/// *map.entry("poneyland").or_insert(10) *= 2;
/// assert_eq!(map["poneyland"], 6);
/// ```
pub fn or_insert(self, default: V) -> &'a mut V {
match self {

View file

@ -1824,6 +1824,14 @@ fn eat_incorrect_doc_comment(&mut self, applied_to: &str) {
fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
maybe_whole!(self, NtArg, |x| x);
if let Ok(Some(_)) = self.parse_self_arg() {
let mut err = self.struct_span_err(self.prev_span,
"unexpected `self` argument in function");
err.span_label(self.prev_span,
"`self` is only valid as the first argument of an associated function");
return Err(err);
}
let (pat, ty) = if require_name || self.is_named_argument() {
debug!("parse_arg_general parse_pat (require_name:{})",
require_name);
@ -5385,11 +5393,12 @@ fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
-> PResult<'a, (Vec<Arg> , bool)> {
self.expect(&token::OpenDelim(token::Paren))?;
let sp = self.span;
let mut variadic = false;
let args: Vec<Option<Arg>> =
self.parse_unspanned_seq(
&token::OpenDelim(token::Paren),
self.parse_seq_to_before_end(
&token::CloseDelim(token::Paren),
SeqSep::trailing_allowed(token::Comma),
|p| {
@ -5436,6 +5445,8 @@ fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
}
)?;
self.eat(&token::CloseDelim(token::Paren));
let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
if variadic && args.is_empty() {

View file

@ -28,6 +28,9 @@
// gdb-command: print vec_deque
// gdb-check:$3 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
// gdb-command: print vec_deque2
// gdb-check:$4 = VecDeque<i32>(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8}
#![allow(unused_variables)]
use std::collections::BTreeSet;
use std::collections::BTreeMap;
@ -54,6 +57,14 @@ fn main() {
vec_deque.push_back(3);
vec_deque.push_back(7);
// VecDeque where an element was popped.
let mut vec_deque2 = VecDeque::new();
for i in 1..8 {
vec_deque2.push_back(i)
}
vec_deque2.pop_front();
vec_deque2.push_back(8);
zzz(); // #break
}

View file

@ -0,0 +1,20 @@
// Copyright 2018 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(private_doc_tests)]
mod foo {
/// private doc test
///
/// ```
/// assert!(false);
/// ```
fn bar() {}
}

View file

@ -0,0 +1,16 @@
error: Documentation test in private item
--> $DIR/private-item-doc-test.rs:14:5
|
LL | / /// private doc test
LL | | ///
LL | | /// ```
LL | | /// assert!(false);
LL | | /// ```
| |___________^
|
note: lint level defined here
--> $DIR/private-item-doc-test.rs:11:9
|
LL | #![deny(private_doc_tests)]
| ^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,5 @@
fn a(&self) { }
//~^ ERROR unexpected `self` argument in function
//~| NOTE `self` is only valid as the first argument of an associated function
fn main() { }

View file

@ -0,0 +1,8 @@
error: unexpected `self` argument in function
--> $DIR/bare-fn-start.rs:1:7
|
LL | fn a(&self) { }
| ^^^^ `self` is only valid as the first argument of an associated function
error: aborting due to previous error

View file

@ -0,0 +1,5 @@
fn b(foo: u32, &mut self) { }
//~^ ERROR unexpected `self` argument in function
//~| NOTE `self` is only valid as the first argument of an associated function
fn main() { }

View file

@ -0,0 +1,8 @@
error: unexpected `self` argument in function
--> $DIR/bare-fn.rs:1:21
|
LL | fn b(foo: u32, &mut self) { }
| ^^^^ `self` is only valid as the first argument of an associated function
error: aborting due to previous error

View file

@ -0,0 +1,11 @@
struct Foo {}
impl Foo {
fn c(foo: u32, self) {}
//~^ ERROR unexpected `self` argument in function
//~| NOTE `self` is only valid as the first argument of an associated function
fn good(&mut self, foo: u32) {}
}
fn main() { }

View file

@ -0,0 +1,8 @@
error: unexpected `self` argument in function
--> $DIR/trait-fn.rs:4:20
|
LL | fn c(foo: u32, self) {}
| ^^^^ `self` is only valid as the first argument of an associated function
error: aborting due to previous error

View file

@ -22,6 +22,8 @@ fn main() {
//~^ ERROR closure is expected to take
f(|| panic!());
//~^ ERROR closure is expected to take
f( move || panic!());
//~^ ERROR closure is expected to take
let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
//~^ ERROR closure is expected to take

View file

@ -60,8 +60,26 @@ help: consider changing the closure to take and ignore the expected argument
LL | f(|_| panic!());
| ^^^
error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
--> $DIR/closure-arg-count.rs:25:5
|
LL | f( move || panic!());
| ^ ---------- takes 0 arguments
| |
| expected closure that takes 1 argument
|
note: required by `f`
--> $DIR/closure-arg-count.rs:13:1
|
LL | fn f<F: Fn<usize>>(_: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the closure to take and ignore the expected argument
|
LL | f( move |_| panic!());
| ^^^
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:26:53
--> $DIR/closure-arg-count.rs:28:53
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
| ^^^ ------ takes 2 distinct arguments
@ -73,7 +91,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
| ^^^^^^^^
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:28:53
--> $DIR/closure-arg-count.rs:30:53
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
| ^^^ ------------- takes 2 distinct arguments
@ -85,7 +103,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
| ^^^^^^^^
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
--> $DIR/closure-arg-count.rs:30:53
--> $DIR/closure-arg-count.rs:32:53
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
| ^^^ --------- takes 3 distinct arguments
@ -93,7 +111,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
| expected closure that takes a single 2-tuple as argument
error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments
--> $DIR/closure-arg-count.rs:32:53
--> $DIR/closure-arg-count.rs:34:53
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
| ^^^ expected function that takes a single 2-tuple as argument
@ -102,7 +120,7 @@ LL | fn foo() {}
| -------- takes 0 arguments
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
--> $DIR/closure-arg-count.rs:35:53
--> $DIR/closure-arg-count.rs:37:53
|
LL | let bar = |i, x, y| i;
| --------- takes 3 distinct arguments
@ -110,7 +128,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
| ^^^ expected closure that takes a single 2-tuple as argument
error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:37:53
--> $DIR/closure-arg-count.rs:39:53
|
LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
| ^^^ expected function that takes a single 2-tuple as argument
@ -119,13 +137,13 @@ LL | fn qux(x: usize, y: usize) {}
| -------------------------- takes 2 distinct arguments
error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
--> $DIR/closure-arg-count.rs:40:41
--> $DIR/closure-arg-count.rs:42:41
|
LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
| ^^^ expected function that takes 1 argument
error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
--> $DIR/closure-arg-count.rs:43:5
--> $DIR/closure-arg-count.rs:45:5
|
LL | call(Foo);
| ^^^^ expected function that takes 0 arguments
@ -134,11 +152,11 @@ LL | struct Foo(u8);
| --------------- takes 1 argument
|
note: required by `call`
--> $DIR/closure-arg-count.rs:50:1
--> $DIR/closure-arg-count.rs:52:1
|
LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 13 previous errors
error: aborting due to 14 previous errors
For more information about this error, try `rustc --explain E0593`.

View file

@ -9,6 +9,6 @@
// except according to those terms.
// compile-flags:-C panic=foo
// error-pattern:either `panic` or `abort` was expected
// error-pattern:either `unwind` or `abort` was expected
fn main() {}

View file

@ -1,2 +1,2 @@
error: incorrect value `foo` for codegen option `panic` - either `panic` or `abort` was expected
error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected

View file

@ -9,6 +9,6 @@
// except according to those terms.
// compile-flags:-C panic
// error-pattern:requires either `panic` or `abort`
// error-pattern:requires either `unwind` or `abort`
fn main() {}

View file

@ -1,2 +1,2 @@
error: codegen option `panic` requires either `panic` or `abort` (C panic=<value>)
error: codegen option `panic` requires either `unwind` or `abort` (C panic=<value>)