Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8e6b478

Browse files
committedApr 5, 2021
Auto merge of #83905 - JohnTitor:rollup-pa1la80, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #83370 (Add `x.py setup tools` which enables `download-rustc` by default) - #83489 (Properly suggest deref in else block) - #83734 (Catch a bad placeholder type error for statics in `extern`s) - #83814 (expand: Do not ICE when a legacy AST-based macro attribute produces and empty expression) - #83835 (rustdoc: sort search index items for compression) - #83849 (rustdoc: Cleanup handling of associated items for intra-doc links) - #83881 (:arrow_up: rust-analyzer) - #83885 (Document compiler/ with -Aprivate-intra-doc-links) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents d322385 + d8c04b1 commit 8e6b478

File tree

25 files changed

+367
-192
lines changed

25 files changed

+367
-192
lines changed
 

‎compiler/rustc_errors/src/diagnostic_builder.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ macro_rules! forward {
4545
pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)?) -> &Self
4646
) => {
4747
$(#[$attrs])*
48-
// we always document with --document-private-items
49-
#[cfg_attr(not(bootstrap), allow(rustdoc::private_intra_doc_links))]
50-
#[cfg_attr(bootstrap, allow(private_intra_doc_links))]
5148
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
5249
pub fn $n(&self, $($name: $ty),*) -> &Self {
5350
self.diagnostic.$n($($name),*);
@@ -62,9 +59,6 @@ macro_rules! forward {
6259
) => {
6360
$(#[$attrs])*
6461
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
65-
// we always document with --document-private-items
66-
#[cfg_attr(not(bootstrap), allow(rustdoc::private_intra_doc_links))]
67-
#[cfg_attr(bootstrap, allow(private_intra_doc_links))]
6862
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
6963
self.0.diagnostic.$n($($name),*);
7064
self
@@ -82,9 +76,6 @@ macro_rules! forward {
8276
) => {
8377
$(#[$attrs])*
8478
#[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")]
85-
// we always document with --document-private-items
86-
#[cfg_attr(not(bootstrap), allow(rustdoc::private_intra_doc_links))]
87-
#[cfg_attr(bootstrap, allow(private_intra_doc_links))]
8879
pub fn $n<$($generic: $bound),*>(&mut self, $($name: $ty),*) -> &mut Self {
8980
self.0.diagnostic.$n($($name),*);
9081
self

‎compiler/rustc_expand/src/expand.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
735735
});
736736
}
737737
};
738-
fragment_kind.expect_from_annotatables(items)
738+
if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
739+
let msg =
740+
"removing an expression is not supported in this position";
741+
self.cx.span_err(span, msg);
742+
fragment_kind.dummy(span)
743+
} else {
744+
fragment_kind.expect_from_annotatables(items)
745+
}
739746
}
740747
Err(mut err) => {
741748
err.emit();

‎compiler/rustc_resolve/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![feature(nll)]
1919
#![cfg_attr(bootstrap, feature(or_patterns))]
2020
#![recursion_limit = "256"]
21+
#![allow(rustdoc::private_intra_doc_links)]
2122

2223
pub use rustc_hir::def::{Namespace, PerNS};
2324

‎compiler/rustc_typeck/src/check/demand.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
366366
false
367367
}
368368

369+
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
370+
crate fn maybe_get_block_expr(&self, hir_id: hir::HirId) -> Option<&'tcx hir::Expr<'tcx>> {
371+
match self.tcx.hir().find(hir_id)? {
372+
Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, ..), .. }) => block.expr,
373+
_ => None,
374+
}
375+
}
376+
377+
/// Returns whether the given expression is an `else if`.
378+
crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
379+
if let hir::ExprKind::If(..) = expr.kind {
380+
let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
381+
if let Some(Node::Expr(hir::Expr {
382+
kind: hir::ExprKind::If(_, _, Some(else_expr)),
383+
..
384+
})) = self.tcx.hir().find(parent_id)
385+
{
386+
return else_expr.hir_id == expr.hir_id;
387+
}
388+
}
389+
false
390+
}
391+
369392
/// This function is used to determine potential "simple" improvements or users' errors and
370393
/// provide them useful help. For example:
371394
///
@@ -652,6 +675,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
652675
};
653676
let suggestion = if is_struct_pat_shorthand_field {
654677
format!("{}: *{}", code, code)
678+
} else if self.is_else_if_block(expr) {
679+
// Don't suggest nonsense like `else *if`
680+
return None;
681+
} else if let Some(expr) = self.maybe_get_block_expr(expr.hir_id) {
682+
format!("*{}", sm.span_to_snippet(expr.span).unwrap_or(code))
655683
} else {
656684
format!("*{}", code)
657685
};

