From 47b8a5258df2e8ca59bf989b2dca2f1619e24092 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 22 Aug 2020 15:00:19 -0400 Subject: [PATCH 1/7] Report an ambiguity if both modules and primitives are in scope - Add a new `prim@` disambiguator, since both modules and primitives are in the same namespace - Refactor `report_ambiguity` into a closure Additionally, I noticed that rustdoc would previously allow `[struct@char]` if `char` resolved to a primitive (not if it had a DefId). I fixed that and added a test case. --- .../passes/collect_intra_doc_links.rs | 152 +++++++++++++----- .../rustdoc-ui/intra-link-prim-conflict.rs | 30 ++++ .../intra-link-prim-conflict.stderr | 53 ++++++ 3 files changed, 192 insertions(+), 43 deletions(-) create mode 100644 src/test/rustdoc-ui/intra-link-prim-conflict.rs create mode 100644 src/test/rustdoc-ui/intra-link-prim-conflict.stderr diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 2ed3d07974fcf..bf6d47c885b89 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -181,7 +181,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { fn resolve( &self, path_str: &str, - disambiguator: Option, ns: Namespace, current_item: &Option, parent_id: Option, @@ -218,18 +217,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { return Ok((res, Some(path_str.to_owned()))); } Res::Def(DefKind::Mod, _) => { - // This resolved to a module, but we want primitive types to take precedence instead. - if matches!( - disambiguator, - None | Some(Disambiguator::Namespace(Namespace::TypeNS)) - ) { - if let Some((path, prim)) = is_primitive(path_str, ns) { - if extra_fragment.is_some() { - return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive)); - } - return Ok((prim, Some(path.to_owned()))); - } - } return Ok((res, extra_fragment.clone())); } _ => { @@ -713,7 +700,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let resolved_self; let mut path_str; let disambiguator; - let (res, fragment) = { + let (mut res, mut fragment) = { path_str = if let Ok((d, path)) = Disambiguator::from_str(&link) { disambiguator = Some(d); path @@ -756,7 +743,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { Some(ns @ (ValueNS | TypeNS)) => { match self.resolve( path_str, - disambiguator, ns, ¤t_item, base_node, @@ -784,7 +770,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { .map(|res| (res, extra_fragment.clone())), type_ns: match self.resolve( path_str, - disambiguator, TypeNS, ¤t_item, base_node, @@ -802,7 +787,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }, value_ns: match self.resolve( path_str, - disambiguator, ValueNS, ¤t_item, base_node, @@ -848,13 +832,18 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if is_derive_trait_collision(&candidates) { candidates.macro_ns = None; } + let candidates = + candidates.map(|candidate| candidate.map(|(res, _)| res)); + let candidates = [TypeNS, ValueNS, MacroNS] + .iter() + .filter_map(|&ns| candidates[ns].map(|res| (res, ns))); ambiguity_error( cx, &item, path_str, &dox, link_range, - candidates.map(|candidate| candidate.map(|(res, _)| res)), + candidates.collect(), ); continue; } @@ -870,13 +859,81 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } }; + // Check for a primitive which might conflict with a module + // Report the ambiguity and require that the user specify which one they meant. + // FIXME: could there ever be a primitive not in the type namespace? + if matches!( + disambiguator, + None | Some(Disambiguator::Namespace(Namespace::TypeNS) | Disambiguator::Primitive) + ) && !matches!(res, Res::PrimTy(_)) + { + if let Some((path, prim)) = is_primitive(path_str, TypeNS) { + // `prim@char` + if matches!(disambiguator, Some(Disambiguator::Primitive)) { + if fragment.is_some() { + anchor_failure( + cx, + &item, + path_str, + &dox, + link_range, + AnchorFailure::Primitive, + ); + continue; + } + res = prim; + fragment = Some(path.to_owned()); + } else { + // `[char]` when a `char` module is in scope + let candidates = vec![(res, TypeNS), (prim, TypeNS)]; + ambiguity_error(cx, &item, path_str, &dox, link_range, candidates); + continue; + } + } + } + + let report_mismatch = |specified: Disambiguator, resolved: Disambiguator| { + // The resolved item did not match the disambiguator; give a better error than 'not found' + let msg = format!("incompatible link kind for `{}`", path_str); + report_diagnostic(cx, &msg, &item, &dox, link_range.clone(), |diag, sp| { + let note = format!( + "this link resolved to {} {}, which is not {} {}", + resolved.article(), + resolved.descr(), + specified.article(), + specified.descr() + ); + let suggestion = resolved.display_for(path_str); + let help_msg = + format!("to link to the {}, use its disambiguator", resolved.descr()); + diag.note(¬e); + if let Some(sp) = sp { + diag.span_suggestion( + sp, + &help_msg, + suggestion, + Applicability::MaybeIncorrect, + ); + } else { + diag.help(&format!("{}: {}", help_msg, suggestion)); + } + }); + }; if let Res::PrimTy(_) = res { - item.attrs.links.push((ori_link, None, fragment)); + match disambiguator { + Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => { + item.attrs.links.push((ori_link, None, fragment)) + } + Some(other) => { + report_mismatch(other, Disambiguator::Primitive); + continue; + } + } } else { debug!("intra-doc link to {} resolved to {:?}", path_str, res); // Disallow e.g. linking to enums with `struct@` - if let Res::Def(kind, id) = res { + if let Res::Def(kind, _) = res { debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator); match (self.kind_side_channel.take().unwrap_or(kind), disambiguator) { | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const))) @@ -890,22 +947,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { // All of these are valid, so do nothing => {} (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {} - (_, Some(Disambiguator::Kind(expected))) => { - // The resolved item did not match the disambiguator; give a better error than 'not found' - let msg = format!("incompatible link kind for `{}`", path_str); - report_diagnostic(cx, &msg, &item, &dox, link_range, |diag, sp| { - // HACK(jynelson): by looking at the source I saw the DefId we pass - // for `expected.descr()` doesn't matter, since it's not a crate - let note = format!("this link resolved to {} {}, which is not {} {}", kind.article(), kind.descr(id), expected.article(), expected.descr(id)); - let suggestion = Disambiguator::display_for(kind, path_str); - let help_msg = format!("to link to the {}, use its disambiguator", kind.descr(id)); - diag.note(¬e); - if let Some(sp) = sp { - diag.span_suggestion(sp, &help_msg, suggestion, Applicability::MaybeIncorrect); - } else { - diag.help(&format!("{}: {}", help_msg, suggestion)); - } - }); + (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => { + report_mismatch(specified, Disambiguator::Kind(kind)); continue; } } @@ -961,6 +1004,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Disambiguator { + Primitive, Kind(DefKind), Namespace(Namespace), } @@ -968,7 +1012,7 @@ enum Disambiguator { impl Disambiguator { /// (disambiguator, path_str) fn from_str(link: &str) -> Result<(Self, &str), ()> { - use Disambiguator::{Kind, Namespace as NS}; + use Disambiguator::{Kind, Namespace as NS, Primitive}; let find_suffix = || { let suffixes = [ @@ -999,6 +1043,7 @@ impl Disambiguator { "type" => NS(Namespace::TypeNS), "value" => NS(Namespace::ValueNS), "macro" => NS(Namespace::MacroNS), + "prim" | "primitive" => Primitive, _ => return find_suffix(), }; Ok((d, &rest[1..])) @@ -1007,7 +1052,12 @@ impl Disambiguator { } } - fn display_for(kind: DefKind, path_str: &str) -> String { + fn display_for(self, path_str: &str) -> String { + let kind = match self { + Disambiguator::Primitive => return format!("prim@{}", path_str), + Disambiguator::Kind(kind) => kind, + Disambiguator::Namespace(_) => panic!("display_for cannot be used on namespaces"), + }; if kind == DefKind::Macro(MacroKind::Bang) { return format!("{}!", path_str); } else if kind == DefKind::Fn || kind == DefKind::AssocFn { @@ -1043,6 +1093,25 @@ impl Disambiguator { Self::Kind(k) => { k.ns().expect("only DefKinds with a valid namespace can be disambiguators") } + Self::Primitive => TypeNS, + } + } + + fn article(self) -> &'static str { + match self { + Self::Namespace(_) => panic!("article() doesn't make sense for namespaces"), + Self::Kind(k) => k.article(), + Self::Primitive => "a", + } + } + + fn descr(self) -> &'static str { + match self { + Self::Namespace(n) => n.descr(), + // HACK(jynelson): by looking at the source I saw the DefId we pass + // for `expected.descr()` doesn't matter, since it's not a crate + Self::Kind(k) => k.descr(DefId::local(hir::def_id::DefIndex::from_usize(0))), + Self::Primitive => "builtin type", } } } @@ -1183,14 +1252,10 @@ fn ambiguity_error( path_str: &str, dox: &str, link_range: Option>, - candidates: PerNS>, + candidates: Vec<(Res, Namespace)>, ) { let mut msg = format!("`{}` is ", path_str); - let candidates = [TypeNS, ValueNS, MacroNS] - .iter() - .filter_map(|&ns| candidates[ns].map(|res| (res, ns))) - .collect::>(); match candidates.as_slice() { [(first_def, _), (second_def, _)] => { msg += &format!( @@ -1229,6 +1294,7 @@ fn ambiguity_error( } _ => { let type_ = match (res, ns) { + (Res::PrimTy(_), _) => "prim", (Res::Def(DefKind::Const, _), _) => "const", (Res::Def(DefKind::Static, _), _) => "static", (Res::Def(DefKind::Struct, _), _) => "struct", diff --git a/src/test/rustdoc-ui/intra-link-prim-conflict.rs b/src/test/rustdoc-ui/intra-link-prim-conflict.rs new file mode 100644 index 0000000000000..34276fbcf2058 --- /dev/null +++ b/src/test/rustdoc-ui/intra-link-prim-conflict.rs @@ -0,0 +1,30 @@ +#![deny(broken_intra_doc_links)] +//~^ NOTE lint level is defined + +/// [char] +//~^ ERROR both a module and a builtin type +//~| NOTE ambiguous link +//~| HELP to link to the module +//~| HELP to link to the builtin type + +/// [type@char] +//~^ ERROR both a module and a builtin type +//~| NOTE ambiguous link +//~| HELP to link to the module +//~| HELP to link to the builtin type + +/// [mod@char] // ok +/// [prim@char] // ok + +/// [struct@char] +//~^ ERROR incompatible link +//~| HELP use its disambiguator +//~| NOTE resolved to a module +pub mod char {} + +pub mod inner { + //! [struct@char] + //~^ ERROR incompatible link + //~| HELP use its disambiguator + //~| NOTE resolved to a builtin type +} diff --git a/src/test/rustdoc-ui/intra-link-prim-conflict.stderr b/src/test/rustdoc-ui/intra-link-prim-conflict.stderr new file mode 100644 index 0000000000000..b28a442666656 --- /dev/null +++ b/src/test/rustdoc-ui/intra-link-prim-conflict.stderr @@ -0,0 +1,53 @@ +error: `char` is both a module and a builtin type + --> $DIR/intra-link-prim-conflict.rs:4:6 + | +LL | /// [char] + | ^^^^ ambiguous link + | +note: the lint level is defined here + --> $DIR/intra-link-prim-conflict.rs:1:9 + | +LL | #![deny(broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^ +help: to link to the module, prefix with the item type + | +LL | /// [module@char] + | ^^^^^^^^^^^ +help: to link to the builtin type, prefix with the item type + | +LL | /// [prim@char] + | ^^^^^^^^^ + +error: `char` is both a module and a builtin type + --> $DIR/intra-link-prim-conflict.rs:10:6 + | +LL | /// [type@char] + | ^^^^^^^^^ ambiguous link + | +help: to link to the module, prefix with the item type + | +LL | /// [module@char] + | ^^^^^^^^^^^ +help: to link to the builtin type, prefix with the item type + | +LL | /// [prim@char] + | ^^^^^^^^^ + +error: incompatible link kind for `char` + --> $DIR/intra-link-prim-conflict.rs:19:6 + | +LL | /// [struct@char] + | ^^^^^^^^^^^ help: to link to the module, use its disambiguator: `mod@char` + | + = note: this link resolved to a module, which is not a struct + +error: incompatible link kind for `char` + --> $DIR/intra-link-prim-conflict.rs:26:10 + | +LL | //! [struct@char] + | ^^^^^^^^^^^ help: to link to the builtin type, use its disambiguator: `prim@char` + | + = note: this link resolved to a builtin type, which is not a struct + +error: aborting due to 4 previous errors + From 556fd86524e37dc7f33cba66bec5f45794219457 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 22 Aug 2020 16:23:01 -0400 Subject: [PATCH 2/7] Disambiguate char -> prim@char for `core` This also changes human intuition -> intuition. 'human intuition' sounds vaguely menacing. --- library/core/src/str/mod.rs | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 7c1027f60babb..ab9afeb25e0ce 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -476,6 +476,7 @@ Section: Iterators /// This struct is created by the [`chars`] method on [`str`]. /// See its documentation for more. /// +/// [`char`]: prim@char /// [`chars`]: str::chars #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] @@ -673,6 +674,7 @@ impl<'a> Chars<'a> { /// This struct is created by the [`char_indices`] method on [`str`]. /// See its documentation for more. /// +/// [`char`]: prim@char /// [`char_indices`]: str::char_indices #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] @@ -2270,6 +2272,8 @@ impl str { /// This length is in bytes, not [`char`]s or graphemes. In other words, /// it may not be what a human considers the length of the string. /// + /// [`char`]: prim@char + /// /// # Examples /// /// Basic usage: @@ -2791,7 +2795,9 @@ impl str { /// assert_eq!(None, chars.next()); /// ``` /// - /// Remember, [`char`]s may not match your human intuition about characters: + /// Remember, [`char`]s may not match your intuition about characters: + /// + /// [`char`]: prim@char /// /// ``` /// let y = "y̆"; @@ -2842,7 +2848,9 @@ impl str { /// assert_eq!(None, char_indices.next()); /// ``` /// - /// Remember, [`char`]s may not match your human intuition about characters: + /// Remember, [`char`]s may not match your intuition about characters: + /// + /// [`char`]: prim@char /// /// ``` /// let yes = "y̆es"; @@ -3053,6 +3061,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -3079,6 +3088,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -3104,6 +3114,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -3132,6 +3143,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -3179,6 +3191,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -3225,6 +3238,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3344,6 +3358,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -3383,6 +3398,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3434,6 +3450,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// Equivalent to [`split`], except that the trailing substring @@ -3478,6 +3495,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// Equivalent to [`split`], except that the trailing substring is @@ -3526,6 +3544,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3578,6 +3597,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3666,6 +3686,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3702,6 +3723,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3743,6 +3765,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -3785,6 +3808,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Iterator behavior @@ -4003,6 +4027,7 @@ impl str { /// The [pattern] can be a [`char`], a slice of [`char`]s, or a function /// or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -4050,6 +4075,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Text directionality @@ -4094,6 +4120,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -4121,6 +4148,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Examples @@ -4147,6 +4175,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Text directionality @@ -4195,6 +4224,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Text directionality @@ -4231,6 +4261,7 @@ impl str { /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a /// function or closure that determines if a character matches. /// + /// [`char`]: prim@char /// [pattern]: self::pattern /// /// # Text directionality From 373432e47f0203e255b4adff00ac0cbc42e8b879 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 22 Aug 2020 16:26:01 -0400 Subject: [PATCH 3/7] Convert from str -> prim@str for `alloc` --- library/alloc/src/string.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index d7d7b6bd157bc..05690e19d23e4 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -268,8 +268,8 @@ use crate::vec::Vec; /// /// Here, there's no need to allocate more memory inside the loop. /// -/// [`str`]: type@str -/// [`&str`]: type@str +/// [`str`]: prim@str +/// [`&str`]: prim@str /// [`Deref`]: core::ops::Deref /// [`as_str()`]: String::as_str #[derive(PartialOrd, Eq, Ord)] @@ -296,7 +296,7 @@ pub struct String { /// /// [`Utf8Error`]: core::str::Utf8Error /// [`std::str`]: core::str -/// [`&str`]: str +/// [`&str`]: prim@str /// [`utf8_error`]: Self::utf8_error /// /// # Examples @@ -472,7 +472,7 @@ impl String { /// /// [`from_utf8_unchecked`]: String::from_utf8_unchecked /// [`Vec`]: crate::vec::Vec - /// [`&str`]: str + /// [`&str`]: prim@str /// [`into_bytes`]: String::into_bytes #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1576,6 +1576,8 @@ impl String { /// /// This will drop any excess capacity. /// + /// [`str`]: prim@str + /// /// # Examples /// /// Basic usage: @@ -1644,7 +1646,7 @@ impl FromUtf8Error { /// on using it. /// /// [`std::str`]: core::str - /// [`&str`]: str + /// [`&str`]: prim@str /// /// # Examples /// From 6f4681bacc78a00a63766f12a17560701ab5c1e8 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 22 Aug 2020 16:29:55 -0400 Subject: [PATCH 4/7] Convert str -> prim@str in `std` --- library/std/src/error.rs | 4 ++++ library/std/src/ffi/c_str.rs | 7 ++++--- library/std/src/io/mod.rs | 2 +- library/std/src/lib.rs | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 1b7681bd4bb1d..84e686c2fef81 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -296,6 +296,8 @@ impl From for Box { impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// + /// [`str`]: prim@str + /// /// # Examples /// /// ``` @@ -317,6 +319,8 @@ impl<'a> From<&str> for Box { impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// + /// [`str`]: prim@str + /// /// # Examples /// /// ``` diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 11b3f22503e83..717967fb7687f 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -69,7 +69,7 @@ use crate::sys; /// extern functions. See the documentation for that function for a /// discussion on ensuring the lifetime of the raw pointer. /// -/// [`&str`]: str +/// [`&str`]: prim@str /// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr /// [slice.len]: ../primitive.slice.html#method.len /// [`Deref`]: ops::Deref @@ -180,7 +180,7 @@ pub struct CString { /// println!("string: {}", my_string_safe()); /// ``` /// -/// [`&str`]: str +/// [`&str`]: prim@str #[derive(Hash)] #[stable(feature = "rust1", since = "1.0.0")] // FIXME: @@ -1351,7 +1351,7 @@ impl CStr { /// function will return the corresponding [`&str`] slice. Otherwise, /// it will return an error with details of where UTF-8 validation failed. /// - /// [`&str`]: str + /// [`&str`]: prim@str /// /// # Examples /// @@ -1379,6 +1379,7 @@ impl CStr { /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result. /// + /// [`str`]: prim@str /// [`Borrowed`]: Cow::Borrowed /// [`Owned`]: Cow::Owned /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 3245629483828..462b696db40cf 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -480,7 +480,7 @@ where /// ``` /// /// [`read()`]: Read::read -/// [`&str`]: str +/// [`&str`]: prim@str /// [`std::io`]: self /// [`File`]: crate::fs::File /// [slice]: ../../std/primitive.slice.html diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 00f37d90c6afe..1142b74ff0dc4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -172,6 +172,7 @@ //! [`Vec`]: vec::Vec //! [`atomic`]: sync::atomic //! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for +//! [`str`]: prim@str //! [`mpsc`]: sync::mpsc //! [`std::cmp`]: cmp //! [`std::slice`]: slice From bcd6fe35e0b7577de7a72114270f9c2daa431738 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 22 Aug 2020 17:12:32 -0400 Subject: [PATCH 5/7] Update primitive test to match the new behavior --- src/test/rustdoc/intra-link-prim-precedence.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/rustdoc/intra-link-prim-precedence.rs b/src/test/rustdoc/intra-link-prim-precedence.rs index 15ea1232fd6fb..0a4e57ef643e7 100644 --- a/src/test/rustdoc/intra-link-prim-precedence.rs +++ b/src/test/rustdoc/intra-link-prim-precedence.rs @@ -1,17 +1,17 @@ // ignore-tidy-linelength #![deny(broken_intra_doc_links)] -pub mod char {} +pub mod char { + /// [char] + // @has intra_link_prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' + pub struct Inner; +} -/// See also [type@char] +/// See [prim@char] // @has intra_link_prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' pub struct MyString; -/// See also [char] -// @has intra_link_prim_precedence/struct.MyString2.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' -pub struct MyString2; - /// See also [crate::char] and [mod@char] -// @has intra_link_prim_precedence/struct.MyString3.html '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'crate::char' +// @has intra_link_prim_precedence/struct.MyString2.html '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'crate::char' // @has - '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'mod@char' -pub struct MyString3; +pub struct MyString2; From 73de34319eac65a66037870138324f7f5618342d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 22 Aug 2020 17:13:33 -0400 Subject: [PATCH 6/7] Document prim@ and primitive@ --- src/doc/rustdoc/src/unstable-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index f45e229506438..2f49fc8a41552 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -81,7 +81,7 @@ impl AsyncReceiver { } ``` -Paths in Rust have three namespaces: type, value, and macro. Items from these namespaces are allowed to overlap. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `function@`, `mod@`, `fn@`, `module@`, `method@` , `macro@`, or `derive@`: +Paths in Rust have three namespaces: type, value, and macro. Items from these namespaces are allowed to overlap. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `function@`, `mod@`, `fn@`, `module@`, `method@`, `prim@`, `primitive@`, `macro@`, or `derive@`: ```rust /// See also: [`Foo`](struct@Foo) From 25cfd57b49b84fda6cd5b87072bc7e9fe0c582ce Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 23 Aug 2020 22:41:45 -0400 Subject: [PATCH 7/7] xpy fmt --- src/librustdoc/passes/collect_intra_doc_links.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index bf6d47c885b89..bf091a0a624dd 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -741,13 +741,8 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { match disambiguator.map(Disambiguator::ns) { Some(ns @ (ValueNS | TypeNS)) => { - match self.resolve( - path_str, - ns, - ¤t_item, - base_node, - &extra_fragment, - ) { + match self.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment) + { Ok(res) => res, Err(ErrorKind::ResolutionFailure) => { resolution_failure(cx, &item, path_str, &dox, link_range);