Auto merge of #83301 - Dylan-DPC:rollup-x1yzvhm, r=Dylan-DPC

Rollup of 11 pull requests

Successful merges:

 - #82500 (Reuse `std::sys::unsupported::pipe` on `hermit`)
 - #82759 (Remove unwrap_none/expect_none from compiler/.)
 - #82846 (rustdoc: allow list syntax for #[doc(alias)] attributes)
 - #82892 (Clarify docs for Read::read's return value)
 - #83179 (Extend `proc_macro_back_compat` lint to `actix-web`)
 - #83197 (Move some test-only code to test files)
 - #83208 (Fix gitattibutes for old git versions)
 - #83215 (Deprecate std::os::haiku::raw, which accidentally wasn't deprecated)
 - #83230 (Remove unnecessary `forward_inner_docs` hack)
 - #83236 (Upgrade memmap to memmap2)
 - #83270 (Fix typo/inaccuracy in the documentation of Iterator::skip_while)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-03-19 15:38:57 +00:00
commit 9f4bc3ead4
45 changed files with 530 additions and 252 deletions

6
.gitattributes vendored
View File

@ -7,11 +7,11 @@
*.fixed linguist-language=Rust
*.mir linguist-language=Rust
src/etc/installer/gfx/* binary
*.woff binary
*.woff2 binary
src/vendor/** -text
Cargo.lock linguist-generated=false
# Older git versions try to fix line endings on images, this prevents it.
# Older git versions try to fix line endings on images and fonts, this prevents it.
*.png binary
*.ico binary
*.woff binary
*.woff2 binary

View File

@ -2164,6 +2164,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "memmap2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e3e85b970d650e2ae6d70592474087051c11c54da7f7b4949725c5735fbcc6"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.5.5"
@ -3782,7 +3791,7 @@ dependencies = [
"itertools 0.9.0",
"jobserver",
"libc",
"memmap",
"memmap2",
"pathdiff",
"rustc_apfloat",
"rustc_ast",
@ -4116,7 +4125,7 @@ name = "rustc_metadata"
version = "0.0.0"
dependencies = [
"libc",
"memmap",
"memmap2",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",

View File

@ -298,22 +298,6 @@ impl<T> TypedArena<T> {
}
}
/// Clears the arena. Deallocates all but the longest chunk which may be reused.
pub fn clear(&mut self) {
unsafe {
// Clear the last chunk, which is partially filled.
let mut chunks_borrow = self.chunks.borrow_mut();
if let Some(mut last_chunk) = chunks_borrow.last_mut() {
self.clear_last_chunk(&mut last_chunk);
let len = chunks_borrow.len();
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..len - 1) {
chunk.destroy(chunk.entries);
}
}
}
}
// Drops the contents of the last chunk. The last chunk is partially empty, unlike all other
// chunks.
fn clear_last_chunk(&self, last_chunk: &mut TypedArenaChunk<T>) {

View File

@ -11,6 +11,24 @@ struct Point {
z: i32,
}
impl<T> TypedArena<T> {
/// Clears the arena. Deallocates all but the longest chunk which may be reused.
fn clear(&mut self) {
unsafe {
// Clear the last chunk, which is partially filled.
let mut chunks_borrow = self.chunks.borrow_mut();
if let Some(mut last_chunk) = chunks_borrow.last_mut() {
self.clear_last_chunk(&mut last_chunk);
let len = chunks_borrow.len();
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..len - 1) {
chunk.destroy(chunk.entries);
}
}
}
}
}
#[test]
pub fn test_unused() {
let arena: TypedArena<Point> = TypedArena::default();

View File

@ -11,7 +11,7 @@ test = false
bitflags = "1.2.1"
cc = "1.0.1"
itertools = "0.9"
memmap = "0.7"
memmap2 = "0.2.1"
tracing = "0.1"
libc = "0.2.50"
jobserver = "0.1.11"

View File

@ -93,7 +93,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
pub enum SerializedModule<M: ModuleBufferMethods> {
Local(M),
FromRlib(Vec<u8>),
FromUncompressedFile(memmap::Mmap),
FromUncompressedFile(memmap2::Mmap),
}
impl<M: ModuleBufferMethods> SerializedModule<M> {

View File

@ -1958,7 +1958,7 @@ pub fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>(
.unwrap_or_else(|e| panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e));
let mmap = unsafe {
memmap::Mmap::map(&file).unwrap_or_else(|e| {
memmap2::Mmap::map(&file).unwrap_or_else(|e| {
panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e)
})
};

View File

@ -1,6 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(assert_matches)]
#![feature(bool_to_option)]
#![feature(option_expect_none)]
#![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(try_blocks)]

View File

@ -15,7 +15,7 @@
mod tests;
#[derive(Clone)]
pub struct TinyList<T: PartialEq> {
pub struct TinyList<T> {
head: Option<Element<T>>,
}
@ -56,20 +56,10 @@ impl<T: PartialEq> TinyList<T> {
}
false
}
#[inline]
pub fn len(&self) -> usize {
let (mut elem, mut count) = (self.head.as_ref(), 0);
while let Some(ref e) = elem {
count += 1;
elem = e.next.as_deref();
}
count
}
}
#[derive(Clone)]
struct Element<T: PartialEq> {
struct Element<T> {
data: T,
next: Option<Box<Element<T>>>,
}

View File

@ -3,6 +3,17 @@ use super::*;
extern crate test;
use test::{black_box, Bencher};
impl<T> TinyList<T> {
fn len(&self) -> usize {
let (mut elem, mut count) = (self.head.as_ref(), 0);
while let Some(ref e) = elem {
count += 1;
elem = e.next.as_deref();
}
count
}
}
#[test]
fn test_contains_and_insert() {
fn do_insert(i: u32) -> bool {

View File

@ -9,7 +9,7 @@ use std::mem;
mod tests;
#[derive(Clone, Debug)]
pub struct TransitiveRelation<T: Eq + Hash> {
pub struct TransitiveRelation<T> {
// List of elements. This is used to map from a T to a usize.
elements: FxIndexSet<T>,
@ -49,7 +49,7 @@ struct Edge {
target: Index,
}
impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
impl<T: Eq + Hash> TransitiveRelation<T> {
pub fn is_empty(&self) -> bool {
self.edges.is_empty()
}
@ -322,12 +322,6 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
.collect()
}
/// A "best" parent in some sense. See `parents` and
/// `postdom_upper_bound` for more details.
pub fn postdom_parent(&self, a: &T) -> Option<&T> {
self.mutual_immediate_postdominator(self.parents(a))
}
fn with_closure<OP, R>(&self, op: OP) -> R
where
OP: FnOnce(&BitMatrix<usize, usize>) -> R,

View File

@ -1,5 +1,13 @@
use super::*;
impl<T: Eq + Hash> TransitiveRelation<T> {
/// A "best" parent in some sense. See `parents` and
/// `postdom_upper_bound` for more details.
fn postdom_parent(&self, a: &T) -> Option<&T> {
self.mutual_immediate_postdominator(self.parents(a))
}
}
#[test]
fn test_one_step() {
let mut relation = TransitiveRelation::default();

View File

@ -30,15 +30,6 @@ struct DiagnosticBuilderInner<'a> {
allow_suggestions: bool,
}
/// This is a helper macro for [`forward!`] that allows automatically adding documentation
/// that uses tokens from [`forward!`]'s input.
macro_rules! forward_inner_docs {
($e:expr => $i:item) => {
#[doc = $e]
$i
};
}
/// In general, the `DiagnosticBuilder` uses deref to allow access to
/// the fields and methods of the embedded `diagnostic` in a
/// transparent way. *However,* many of the methods are intended to
@ -54,11 +45,11 @@ macro_rules! forward {
pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)?) -> &Self
) => {
$(#[$attrs])*
forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") =>
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
pub fn $n(&self, $($name: $ty),*) -> &Self {
self.diagnostic.$n($($name),*);
self
});
}
};
// Forward pattern for &mut self -> &mut Self
@ -67,11 +58,11 @@ macro_rules! forward {
pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)?) -> &mut Self
) => {
$(#[$attrs])*
forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") =>
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
self.0.diagnostic.$n($($name),*);
self
});
}
};
// Forward pattern for &mut self -> &mut Self, with generic parameters.
@ -84,11 +75,11 @@ macro_rules! forward {
) -> &mut Self
) => {
$(#[$attrs])*
forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") =>
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
pub fn $n<$($generic: $bound),*>(&mut self, $($name: $ty),*) -> &mut Self {
self.0.diagnostic.$n($($name),*);
self
});
}
};
}

View File

@ -5,6 +5,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(crate_visibility_modifier)]
#![feature(backtrace)]
#![feature(extended_key_value_attributes)]
#![feature(nll)]
#[macro_use]

View File

@ -53,11 +53,11 @@ impl ToInternal<token::DelimToken> for Delimiter {
}
}
impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_>)>
for TokenTree<Group, Punct, Ident, Literal>
{
fn from_internal(
((tree, spacing), sess, stack): (TreeAndSpacing, &ParseSess, &mut Vec<Self>),
((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec<Self>, &mut Rustc<'_>),
) -> Self {
use rustc_ast::token::*;
@ -146,10 +146,10 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
SingleQuote => op!('\''),
Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()),
Ident(name, is_raw) => tt!(Ident::new(sess, name, is_raw)),
Ident(name, is_raw) => tt!(Ident::new(rustc.sess, name, is_raw)),
Lifetime(name) => {
let ident = symbol::Ident::new(name, span).without_first_quote();
stack.push(tt!(Ident::new(sess, ident.name, false)));
stack.push(tt!(Ident::new(rustc.sess, ident.name, false)));
tt!(Punct::new('\'', true))
}
Literal(lit) => tt!(Literal { lit }),
@ -179,15 +179,15 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
}
Interpolated(nt) => {
if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, sess) {
TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) {
TokenTree::Ident(Ident::new(rustc.sess, name.name, is_raw, name.span))
} else {
let stream = nt_to_tokenstream(&nt, sess, CanSynthesizeMissingTokens::No);
let stream = nt_to_tokenstream(&nt, rustc.sess, CanSynthesizeMissingTokens::No);
TokenTree::Group(Group {
delimiter: Delimiter::None,
stream,
span: DelimSpan::from_single(span),
flatten: crate::base::pretty_printing_compatibility_hack(&nt, sess),
flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess),
})
}
}
@ -449,7 +449,7 @@ impl server::TokenStreamIter for Rustc<'_> {
loop {
let tree = iter.stack.pop().or_else(|| {
let next = iter.cursor.next_with_spacing()?;
Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
Some(TokenTree::from_internal((next, &mut iter.stack, self)))
})?;
// A hack used to pass AST fragments to attribute and derive macros
// as a single nonterminal token instead of a token stream.
@ -719,11 +719,11 @@ impl server::Span for Rustc<'_> {
fn ident_name_compatibility_hack(
nt: &Nonterminal,
orig_span: Span,
sess: &ParseSess,
rustc: &mut Rustc<'_>,
) -> Option<(rustc_span::symbol::Ident, bool)> {
if let NtIdent(ident, is_raw) = nt {
if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
let source_map = sess.source_map();
let source_map = rustc.sess.source_map();
let filename = source_map.span_to_filename(orig_span);
if let FileName::Real(RealFileName::Named(path)) = filename {
let matches_prefix = |prefix, filename| {
@ -745,7 +745,7 @@ fn ident_name_compatibility_hack(
let snippet = source_map.span_to_snippet(orig_span);
if snippet.as_deref() == Ok("$name") {
if time_macros_impl {
sess.buffer_lint_with_diagnostic(
rustc.sess.buffer_lint_with_diagnostic(
&PROC_MACRO_BACK_COMPAT,
orig_span,
ast::CRATE_NODE_ID,
@ -759,13 +759,25 @@ fn ident_name_compatibility_hack(
}
}
if macro_name == sym::tuple_from_req
&& (matches_prefix("actix-web", "extract.rs")
|| matches_prefix("actori-web", "extract.rs"))
{
if macro_name == sym::tuple_from_req && matches_prefix("actix-web", "extract.rs") {
let snippet = source_map.span_to_snippet(orig_span);
if snippet.as_deref() == Ok("$T") {
return Some((*ident, *is_raw));
if let FileName::Real(RealFileName::Named(macro_path)) =
source_map.span_to_filename(rustc.def_site)
{
if macro_path.to_string_lossy().contains("pin-project-internal-0.") {
rustc.sess.buffer_lint_with_diagnostic(
&PROC_MACRO_BACK_COMPAT,
orig_span,
ast::CRATE_NODE_ID,
"using an old version of `actix-web`",
BuiltinLintDiagnostics::ProcMacroBackCompat(
"the version of `actix-web` you are using might stop compiling in future versions of Rust; \
please update to the latest version of the `actix-web` crate to avoid breakage".to_string())
);
return Some((*ident, *is_raw));
}
}
}
}
}

View File

@ -11,7 +11,7 @@ doctest = false
libc = "0.2"
snap = "1"
tracing = "0.1"
memmap = "0.7"
memmap2 = "0.2.1"
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
rustc_middle = { path = "../rustc_middle" }
rustc_attr = { path = "../rustc_attr" }

View File

@ -728,7 +728,7 @@ impl<'a> CrateLocator<'a> {
}
/// A trivial wrapper for `Mmap` that implements `StableDeref`.
struct StableDerefMmap(memmap::Mmap);
struct StableDerefMmap(memmap2::Mmap);
impl Deref for StableDerefMmap {
type Target = [u8];
@ -779,7 +779,7 @@ fn get_metadata_section(
// mmap the file, because only a small fraction of it is read.
let file = std::fs::File::open(filename)
.map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?;
let mmap = unsafe { memmap::Mmap::map(&file) };
let mmap = unsafe { memmap2::Mmap::map(&file) };
let mmap = mmap
.map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?;

View File

@ -45,7 +45,11 @@ impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
item.hash_stable(self, hasher);
style.hash_stable(self, hasher);
span.hash_stable(self, hasher);
tokens.as_ref().expect_none("Tokens should have been removed during lowering!");
assert_matches!(
tokens.as_ref(),
None,
"Tokens should have been removed during lowering!"
);
} else {
unreachable!();
}

View File

@ -24,6 +24,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(assoc_char_funcs)]
#![feature(backtrace)]
#![feature(bool_to_option)]
@ -38,7 +39,6 @@
#![feature(extern_types)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(option_expect_none)]
#![feature(or_patterns)]
#![feature(min_specialization)]
#![feature(trusted_len)]

View File

@ -339,7 +339,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
for dest in bytes {
*dest = src.next().expect("iterator was shorter than it said it would be");
}
src.next().expect_none("iterator was longer than it said it would be");
assert_matches!(src.next(), None, "iterator was longer than it said it would be");
Ok(())
}

View File

@ -854,7 +854,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Some(ptr) => ptr,
None => {
// zero-sized access
src.next().expect_none("iterator said it was empty but returned an element");
assert_matches!(
src.next(),
None,
"iterator said it was empty but returned an element"
);
return Ok(());
}
};
@ -880,7 +884,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Some(ptr) => ptr,
None => {
// zero-sized access
src.next().expect_none("iterator said it was empty but returned an element");
assert_matches!(
src.next(),
None,
"iterator said it was empty but returned an element"
);
return Ok(());
}
};
@ -894,7 +902,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication
allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?;
}
src.next().expect_none("iterator was longer than it said it would be");
assert_matches!(src.next(), None, "iterator was longer than it said it would be");
Ok(())
}

View File

@ -7,6 +7,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(nll)]
#![feature(in_band_lifetimes)]
#![feature(array_windows)]
#![feature(assert_matches)]
#![feature(bindings_after_at)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
@ -18,13 +19,13 @@ Rust MIR: a lowered representation of Rust.
#![feature(exact_size_is_empty)]
#![feature(exhaustive_patterns)]
#![feature(never_type)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(try_blocks)]
#![feature(associated_type_defaults)]
#![feature(stmt_expr_attributes)]
#![feature(trait_alias)]
#![feature(option_expect_none)]
#![feature(option_get_or_insert_default)]
#![feature(or_patterns)]
#![feature(once_cell)]

View File

@ -285,10 +285,8 @@ impl DebugCounters {
),
};
counters
.insert(id, DebugCounter::new(counter_kind.clone(), some_block_label))
.expect_none(
"attempt to add the same counter_kind to DebugCounters more than once",
);
.try_insert(id, DebugCounter::new(counter_kind.clone(), some_block_label))
.expect("attempt to add the same counter_kind to DebugCounters more than once");
}
}
@ -479,9 +477,9 @@ impl GraphvizData {
counter_kind: &CoverageKind,
) {
if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() {
edge_to_counter.insert((from_bcb, to_bb), counter_kind.clone()).expect_none(
"invalid attempt to insert more than one edge counter for the same edge",
);
edge_to_counter
.try_insert((from_bcb, to_bb), counter_kind.clone())
.expect("invalid attempt to insert more than one edge counter for the same edge");
}
}

View File

@ -86,7 +86,7 @@ fn find_duplicates<'a, 'tcx>(body: &'a Body<'tcx>) -> FxHashMap<BasicBlock, Basi
// The basic block was already in the hashmap, which means we have a duplicate
let value = *occupied.get();
debug!("Inserting {:?} -> {:?}", bb, value);
duplicates.insert(bb, value).expect_none("key was already inserted");
duplicates.try_insert(bb, value).expect("key was already inserted");
}
Entry::Vacant(vacant) => {
vacant.insert(bb);

View File

@ -394,33 +394,50 @@ impl CheckAttrVisitor<'tcx> {
.emit();
}
fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool {
let doc_alias = meta.value_str().map(|s| s.to_string()).unwrap_or_else(String::new);
fn check_doc_alias_value(
&self,
meta: &NestedMetaItem,
doc_alias: &str,
hir_id: HirId,
target: Target,
is_list: bool,
) -> bool {
let tcx = self.tcx;
let err_fn = move |span: Span, msg: &str| {
tcx.sess.span_err(
span,
&format!(
"`#[doc(alias{})]` {}",
if is_list { "(\"...\")" } else { " = \"...\"" },
msg,
),
);
false
};
if doc_alias.is_empty() {
self.doc_attr_str_error(meta, "alias");
return false;
return err_fn(
meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
"attribute cannot have empty value",
);
}
if let Some(c) =
doc_alias.chars().find(|&c| c == '"' || c == '\'' || (c.is_whitespace() && c != ' '))
{
self.tcx
.sess
.struct_span_err(
meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
&format!("{:?} character isn't allowed in `#[doc(alias = \"...\")]`", c),
)
.emit();
self.tcx.sess.span_err(
meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
&format!(
"{:?} character isn't allowed in `#[doc(alias{})]`",
c,
if is_list { "(\"...\")" } else { " = \"...\"" },
),
);
return false;
}
if doc_alias.starts_with(' ') || doc_alias.ends_with(' ') {
self.tcx
.sess
.struct_span_err(
meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
"`#[doc(alias = \"...\")]` cannot start or end with ' '",
)
.emit();
return false;
return err_fn(
meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
"cannot start or end with ' '",
);
}
if let Some(err) = match target {
Target::Impl => Some("implementation block"),
@ -446,27 +463,63 @@ impl CheckAttrVisitor<'tcx> {
}
_ => None,
} {
self.tcx
.sess
.struct_span_err(
meta.span(),
&format!("`#[doc(alias = \"...\")]` isn't allowed on {}", err),
)
.emit();
return false;
return err_fn(meta.span(), &format!("isn't allowed on {}", err));
}
let item_name = self.tcx.hir().name(hir_id);
if &*item_name.as_str() == doc_alias {
return err_fn(meta.span(), "is the same as the item's name");
}
true
}
fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool {
if let Some(values) = meta.meta_item_list() {
let mut errors = 0;
for v in values {
match v.literal() {
Some(l) => match l.kind {
LitKind::Str(s, _) => {
if !self.check_doc_alias_value(v, &s.as_str(), hir_id, target, true) {
errors += 1;
}
}
_ => {
self.tcx
.sess
.struct_span_err(
v.span(),
"`#[doc(alias(\"a\"))]` expects string literals",
)
.emit();
errors += 1;
}
},
None => {
self.tcx
.sess
.struct_span_err(
v.span(),
"`#[doc(alias(\"a\"))]` expects string literals",
)
.emit();
errors += 1;
}
}
}
errors == 0
} else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) {
self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false)
} else {
self.tcx
.sess
.struct_span_err(
meta.span(),
&format!("`#[doc(alias = \"...\")]` is the same as the item's name"),
"doc alias attribute expects a string `#[doc(alias = \"a\")]` or a list of \
strings `#[doc(alias(\"a\", \"b\"))]`",
)
.emit();
return false;
false
}
true
}
fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {

View File

@ -118,7 +118,8 @@ impl ExpnId {
HygieneData::with(|data| {
let old_expn_data = &mut data.expn_data[self.0 as usize];
assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
expn_data.orig_id.replace(self.as_u32()).expect_none("orig_id should be None");
assert_eq!(expn_data.orig_id, None);
expn_data.orig_id = Some(self.as_u32());
*old_expn_data = Some(expn_data);
});
update_disambiguator(self)
@ -202,7 +203,8 @@ impl HygieneData {
fn fresh_expn(&mut self, mut expn_data: Option<ExpnData>) -> ExpnId {
let raw_id = self.expn_data.len() as u32;
if let Some(data) = expn_data.as_mut() {
data.orig_id.replace(raw_id).expect_none("orig_id should be None");
assert_eq!(data.orig_id, None);
data.orig_id = Some(raw_id);
}
self.expn_data.push(expn_data);
ExpnId(raw_id)
@ -1410,9 +1412,11 @@ fn update_disambiguator(expn_id: ExpnId) {
let new_hash: Fingerprint = hasher.finish();
HygieneData::with(|data| {
data.expn_data_disambiguators
.get(&new_hash)
.expect_none("Hash collision after disambiguator update!");
assert_eq!(
data.expn_data_disambiguators.get(&new_hash),
None,
"Hash collision after disambiguator update!",
);
});
};
}

View File

@ -21,7 +21,6 @@
#![feature(negative_impls)]
#![feature(nll)]
#![feature(min_specialization)]
#![feature(option_expect_none)]
#[macro_use]
extern crate rustc_macros;
@ -1996,7 +1995,8 @@ impl<CTX: HashStableContext> HashStable<CTX> for ExpnId {
if cache.len() < new_len {
cache.resize(new_len, None);
}
cache[index].replace(sub_hash).expect_none("Cache slot was filled");
let prev = cache[index].replace(sub_hash);
assert_eq!(prev, None, "Cache slot was filled");
});
sub_hash.hash_stable(ctx, hasher);
}

View File

@ -453,41 +453,6 @@ impl SourceMap {
}
}
/// Returns `Some(span)`, a union of the LHS and RHS span. The LHS must precede the RHS. If
/// there are gaps between LHS and RHS, the resulting union will cross these gaps.
/// For this to work,
///
/// * the syntax contexts of both spans much match,
/// * the LHS span needs to end on the same line the RHS span begins,
/// * the LHS span must start at or before the RHS span.
pub fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
// Ensure we're at the same expansion ID.
if sp_lhs.ctxt() != sp_rhs.ctxt() {
return None;
}
let lhs_end = match self.lookup_line(sp_lhs.hi()) {
Ok(x) => x,
Err(_) => return None,
};
let rhs_begin = match self.lookup_line(sp_rhs.lo()) {
Ok(x) => x,
Err(_) => return None,
};
// If we must cross lines to merge, don't merge.
if lhs_end.line != rhs_begin.line {
return None;
}
// Ensure these follow the expected order and that we don't overlap.
if (sp_lhs.lo() <= sp_rhs.lo()) && (sp_lhs.hi() <= sp_rhs.lo()) {
Some(sp_lhs.to(sp_rhs))
} else {
None
}
}
pub fn span_to_string(&self, sp: Span) -> String {
if self.files.borrow().source_files.is_empty() && sp.is_dummy() {
return "no-location".to_string();
@ -931,13 +896,6 @@ impl SourceMap {
SourceFileAndBytePos { sf, pos: offset }
}
/// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
let idx = self.lookup_source_file_idx(bpos);
let sf = &(*self.files.borrow().source_files)[idx];
sf.bytepos_to_file_charpos(bpos)
}
// Returns the index of the `SourceFile` (in `self.files`) that contains `pos`.
// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
// since `source_files` is a `MonotonicVec`

View File

@ -10,6 +10,50 @@ fn init_source_map() -> SourceMap {
sm
}
impl SourceMap {
/// Returns `Some(span)`, a union of the LHS and RHS span. The LHS must precede the RHS. If
/// there are gaps between LHS and RHS, the resulting union will cross these gaps.
/// For this to work,
///
/// * the syntax contexts of both spans much match,
/// * the LHS span needs to end on the same line the RHS span begins,
/// * the LHS span must start at or before the RHS span.
fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
// Ensure we're at the same expansion ID.
if sp_lhs.ctxt() != sp_rhs.ctxt() {
return None;
}
let lhs_end = match self.lookup_line(sp_lhs.hi()) {
Ok(x) => x,
Err(_) => return None,
};
let rhs_begin = match self.lookup_line(sp_rhs.lo()) {
Ok(x) => x,
Err(_) => return None,
};
// If we must cross lines to merge, don't merge.
if lhs_end.line != rhs_begin.line {
return None;
}
// Ensure these follow the expected order and that we don't overlap.
if (sp_lhs.lo() <= sp_rhs.lo()) && (sp_lhs.hi() <= sp_rhs.lo()) {
Some(sp_lhs.to(sp_rhs))
} else {
None
}
}
/// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.
fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
let idx = self.lookup_source_file_idx(bpos);
let sf = &(*self.files.borrow().source_files)[idx];
sf.bytepos_to_file_charpos(bpos)
}
}
/// Tests `lookup_byte_offset`.
#[test]
fn t3() {

View File

@ -1012,7 +1012,7 @@ pub trait Iterator {
///
/// Because the closure passed to `skip_while()` takes a reference, and many
/// iterators iterate over references, this leads to a possibly confusing
/// situation, where the type of the closure is a double reference:
/// situation, where the type of the closure argument is a double reference:
///
/// ```
/// let a = [-1, 0, 1];

View File

@ -514,8 +514,8 @@ pub trait Read {
/// waiting for data, but if an object needs to block for a read and cannot,
/// it will typically signal this via an [`Err`] return value.
///
/// If the return value of this method is [`Ok(n)`], then it must be
/// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates
/// If the return value of this method is [`Ok(n)`], then implementations must
/// guarantee that `0 <= n <= buf.len()`. A nonzero `n` value indicates
/// that the buffer `buf` has been filled in with `n` bytes of data from this
/// source. If `n` is `0`, then it can indicate one of two scenarios:
///
@ -529,6 +529,11 @@ pub trait Read {
/// This may happen for example because fewer bytes are actually available right now
/// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
///
/// As this trait is safe to implement, callers cannot rely on `n <= buf.len()` for safety.
/// Extra care needs to be taken when `unsafe` functions are used to access the read bytes.
/// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
/// `n > buf.len()`.
///
/// No guarantees are provided about the contents of `buf` when this
/// function is called, implementations cannot rely on any property of the
/// contents of `buf` being true. It is recommended that *implementations*

View File

@ -1,6 +1,13 @@
//! Haiku-specific raw type definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
#![rustc_deprecated(
since = "1.53.0",
reason = "these type aliases are no longer supported by \
the standard library, the `libc` crate on \
crates.io should be used instead for the correct \
definitions"
)]
#![allow(deprecated)]
use crate::os::raw::c_long;

View File

@ -32,6 +32,7 @@ pub mod mutex;
pub mod net;
pub mod os;
pub mod path;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/process.rs"]
pub mod process;

View File

@ -1,38 +0,0 @@
use crate::io::{self, IoSlice, IoSliceMut};
use crate::sys::Void;
pub struct AnonPipe(Void);
impl AnonPipe {
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
match self.0 {}
}
pub fn is_read_vectored(&self) -> bool {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
match self.0 {}
}
pub fn is_write_vectored(&self) -> bool {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}
}
pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
match p1.0 {}
}

View File

@ -81,3 +81,10 @@ Then, when looking for it through the `rustdoc` search, if you enter "x" or
"big", search will show the `BigX` struct first.
There are some limitations on the doc alias names though: you can't use `"` or whitespace.
You can add multiple aliases at the same time by using a list:
```rust,no_run
#[doc(alias("x", "big"))]
pub struct BigX;
```

View File

@ -910,12 +910,23 @@ impl Attributes {
}
crate fn get_doc_aliases(&self) -> FxHashSet<String> {
self.other_attrs
.lists(sym::doc)
.filter(|a| a.has_name(sym::alias))
.filter_map(|a| a.value_str().map(|s| s.to_string()))
.filter(|v| !v.is_empty())
.collect::<FxHashSet<_>>()
let mut aliases = FxHashSet::default();
for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
if let Some(values) = attr.meta_item_list() {
for l in values {
match l.literal().unwrap().kind {
ast::LitKind::Str(s, _) => {
aliases.insert(s.as_str().to_string());
}
_ => unreachable!(),
}
}
} else {
aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap());
}
}
aliases
}
}

View File

@ -1,11 +1,11 @@
#![crate_type = "lib"]
#[doc(alias = "foo")] // ok!
#[doc(alias("bar", "baz"))] // ok!
pub struct Bar;
#[doc(alias)] //~ ERROR
#[doc(alias = 0)] //~ ERROR
#[doc(alias("bar"))] //~ ERROR
#[doc(alias = "\"")] //~ ERROR
#[doc(alias = "\n")] //~ ERROR
#[doc(alias = "
@ -13,4 +13,16 @@ pub struct Bar;
#[doc(alias = "\t")] //~ ERROR
#[doc(alias = " hello")] //~ ERROR
#[doc(alias = "hello ")] //~ ERROR
#[doc(alias = "")] //~ ERROR
pub struct Foo;
#[doc(alias(0))] //~ ERROR
#[doc(alias("\""))] //~ ERROR
#[doc(alias("\n"))] //~ ERROR
#[doc(alias("
"))] //~^ ERROR
#[doc(alias("\t"))] //~ ERROR
#[doc(alias(" hello"))] //~ ERROR
#[doc(alias("hello "))] //~ ERROR
#[doc(alias(""))] //~ ERROR
pub struct Foo2;

View File

@ -1,21 +1,15 @@
error: doc alias attribute expects a string: #[doc(alias = "a")]
--> $DIR/check-doc-alias-attr.rs:6:7
error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
--> $DIR/check-doc-alias-attr.rs:7:7
|
LL | #[doc(alias)]
| ^^^^^
error: doc alias attribute expects a string: #[doc(alias = "a")]
--> $DIR/check-doc-alias-attr.rs:7:7
error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
--> $DIR/check-doc-alias-attr.rs:8:7
|
LL | #[doc(alias = 0)]
| ^^^^^^^^^
error: doc alias attribute expects a string: #[doc(alias = "a")]
--> $DIR/check-doc-alias-attr.rs:8:7
|
LL | #[doc(alias("bar"))]
| ^^^^^^^^^^^^
error: '\"' character isn't allowed in `#[doc(alias = "...")]`
--> $DIR/check-doc-alias-attr.rs:9:15
|
@ -54,5 +48,61 @@ error: `#[doc(alias = "...")]` cannot start or end with ' '
LL | #[doc(alias = "hello ")]
| ^^^^^^^^
error: aborting due to 9 previous errors
error: `#[doc(alias = "...")]` attribute cannot have empty value
--> $DIR/check-doc-alias-attr.rs:16:15
|
LL | #[doc(alias = "")]
| ^^
error: `#[doc(alias("a"))]` expects string literals
--> $DIR/check-doc-alias-attr.rs:19:13
|
LL | #[doc(alias(0))]
| ^
error: '\"' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:20:13
|
LL | #[doc(alias("\""))]
| ^^^^
error: '\n' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:21:13
|
LL | #[doc(alias("\n"))]
| ^^^^
error: '\n' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:22:13
|
LL | #[doc(alias("
| _____________^
LL | | "))]
| |_^
error: '\t' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:24:13
|
LL | #[doc(alias("\t"))]
| ^^^^
error: `#[doc(alias("..."))]` cannot start or end with ' '
--> $DIR/check-doc-alias-attr.rs:25:13
|
LL | #[doc(alias(" hello"))]
| ^^^^^^^^
error: `#[doc(alias("..."))]` cannot start or end with ' '
--> $DIR/check-doc-alias-attr.rs:26:13
|
LL | #[doc(alias("hello "))]
| ^^^^^^^^
error: `#[doc(alias("..."))]` attribute cannot have empty value
--> $DIR/check-doc-alias-attr.rs:27:13
|
LL | #[doc(alias(""))]
| ^^
error: aborting due to 17 previous errors

View File

@ -2,6 +2,10 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![crate_name = "group_compat_hack"]
// This file has an unusual name in order to trigger the back-compat
// code in the compiler
extern crate proc_macro;
use proc_macro::TokenStream;

View File

@ -1,5 +1,5 @@
// check-pass
// aux-build:group-compat-hack.rs
// aux-build:pin-project-internal-0.4.0.rs
// compile-flags: -Z span-debug
#![no_std] // Don't load unnecessary hygiene information from std
@ -51,14 +51,16 @@ mod actix_web_test {
include!("actix-web/src/extract.rs");
struct Foo;
tuple_from_req!(Foo);
tuple_from_req!(Foo); //~ WARN using an old version
//~| WARN this was previously
}
mod actix_web_version_test {
include!("actix-web-2.0.0/src/extract.rs");
struct Foo;
tuple_from_req!(Foo);
tuple_from_req!(Foo); //~ WARN using an old version
//~| WARN this was previously
}
mod actori_web_test {

View File

@ -31,7 +31,39 @@ LL | impl_macros!(Foo);
= note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 2 warnings emitted
warning: using an old version of `actix-web`
--> $DIR/actix-web/src/extract.rs:5:34
|
LL | #[my_macro] struct Three($T);
| ^^
|
::: $DIR/group-compat-hack.rs:54:5
|
LL | tuple_from_req!(Foo);
| --------------------- in this macro invocation
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
= note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: using an old version of `actix-web`
--> $DIR/actix-web-2.0.0/src/extract.rs:5:34
|
LL | #[my_macro] struct Three($T);
| ^^
|
::: $DIR/group-compat-hack.rs:62:5
|
LL | tuple_from_req!(Foo);
| --------------------- in this macro invocation
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
= note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 4 warnings emitted
Future incompatibility report: Future breakage date: None, diagnostic:
warning: using an old version of `time-macros-impl`
@ -68,3 +100,37 @@ LL | impl_macros!(Foo);
= note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage date: None, diagnostic:
warning: using an old version of `actix-web`
--> $DIR/actix-web/src/extract.rs:5:34
|
LL | #[my_macro] struct Three($T);
| ^^
|
::: $DIR/group-compat-hack.rs:54:5
|
LL | tuple_from_req!(Foo);
| --------------------- in this macro invocation
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
= note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage date: None, diagnostic:
warning: using an old version of `actix-web`
--> $DIR/actix-web-2.0.0/src/extract.rs:5:34
|
LL | #[my_macro] struct Three($T);
| ^^
|
::: $DIR/group-compat-hack.rs:62:5
|
LL | tuple_from_req!(Foo);
| --------------------- in this macro invocation
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
= note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -5,6 +5,6 @@ Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/tim
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:46:13: 46:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:61:21: 61:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:68:21: 68:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:75:21: 75:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:62:21: 62:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:70:21: 70:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:77:21: 77:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]

View File

@ -1,11 +1,11 @@
#![crate_type = "lib"]
#[doc(alias = "foo")] // ok!
#[doc(alias("bar", "baz"))] // ok!
pub struct Bar;
#[doc(alias)] //~ ERROR
#[doc(alias = 0)] //~ ERROR
#[doc(alias("bar"))] //~ ERROR
#[doc(alias = "\"")] //~ ERROR
#[doc(alias = "\n")] //~ ERROR
#[doc(alias = "
@ -13,4 +13,16 @@ pub struct Bar;
#[doc(alias = "\t")] //~ ERROR
#[doc(alias = " hello")] //~ ERROR
#[doc(alias = "hello ")] //~ ERROR
#[doc(alias = "")] //~ ERROR
pub struct Foo;
#[doc(alias(0))] //~ ERROR
#[doc(alias("\""))] //~ ERROR
#[doc(alias("\n"))] //~ ERROR
#[doc(alias("
"))] //~^ ERROR
#[doc(alias("\t"))] //~ ERROR
#[doc(alias(" hello"))] //~ ERROR
#[doc(alias("hello "))] //~ ERROR
#[doc(alias(""))] //~ ERROR
pub struct Foo2;

View File

@ -1,21 +1,15 @@
error: doc alias attribute expects a string: #[doc(alias = "a")]
--> $DIR/check-doc-alias-attr.rs:6:7
error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
--> $DIR/check-doc-alias-attr.rs:7:7
|
LL | #[doc(alias)]
| ^^^^^
error: doc alias attribute expects a string: #[doc(alias = "a")]
--> $DIR/check-doc-alias-attr.rs:7:7
error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
--> $DIR/check-doc-alias-attr.rs:8:7
|
LL | #[doc(alias = 0)]
| ^^^^^^^^^
error: doc alias attribute expects a string: #[doc(alias = "a")]
--> $DIR/check-doc-alias-attr.rs:8:7
|
LL | #[doc(alias("bar"))]
| ^^^^^^^^^^^^
error: '\"' character isn't allowed in `#[doc(alias = "...")]`
--> $DIR/check-doc-alias-attr.rs:9:15
|
@ -54,5 +48,61 @@ error: `#[doc(alias = "...")]` cannot start or end with ' '
LL | #[doc(alias = "hello ")]
| ^^^^^^^^
error: aborting due to 9 previous errors
error: `#[doc(alias = "...")]` attribute cannot have empty value
--> $DIR/check-doc-alias-attr.rs:16:15
|
LL | #[doc(alias = "")]
| ^^
error: `#[doc(alias("a"))]` expects string literals
--> $DIR/check-doc-alias-attr.rs:19:13
|
LL | #[doc(alias(0))]
| ^
error: '\"' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:20:13
|
LL | #[doc(alias("\""))]
| ^^^^
error: '\n' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:21:13
|
LL | #[doc(alias("\n"))]
| ^^^^
error: '\n' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:22:13
|
LL | #[doc(alias("
| _____________^
LL | | "))]
| |_^
error: '\t' character isn't allowed in `#[doc(alias("..."))]`
--> $DIR/check-doc-alias-attr.rs:24:13
|
LL | #[doc(alias("\t"))]
| ^^^^
error: `#[doc(alias("..."))]` cannot start or end with ' '
--> $DIR/check-doc-alias-attr.rs:25:13
|
LL | #[doc(alias(" hello"))]
| ^^^^^^^^
error: `#[doc(alias("..."))]` cannot start or end with ' '
--> $DIR/check-doc-alias-attr.rs:26:13
|
LL | #[doc(alias("hello "))]
| ^^^^^^^^
error: `#[doc(alias("..."))]` attribute cannot have empty value
--> $DIR/check-doc-alias-attr.rs:27:13
|
LL | #[doc(alias(""))]
| ^^
error: aborting due to 17 previous errors

View File

@ -123,6 +123,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
"measureme",
"memchr",
"memmap",
"memmap2",
"memoffset",
"miniz_oxide",
"num_cpus",