‎compiler/rustc_typeck/src/collect.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,14 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
734734
tcx.ensure().generics_of(item.def_id);
735735
tcx.ensure().type_of(item.def_id);
736736
tcx.ensure().predicates_of(item.def_id);
737-
if let hir::ForeignItemKind::Fn(..) = item.kind {
738-
tcx.ensure().fn_sig(item.def_id);
737+
match item.kind {
738+
hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id),
739+
hir::ForeignItemKind::Static(..) => {
740+
let mut visitor = PlaceholderHirTyCollector::default();
741+
visitor.visit_foreign_item(item);
742+
placeholder_type_error(tcx, None, &[], visitor.0, false, None);
743+
}
744+
_ => (),
739745
}
740746
}
741747
}

‎src/bootstrap/defaults/config.compiler.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@ debug-logging = true
88
incremental = true
99

1010
[llvm]
11-
# Will download LLVM from CI if available on your platform (Linux only for now)
12-
# https://github.com/rust-lang/rust/issues/77084 tracks support for more platforms
11+
# Will download LLVM from CI if available on your platform.
1312
download-ci-llvm = "if-available"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# These defaults are meant for contributors to tools which build on the
2+
# compiler, but do not modify it directly.
3+
[rust]
4+
# This enables `RUSTC_LOG=debug`, avoiding confusing situations
5+
# where adding `debug!()` appears to do nothing.
6+
# However, it makes running the compiler slightly slower.
7+
debug-logging = true
8+
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
9+
incremental = true
10+
# Download rustc from CI instead of building it from source.
11+
# This cuts compile times by almost 60x, but means you can't modify the compiler.
12+
download-rustc = "if-unchanged"
13+
14+
[llvm]
15+
# Will download LLVM from CI if available on your platform.
16+
download-ci-llvm = "if-available"

