diff options
| author | bors <bors@rust-lang.org> | 2021-03-19 15:38:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-03-19 15:38:57 +0000 |
| commit | 9f4bc3ead43a57783d8abea2fa6931a6736f3490 (patch) | |
| tree | ea7f9020ead403b250e25b49007cbc9043c9ec21 /compiler/rustc_passes/src | |
| parent | b97fd3e5a1545ab02e18c52e7f3d2e78a5c960bf (diff) | |
| parent | 99f411d4385f654cfffb5126725414da8b99e211 (diff) | |
| download | rust-9f4bc3ead43a57783d8abea2fa6931a6736f3490.tar.gz rust-9f4bc3ead43a57783d8abea2fa6931a6736f3490.zip | |
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
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 113 |
1 files changed, 83 insertions, 30 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 775e27e68f8..d91d0e1765b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -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 { |
