Special case ambiguity_error if all candidates have the same "kind"

This commit is contained in:
Guillaume Gomez 2023-03-14 15:06:27 +01:00
parent e9817385f4
commit e193950c3c

View File

@ -1016,7 +1016,7 @@ impl LinkCollector<'_, '_> {
} else { } else {
// `[char]` when a `char` module is in scope // `[char]` when a `char` module is in scope
let candidates = vec![(res, res.def_id(self.cx.tcx)), (prim, None)]; let candidates = vec![(res, res.def_id(self.cx.tcx)), (prim, None)];
ambiguity_error(self.cx, diag_info, path_str, candidates); ambiguity_error(self.cx, &diag_info, path_str, &candidates);
return None; return None;
} }
} }
@ -1206,6 +1206,10 @@ impl LinkCollector<'_, '_> {
} }
} }
if candidates.len() > 1 && !ambiguity_error(self.cx, &diag, &key.path_str, &candidates) {
candidates = vec![candidates[0]];
}
if let &[(res, def_id)] = candidates.as_slice() { if let &[(res, def_id)] = candidates.as_slice() {
let fragment = match (&key.extra_fragment, def_id) { let fragment = match (&key.extra_fragment, def_id) {
(Some(_), Some(def_id)) => { (Some(_), Some(def_id)) => {
@ -1221,9 +1225,6 @@ impl LinkCollector<'_, '_> {
return r; return r;
} }
if !candidates.is_empty() {
ambiguity_error(self.cx, diag, &key.path_str, candidates);
}
if cache_errors { if cache_errors {
self.visited_links.insert(key, None); self.visited_links.insert(key, None);
} }
@ -1898,21 +1899,30 @@ fn report_malformed_generics(
} }
/// Report an ambiguity error, where there were multiple possible resolutions. /// Report an ambiguity error, where there were multiple possible resolutions.
///
/// If all `candidates` have the same kind, it's not possible to disambiguate so in this case,
/// the function returns `false`. Otherwise, it'll emit the error and return `true`.
fn ambiguity_error( fn ambiguity_error(
cx: &DocContext<'_>, cx: &DocContext<'_>,
diag_info: DiagnosticInfo<'_>, diag_info: &DiagnosticInfo<'_>,
path_str: &str, path_str: &str,
candidates: Vec<(Res, Option<DefId>)>, candidates: &[(Res, Option<DefId>)],
) { ) -> bool {
let mut msg = format!("`{}` is ", path_str); let mut msg = format!("`{}` is ", path_str);
let kinds = candidates let kinds = candidates
.into_iter() .iter()
.map( .map(
|(res, def_id)| { |(res, def_id)| {
if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, def_id) } else { res } if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res }
}, },
) )
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let descrs = kinds.iter().map(|res| res.descr()).collect::<FxHashSet<&'static str>>();
if descrs.len() == 1 {
// There is no way for users to disambiguate at this point, so better return the first
// candidate and not show a warning.
return false;
}
match kinds.as_slice() { match kinds.as_slice() {
[res1, res2] => { [res1, res2] => {
@ -1936,7 +1946,7 @@ fn ambiguity_error(
} }
} }
report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, |diag, sp| { report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
if let Some(sp) = sp { if let Some(sp) = sp {
diag.span_label(sp, "ambiguous link"); diag.span_label(sp, "ambiguous link");
} else { } else {
@ -1947,6 +1957,7 @@ fn ambiguity_error(
suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp); suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
} }
}); });
true
} }
/// In case of an ambiguity or mismatched disambiguator, suggest the correct /// In case of an ambiguity or mismatched disambiguator, suggest the correct