‎src/bootstrap/doc.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,8 @@ impl Step for Rustc {
549549
// Build cargo command.
550550
let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc");
551551
cargo.rustdocflag("--document-private-items");
552+
// Since we always pass --document-private-items, there's no need to warn about linking to private items.
553+
cargo.rustdocflag("-Arustdoc::private-intra-doc-links");
552554
cargo.rustdocflag("--enable-index-page");
553555
cargo.rustdocflag("-Zunstable-options");
554556
cargo.rustdocflag("-Znormalize-docs");

‎src/bootstrap/setup.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub enum Profile {
1313
Compiler,
1414
Codegen,
1515
Library,
16+
Tools,
1617
User,
1718
}
1819

@@ -24,15 +25,16 @@ impl Profile {
2425
pub fn all() -> impl Iterator<Item = Self> {
2526
use Profile::*;
2627
// N.B. these are ordered by how they are displayed, not alphabetically
27-
[Library, Compiler, Codegen, User].iter().copied()
28+
[Library, Compiler, Codegen, Tools, User].iter().copied()
2829
}
2930

3031
pub fn purpose(&self) -> String {
3132
use Profile::*;
3233
match self {
3334
Library => "Contribute to the standard library",
34-
Compiler => "Contribute to the compiler or rustdoc",
35+
Compiler => "Contribute to the compiler itself",
3536
Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
37+
Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
3638
User => "Install Rust from source",
3739
}
3840
.to_string()
@@ -53,9 +55,12 @@ impl FromStr for Profile {
5355
fn from_str(s: &str) -> Result<Self, Self::Err> {
5456
match s {
5557
"lib" | "library" => Ok(Profile::Library),
56-
"compiler" | "rustdoc" => Ok(Profile::Compiler),
58+
"compiler" => Ok(Profile::Compiler),
5759
"llvm" | "codegen" => Ok(Profile::Codegen),
5860
"maintainer" | "user" => Ok(Profile::User),
61+
"tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
62+
Ok(Profile::Tools)
63+
}
5964
_ => Err(format!("unknown profile: '{}'", s)),
6065
}
6166
}
@@ -68,6 +73,7 @@ impl fmt::Display for Profile {
6873
Profile::Codegen => write!(f, "codegen"),
6974
Profile::Library => write!(f, "library"),
7075
Profile::User => write!(f, "user"),
76+
Profile::Tools => write!(f, "tools"),
7177
}
7278
}
7379
}
@@ -103,6 +109,14 @@ pub fn setup(src_path: &Path, profile: Profile) {
103109

104110
let suggestions = match profile {
105111
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
112+
Profile::Tools => &[
113+
"check",
114+
"build",
115+
"test src/test/rustdoc*",
116+
"test src/tools/clippy",
117+
"test src/tools/miri",
118+
"test src/tools/rustfmt",
119+
],
106120
Profile::Library => &["check", "build", "test library/std", "doc"],
107121
Profile::User => &["dist", "build"],
108122
};

‎src/librustdoc/clean/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ impl Attributes {
914914
.collect()
915915
}
916916

917-
crate fn get_doc_aliases(&self) -> FxHashSet<String> {
917+
crate fn get_doc_aliases(&self) -> Box<[String]> {
918918
let mut aliases = FxHashSet::default();
919919

920920
for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
@@ -931,7 +931,7 @@ impl Attributes {
931931
aliases.insert(attr.value_str().map(|s| s.to_string()).unwrap());
932932
}
933933
}
934-
aliases
934+
aliases.into_iter().collect::<Vec<String>>().into()
935935
}
936936
}
937937

‎src/librustdoc/formats/cache.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,6 @@ crate struct Cache {
120120
// when gathering trait documentation on a type, hold impls here while
121121
// folding and add them to the cache later on if we find the trait.
122122
orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
123-
124-
/// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
125-
/// we need the alias element to have an array of items.
126-
crate aliases: BTreeMap<String, Vec<usize>>,
127123
}
128124

129125
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
@@ -309,15 +305,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
309305
parent,
310306
parent_idx: None,
311307
search_type: get_index_search_type(&item, &self.empty_cache, self.tcx),
308+
aliases: item.attrs.get_doc_aliases(),
312309
});
313-
314-
for alias in item.attrs.get_doc_aliases() {
315-
self.cache
316-
.aliases
317-
.entry(alias.to_lowercase())
318-
.or_insert(Vec::new())
319-
.push(self.cache.search_index.len() - 1);
320-
}
321310
}
322311
}
323312
(Some(parent), None) if is_inherent_impl_item => {

‎src/librustdoc/html/render/cache.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,31 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
8282
parent: Some(did),
8383
parent_idx: None,
8484
search_type: get_index_search_type(&item, cache, tcx),
85+
aliases: item.attrs.get_doc_aliases(),
8586
});
86-
for alias in item.attrs.get_doc_aliases() {
87-
cache
88-
.aliases
89-
.entry(alias.to_lowercase())
90-
.or_insert(Vec::new())
91-
.push(cache.search_index.len() - 1);
92-
}
9387
}
9488
}
9589

96-
let Cache { ref mut search_index, ref paths, ref mut aliases, .. } = *cache;
90+
let Cache { ref mut search_index, ref paths, .. } = *cache;
91+
92+
// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
93+
// we need the alias element to have an array of items.
94+
let mut aliases: BTreeMap<String, Vec<usize>> = BTreeMap::new();
95+
96+
// Sort search index items. This improves the compressibility of the search index.
97+
search_index.sort_unstable_by(|k1, k2| {
98+
// `sort_unstable_by_key` produces lifetime errors
99+
let k1 = (&k1.path, &k1.name, &k1.ty, &k1.parent);
100+
let k2 = (&k2.path, &k2.name, &k2.ty, &k2.parent);
101+
std::cmp::Ord::cmp(&k1, &k2)
102+
});
103+
104+
// Set up alias indexes.
105+
for (i, item) in search_index.iter().enumerate() {
106+
for alias in &item.aliases[..] {
107+
aliases.entry(alias.to_lowercase()).or_insert(Vec::new()).push(i);
108+
}
109+
}
97110

98111
// Reduce `DefId` in paths into smaller sequential numbers,
99112
// and prune the paths that do not appear in the index.
@@ -201,7 +214,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
201214
doc: crate_doc,
202215
items: crate_items,
203216
paths: crate_paths,
204-
aliases,
217+
aliases: &aliases,
205218
})
206219
.expect("failed serde conversion")
207220
// All these `replace` calls are because we have to go through JS string for JSON content.

‎src/librustdoc/html/render/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ crate struct IndexItem {
164164
crate parent: Option<DefId>,
165165
crate parent_idx: Option<usize>,
166166
crate search_type: Option<IndexItemFunctionType>,
167+
crate aliases: Box<[String]>,
167168
}
168169

169170
/// A type used for the search index.

‎src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 102 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -368,55 +368,28 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
368368
}
369369

370370
/// Given a primitive type, try to resolve an associated item.
371-
///
372-
/// HACK(jynelson): `item_str` is passed in instead of derived from `item_name` so the
373-
/// lifetimes on `&'path` will work.
374371
fn resolve_primitive_associated_item(
375372
&self,
376373
prim_ty: PrimitiveType,
377374
ns: Namespace,
378-
module_id: DefId,
379375
item_name: Symbol,
380-
item_str: &'path str,
381-
) -> Result<(Res, Option<String>), ErrorKind<'path>> {
376+
) -> Option<(Res, String, Option<(DefKind, DefId)>)> {
382377
let tcx = self.cx.tcx;
383378

384-
prim_ty
385-
.impls(tcx)
386-
.into_iter()
387-
.find_map(|&impl_| {
388-
tcx.associated_items(impl_)
389-
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
390-
.map(|item| {
391-
let kind = item.kind;
392-
self.kind_side_channel.set(Some((kind.as_def_kind(), item.def_id)));
393-
match kind {
394-
ty::AssocKind::Fn => "method",
395-
ty::AssocKind::Const => "associatedconstant",
396-
ty::AssocKind::Type => "associatedtype",
397-
}
398-
})
399-
.map(|out| {
400-
(
401-
Res::Primitive(prim_ty),
402-
Some(format!("{}#{}.{}", prim_ty.as_str(), out, item_str)),
403-
)
404-
})
405-
})
406-
.ok_or_else(|| {
407-
debug!(
408-
"returning primitive error for {}::{} in {} namespace",
409-
prim_ty.as_str(),
410-
item_name,
411-
ns.descr()
412-
);
413-
ResolutionFailure::NotResolved {
414-
module_id,
415-
partial_res: Some(Res::Primitive(prim_ty)),
416-
unresolved: item_str.into(),
417-
}
418-
.into()
419-
})
379+
prim_ty.impls(tcx).into_iter().find_map(|&impl_| {
380+
tcx.associated_items(impl_)
381+
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
382+
.map(|item| {
383+
let kind = item.kind;
384+
let out = match kind {
385+
ty::AssocKind::Fn => "method",
386+
ty::AssocKind::Const => "associatedconstant",
387+
ty::AssocKind::Type => "associatedtype",
388+
};
389+
let fragment = format!("{}#{}.{}", prim_ty.as_str(), out, item_name);
390+
(Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
391+
})
392+
})
420393
}
421394

422395
/// Resolves a string as a macro.
@@ -490,8 +463,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
490463
module_id: DefId,
491464
extra_fragment: &Option<String>,
492465
) -> Result<(Res, Option<String>), ErrorKind<'path>> {
493-
let tcx = self.cx.tcx;
494-
495466
if let Some(res) = self.resolve_path(path_str, ns, module_id) {
496467
match res {
497468
// FIXME(#76467): make this fallthrough to lookup the associated
@@ -534,29 +505,58 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
534505
}
535506
})?;
536507

537-
// FIXME: are these both necessary?
538-
let ty_res = if let Some(ty_res) = resolve_primitive(&path_root, TypeNS)
508+
// FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support
509+
// links to primitives when `#[doc(primitive)]` is present. It should give an ambiguity
510+
// error instead and special case *only* modules with `#[doc(primitive)]`, not all
511+
// primitives.
512+
resolve_primitive(&path_root, TypeNS)
539513
.or_else(|| self.resolve_path(&path_root, TypeNS, module_id))
540-
{
541-
ty_res
542-
} else {
543-
// FIXME: this is duplicated on the end of this function.
544-
return if ns == Namespace::ValueNS {
545-
self.variant_field(path_str, module_id)
546-
} else {
547-
Err(ResolutionFailure::NotResolved {
548-
module_id,
549-
partial_res: None,
550-
unresolved: path_root.into(),
514+
.and_then(|ty_res| {
515+
let (res, fragment, side_channel) =
516+
self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
517+
let result = if extra_fragment.is_some() {
518+
let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r));
519+
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res)))
520+
} else {
521+
// HACK(jynelson): `clean` expects the type, not the associated item
522+
// but the disambiguator logic expects the associated item.
523+
// Store the kind in a side channel so that only the disambiguator logic looks at it.
524+
if let Some((kind, id)) = side_channel {
525+
self.kind_side_channel.set(Some((kind, id)));
526+
}
527+
Ok((res, Some(fragment)))
528+
};
529+
Some(result)
530+
})
531+
.unwrap_or_else(|| {
532+
if ns == Namespace::ValueNS {
533+
self.variant_field(path_str, module_id)
534+
} else {
535+
Err(ResolutionFailure::NotResolved {
536+
module_id,
537+
partial_res: None,
538+
unresolved: path_root.into(),
539+
}
540+
.into())
551541
}
552-
.into())
553-
};
554-
};
542+
})
543+
}
544+
545+
/// Returns:
546+
/// - None if no associated item was found
547+
/// - Some((_, _, Some(_))) if an item was found and should go through a side channel
548+
/// - Some((_, _, None)) otherwise
549+
fn resolve_associated_item(
550+
&mut self,
551+
root_res: Res,
552+
item_name: Symbol,
553+
ns: Namespace,
554+
module_id: DefId,
555+
) -> Option<(Res, String, Option<(DefKind, DefId)>)> {
556+
let tcx = self.cx.tcx;
555557

556-
let res = match ty_res {
557-
Res::Primitive(prim) => Some(
558-
self.resolve_primitive_associated_item(prim, ns, module_id, item_name, item_str),
559-
),
558+
match root_res {
559+
Res::Primitive(prim) => self.resolve_primitive_associated_item(prim, ns, item_name),
560560
Res::Def(
561561
DefKind::Struct
562562
| DefKind::Union
@@ -599,59 +599,42 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
599599
ty::AssocKind::Const => "associatedconstant",
600600
ty::AssocKind::Type => "associatedtype",
601601
};
602-
Some(if extra_fragment.is_some() {
603-
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(ty_res)))
604-
} else {
605-
// HACK(jynelson): `clean` expects the type, not the associated item
606-
// but the disambiguator logic expects the associated item.
607-
// Store the kind in a side channel so that only the disambiguator logic looks at it.
608-
self.kind_side_channel.set(Some((kind.as_def_kind(), id)));
609-
Ok((ty_res, Some(format!("{}.{}", out, item_str))))
610-
})
611-
} else if ns == Namespace::ValueNS {
612-
debug!("looking for variants or fields named {} for {:?}", item_name, did);
613-
// FIXME(jynelson): why is this different from
614-
// `variant_field`?
615-
match tcx.type_of(did).kind() {
616-
ty::Adt(def, _) => {
617-
let field = if def.is_enum() {
618-
def.all_fields().find(|item| item.ident.name == item_name)
619-
} else {
620-
def.non_enum_variant()
621-
.fields
622-
.iter()
623-
.find(|item| item.ident.name == item_name)
624-
};
625-
field.map(|item| {
626-
if extra_fragment.is_some() {
627-
let res = Res::Def(
628-
if def.is_enum() {
629-
DefKind::Variant
630-
} else {
631-
DefKind::Field
632-
},
633-
item.did,
634-
);
635-
Err(ErrorKind::AnchorFailure(
636-
AnchorFailure::RustdocAnchorConflict(res),
637-
))
638-
} else {
639-
Ok((
640-
ty_res,
641-
Some(format!(
642-
"{}.{}",
643-
if def.is_enum() { "variant" } else { "structfield" },
644-
item.ident
645-
)),
646-
))
647-
}
648-
})
649-
}
650-
_ => None,
651-
}
652-
} else {
653-
None
602+
// HACK(jynelson): `clean` expects the type, not the associated item
603+
// but the disambiguator logic expects the associated item.
604+
// Store the kind in a side channel so that only the disambiguator logic looks at it.
605+
return Some((
606+
root_res,
607+
format!("{}.{}", out, item_name),
608+
Some((kind.as_def_kind(), id)),
609+
));
610+
}
611+
612+
if ns != Namespace::ValueNS {
613+
return None;
654614
}
615+
debug!("looking for variants or fields named {} for {:?}", item_name, did);
616+
// FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
617+
// NOTE: it's different from variant_field because it resolves fields and variants,
618+
// not variant fields (2 path segments, not 3).
619+
let def = match tcx.type_of(did).kind() {
620+
ty::Adt(def, _) => def,
621+
_ => return None,
622+
};
623+
let field = if def.is_enum() {
624+
def.all_fields().find(|item| item.ident.name == item_name)
625+
} else {
626+
def.non_enum_variant().fields.iter().find(|item| item.ident.name == item_name)
627+
}?;
628+
let kind = if def.is_enum() { DefKind::Variant } else { DefKind::Field };
629+
Some((
630+
root_res,
631+
format!(
632+
"{}.{}",
633+
if def.is_enum() { "variant" } else { "structfield" },
634+
field.ident
635+
),
636+
Some((kind, field.did)),
637+
))
655638
}
656639
Res::Def(DefKind::Trait, did) => tcx
657640
.associated_items(did)
@@ -669,27 +652,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
669652
}
670653
};
671654

672-
if extra_fragment.is_some() {
673-
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(ty_res)))
674-
} else {
675-
let res = Res::Def(item.kind.as_def_kind(), item.def_id);
676-
Ok((res, Some(format!("{}.{}", kind, item_str))))
677-
}
655+
let res = Res::Def(item.kind.as_def_kind(), item.def_id);
656+
(res, format!("{}.{}", kind, item_name), None)
678657
}),
679658
_ => None,
680-
};
681-
res.unwrap_or_else(|| {
682-
if ns == Namespace::ValueNS {
683-
self.variant_field(path_str, module_id)
684-
} else {
685-
Err(ResolutionFailure::NotResolved {
686-
module_id,
687-
partial_res: Some(ty_res),
688-
unresolved: item_str.into(),
689-
}
690-
.into())
691-
}
692-
})
659+
}
693660
}
694661

695662
/// Used for reporting better errors.
Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
warning: public documentation for `DocMe` links to private item `DontDocMe`
2-
--> $DIR/private.rs:5:11
2+
--> $DIR/private.rs:7:11
33
|
4-
LL | /// docs [DontDocMe] [DontDocMe::f]
4+
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
55
| ^^^^^^^^^ this item is private
66
|
77
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
88
= note: this link resolves only because you passed `--document-private-items`, but will break without
99

1010
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
11-
--> $DIR/private.rs:5:23
11+
--> $DIR/private.rs:7:23
1212
|
13-
LL | /// docs [DontDocMe] [DontDocMe::f]
13+
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
1414
| ^^^^^^^^^^^^ this item is private
1515
|
1616
= note: this link resolves only because you passed `--document-private-items`, but will break without
1717

18-
warning: 2 warnings emitted
18+
warning: public documentation for `DocMe` links to private item `DontDocMe::x`
19+
--> $DIR/private.rs:7:38
20+
|
21+
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
22+
| ^^^^^^^^^^^^ this item is private
23+
|
24+
= note: this link resolves only because you passed `--document-private-items`, but will break without
25+
26+
warning: 3 warnings emitted
1927

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
warning: public documentation for `DocMe` links to private item `DontDocMe`
2-
--> $DIR/private.rs:5:11
2+
--> $DIR/private.rs:7:11
33
|
4-
LL | /// docs [DontDocMe] [DontDocMe::f]
4+
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
55
| ^^^^^^^^^ this item is private
66
|
77
= note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
88
= note: this link will resolve properly if you pass `--document-private-items`
99

1010
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
11-
--> $DIR/private.rs:5:23
11+
--> $DIR/private.rs:7:23
1212
|
13-
LL | /// docs [DontDocMe] [DontDocMe::f]
13+
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
1414
| ^^^^^^^^^^^^ this item is private
1515
|
1616
= note: this link will resolve properly if you pass `--document-private-items`
1717

18-
warning: 2 warnings emitted
18+
warning: public documentation for `DocMe` links to private item `DontDocMe::x`
19+
--> $DIR/private.rs:7:38
20+
|
21+
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
22+
| ^^^^^^^^^^^^ this item is private
23+
|
24+
= note: this link will resolve properly if you pass `--document-private-items`
25+
26+
warning: 3 warnings emitted
1927

‎src/test/rustdoc-ui/intra-doc/private.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
// revisions: public private
33
// [private]compile-flags: --document-private-items
44

5-
/// docs [DontDocMe] [DontDocMe::f]
5+
// make sure to update `rustdoc/intra-doc/private.rs` if you update this file
6+
7+
/// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
68
//~^ WARNING public documentation for `DocMe` links to private item `DontDocMe`
9+
//~| WARNING public documentation for `DocMe` links to private item `DontDocMe::x`
710
//~| WARNING public documentation for `DocMe` links to private item `DontDocMe::f`
8-
// FIXME: for [private] we should also make sure the link was actually generated
911
pub struct DocMe;
10-
struct DontDocMe;
12+
struct DontDocMe {
13+
x: usize,
14+
}
1115

1216
impl DontDocMe {
1317
fn f() {}

‎src/test/rustdoc/intra-doc/private.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
#![crate_name = "private"]
22
// compile-flags: --document-private-items
3-
/// docs [DontDocMe]
3+
4+
// make sure to update `rustdoc-ui/intra-doc/private.rs` if you update this file
5+
6+
/// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
47
// @has private/struct.DocMe.html '//*a[@href="../private/struct.DontDocMe.html"]' 'DontDocMe'
8+
// @has private/struct.DocMe.html '//*a[@href="../private/struct.DontDocMe.html#method.f"]' 'DontDocMe::f'
9+
// @has private/struct.DocMe.html '//*a[@href="../private/struct.DontDocMe.html#structfield.x"]' 'DontDocMe::x'
510
pub struct DocMe;
6-
struct DontDocMe;
11+
struct DontDocMe {
12+
x: usize,
13+
}
14+
15+
impl DontDocMe {
16+
fn f() {}
17+
}

‎src/test/ui/deref-suggestion.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,30 @@ fn main() {
4545
//~^ ERROR mismatched types
4646
let r = R { i: i };
4747
//~^ ERROR mismatched types
48+
49+
50+
let a = &1;
51+
let b = &2;
52+
let val: i32 = if true {
53+
a + 1
54+
} else {
55+
b
56+
//~^ ERROR mismatched types
57+
};
58+
let val: i32 = if true {
59+
let _ = 2;
60+
a + 1
61+
} else {
62+
let _ = 2;
63+
b
64+
//~^ ERROR mismatched types
65+
};
66+
let val = if true {
67+
*a
68+
} else if true {
69+
//~^ ERROR incompatible types
70+
b
71+
} else {
72+
&0
73+
};
4874
}

‎src/test/ui/deref-suggestion.stderr

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,43 @@ LL | let r = R { i: i };
8989
| expected `u32`, found `&{integer}`
9090
| help: consider dereferencing the borrow: `*i`
9191

92-
error: aborting due to 10 previous errors
92+
error[E0308]: mismatched types
93+
--> $DIR/deref-suggestion.rs:55:9
94+
|
95+
LL | b
96+
| ^
97+
| |
98+
| expected `i32`, found `&{integer}`
99+
| help: consider dereferencing the borrow: `*b`
100+
101+
error[E0308]: mismatched types
102+
--> $DIR/deref-suggestion.rs:63:9
103+
|
104+
LL | b
105+
| ^
106+
| |
107+
| expected `i32`, found `&{integer}`
108+
| help: consider dereferencing the borrow: `*b`
109+
110+
error[E0308]: `if` and `else` have incompatible types
111+
--> $DIR/deref-suggestion.rs:68:12
112+
|
113+
LL | let val = if true {
114+
| _______________-
115+
LL | | *a
116+
| | -- expected because of this
117+
LL | | } else if true {
118+
| |____________^
119+
LL | ||
120+
LL | || b
121+
LL | || } else {
122+
LL | || &0
123+
LL | || };
124+
| || ^
125+
| ||_____|
126+
| |______`if` and `else` have incompatible types
127+
| expected `i32`, found `&{integer}`
128+
129+
error: aborting due to 13 previous errors
93130

94131
For more information about this error, try `rustc --explain E0308`.

‎src/test/ui/macros/attr-empty-expr.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// AST-based macro attributes expanding to an empty expression produce an error and not ICE.
2+
3+
#![feature(custom_test_frameworks)]
4+
#![feature(stmt_expr_attributes)]
5+
#![feature(test)]
6+
7+
fn main() {
8+
let _ = #[test] 0; //~ ERROR removing an expression is not supported in this position
9+
let _ = #[bench] 1; //~ ERROR removing an expression is not supported in this position
10+
let _ = #[test_case] 2; //~ ERROR removing an expression is not supported in this position
11+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: removing an expression is not supported in this position
2+
--> $DIR/attr-empty-expr.rs:8:13
3+
|
4+
LL | let _ = #[test] 0;
5+
| ^^^^^^^
6+
7+
error: removing an expression is not supported in this position
8+
--> $DIR/attr-empty-expr.rs:9:13
9+
|
10+
LL | let _ = #[bench] 1;
11+
| ^^^^^^^^
12+
13+
error: removing an expression is not supported in this position
14+
--> $DIR/attr-empty-expr.rs:10:13
15+
|
16+
LL | let _ = #[test_case] 2;
17+
| ^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
20+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Regression test for #83621.
2+
3+
extern "C" {
4+
static x: _; //~ ERROR: [E0121]
5+
}
6+
7+
fn main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
2+
--> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15
3+
|
4+
LL | static x: _;
5+
| ^ not allowed in type signatures
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0121`.

‎src/tools/rust-analyzer

0 commit comments

Comments
 (0)
Please sign in to comment.