Review suggestions
This commit is contained in:
parent
850437b6f9
commit
cc31b992b1
1 changed files with 87 additions and 79 deletions
|
@ -169,22 +169,18 @@ enum AnchorFailure {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
struct CacheKey {
|
struct ResolutionInfo {
|
||||||
module_id: DefId,
|
module_id: DefId,
|
||||||
dis: Option<Disambiguator>,
|
dis: Option<Disambiguator>,
|
||||||
path_str: String,
|
path_str: String,
|
||||||
extra_fragment: Option<String>,
|
extra_fragment: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CacheKey {
|
struct DiagnosticInfo<'a> {
|
||||||
fn new(
|
item: &'a Item,
|
||||||
module_id: DefId,
|
dox: &'a str,
|
||||||
dis: Option<Disambiguator>,
|
ori_link: &'a str,
|
||||||
path_str: String,
|
link_range: Option<Range<usize>>,
|
||||||
extra_fragment: Option<String>,
|
|
||||||
) -> Self {
|
|
||||||
Self { module_id, dis, path_str, extra_fragment }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash)]
|
#[derive(Clone, Debug, Hash)]
|
||||||
|
@ -205,7 +201,7 @@ struct LinkCollector<'a, 'tcx> {
|
||||||
/// See the code for associated items on inherent impls for details.
|
/// See the code for associated items on inherent impls for details.
|
||||||
kind_side_channel: Cell<Option<(DefKind, DefId)>>,
|
kind_side_channel: Cell<Option<(DefKind, DefId)>>,
|
||||||
/// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link
|
/// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link
|
||||||
visited_links: FxHashMap<CacheKey, CachedLink>,
|
visited_links: FxHashMap<ResolutionInfo, CachedLink>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
||||||
|
@ -1108,9 +1104,15 @@ impl LinkCollector<'_, '_> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = CacheKey::new(module_id, disambiguator, path_str.to_owned(), extra_fragment);
|
let key = ResolutionInfo {
|
||||||
let (mut res, mut fragment) =
|
module_id,
|
||||||
self.resolve_with_disambiguator_cached(key, item, dox, &ori_link, link_range.clone())?;
|
dis: disambiguator,
|
||||||
|
path_str: path_str.to_owned(),
|
||||||
|
extra_fragment,
|
||||||
|
};
|
||||||
|
let diag =
|
||||||
|
DiagnosticInfo { item, dox, ori_link: &ori_link, link_range: link_range.clone() };
|
||||||
|
let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(key, diag)?;
|
||||||
|
|
||||||
// Check for a primitive which might conflict with a module
|
// Check for a primitive which might conflict with a module
|
||||||
// Report the ambiguity and require that the user specify which one they meant.
|
// Report the ambiguity and require that the user specify which one they meant.
|
||||||
|
@ -1220,28 +1222,19 @@ impl LinkCollector<'_, '_> {
|
||||||
|
|
||||||
fn resolve_with_disambiguator_cached(
|
fn resolve_with_disambiguator_cached(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: CacheKey,
|
key: ResolutionInfo,
|
||||||
item: &Item,
|
diag: DiagnosticInfo<'_>,
|
||||||
dox: &str,
|
|
||||||
ori_link: &str,
|
|
||||||
link_range: Option<Range<usize>>,
|
|
||||||
) -> Option<(Res, Option<String>)> {
|
) -> Option<(Res, Option<String>)> {
|
||||||
// Try to look up both the result and the corresponding side channel value
|
// Try to look up both the result and the corresponding side channel value
|
||||||
if let Some(ref cached) = self.visited_links.get(&key) {
|
if let Some(ref cached) = self.visited_links.get(&key) {
|
||||||
self.kind_side_channel.set(cached.side_channel.clone());
|
self.kind_side_channel.set(cached.side_channel.clone());
|
||||||
Some(cached.res.clone())
|
return Some(cached.res.clone());
|
||||||
} else {
|
}
|
||||||
match self.resolve_with_disambiguator(
|
|
||||||
key.dis,
|
let res = self.resolve_with_disambiguator(&key, diag);
|
||||||
item,
|
|
||||||
dox,
|
// Cache only if resolved successfully - don't silence duplicate errors
|
||||||
&key.path_str,
|
if let Some(res) = &res {
|
||||||
key.module_id,
|
|
||||||
key.extra_fragment.clone(),
|
|
||||||
ori_link,
|
|
||||||
link_range,
|
|
||||||
) {
|
|
||||||
Some(res) => {
|
|
||||||
// Store result for the actual namespace
|
// Store result for the actual namespace
|
||||||
self.visited_links.insert(
|
self.visited_links.insert(
|
||||||
key,
|
key,
|
||||||
|
@ -1250,29 +1243,26 @@ impl LinkCollector<'_, '_> {
|
||||||
side_channel: self.kind_side_channel.clone().into_inner(),
|
side_channel: self.kind_side_channel.clone().into_inner(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Some(res)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// After parsing the disambiguator, resolve the main part of the link.
|
/// After parsing the disambiguator, resolve the main part of the link.
|
||||||
// FIXME(jynelson): wow this is just so much
|
// FIXME(jynelson): wow this is just so much
|
||||||
fn resolve_with_disambiguator(
|
fn resolve_with_disambiguator(
|
||||||
&self,
|
&self,
|
||||||
disambiguator: Option<Disambiguator>,
|
key: &ResolutionInfo,
|
||||||
item: &Item,
|
diag: DiagnosticInfo<'_>,
|
||||||
dox: &str,
|
|
||||||
path_str: &str,
|
|
||||||
base_node: DefId,
|
|
||||||
extra_fragment: Option<String>,
|
|
||||||
ori_link: &str,
|
|
||||||
link_range: Option<Range<usize>>,
|
|
||||||
) -> Option<(Res, Option<String>)> {
|
) -> Option<(Res, Option<String>)> {
|
||||||
|
let disambiguator = key.dis;
|
||||||
|
let path_str = &key.path_str;
|
||||||
|
let base_node = key.module_id;
|
||||||
|
let extra_fragment = &key.extra_fragment;
|
||||||
|
|
||||||
match disambiguator.map(Disambiguator::ns) {
|
match disambiguator.map(Disambiguator::ns) {
|
||||||
Some(ns @ (ValueNS | TypeNS)) => {
|
Some(ns @ (ValueNS | TypeNS)) => {
|
||||||
match self.resolve(path_str, ns, base_node, &extra_fragment) {
|
match self.resolve(path_str, ns, base_node, extra_fragment) {
|
||||||
Ok(res) => Some(res),
|
Ok(res) => Some(res),
|
||||||
Err(ErrorKind::Resolve(box mut kind)) => {
|
Err(ErrorKind::Resolve(box mut kind)) => {
|
||||||
// We only looked in one namespace. Try to give a better error if possible.
|
// We only looked in one namespace. Try to give a better error if possible.
|
||||||
|
@ -1281,12 +1271,9 @@ impl LinkCollector<'_, '_> {
|
||||||
// FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`
|
// FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`
|
||||||
// See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach
|
// See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach
|
||||||
for &new_ns in &[other_ns, MacroNS] {
|
for &new_ns in &[other_ns, MacroNS] {
|
||||||
if let Some(res) = self.check_full_res(
|
if let Some(res) =
|
||||||
new_ns,
|
self.check_full_res(new_ns, path_str, base_node, extra_fragment)
|
||||||
path_str,
|
{
|
||||||
base_node,
|
|
||||||
&extra_fragment,
|
|
||||||
) {
|
|
||||||
kind = ResolutionFailure::WrongNamespace(res, ns);
|
kind = ResolutionFailure::WrongNamespace(res, ns);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1294,11 +1281,11 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
resolution_failure(
|
resolution_failure(
|
||||||
self,
|
self,
|
||||||
&item,
|
diag.item,
|
||||||
path_str,
|
path_str,
|
||||||
disambiguator,
|
disambiguator,
|
||||||
dox,
|
diag.dox,
|
||||||
link_range,
|
diag.link_range,
|
||||||
smallvec![kind],
|
smallvec![kind],
|
||||||
);
|
);
|
||||||
// This could just be a normal link or a broken link
|
// This could just be a normal link or a broken link
|
||||||
|
@ -1307,7 +1294,14 @@ impl LinkCollector<'_, '_> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||||
anchor_failure(self.cx, &item, &ori_link, dox, link_range, msg);
|
anchor_failure(
|
||||||
|
self.cx,
|
||||||
|
diag.item,
|
||||||
|
diag.ori_link,
|
||||||
|
diag.dox,
|
||||||
|
diag.link_range,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1318,21 +1312,35 @@ impl LinkCollector<'_, '_> {
|
||||||
macro_ns: self
|
macro_ns: self
|
||||||
.resolve_macro(path_str, base_node)
|
.resolve_macro(path_str, base_node)
|
||||||
.map(|res| (res, extra_fragment.clone())),
|
.map(|res| (res, extra_fragment.clone())),
|
||||||
type_ns: match self.resolve(path_str, TypeNS, base_node, &extra_fragment) {
|
type_ns: match self.resolve(path_str, TypeNS, base_node, extra_fragment) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
debug!("got res in TypeNS: {:?}", res);
|
debug!("got res in TypeNS: {:?}", res);
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||||
anchor_failure(self.cx, &item, ori_link, dox, link_range, msg);
|
anchor_failure(
|
||||||
|
self.cx,
|
||||||
|
diag.item,
|
||||||
|
diag.ori_link,
|
||||||
|
diag.dox,
|
||||||
|
diag.link_range,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
||||||
},
|
},
|
||||||
value_ns: match self.resolve(path_str, ValueNS, base_node, &extra_fragment) {
|
value_ns: match self.resolve(path_str, ValueNS, base_node, extra_fragment) {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(ErrorKind::AnchorFailure(msg)) => {
|
Err(ErrorKind::AnchorFailure(msg)) => {
|
||||||
anchor_failure(self.cx, &item, ori_link, dox, link_range, msg);
|
anchor_failure(
|
||||||
|
self.cx,
|
||||||
|
diag.item,
|
||||||
|
diag.ori_link,
|
||||||
|
diag.dox,
|
||||||
|
diag.link_range,
|
||||||
|
msg,
|
||||||
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
Err(ErrorKind::Resolve(box kind)) => Err(kind),
|
||||||
|
@ -1343,7 +1351,7 @@ impl LinkCollector<'_, '_> {
|
||||||
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => {
|
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => {
|
||||||
Err(ResolutionFailure::WrongNamespace(res, TypeNS))
|
Err(ResolutionFailure::WrongNamespace(res, TypeNS))
|
||||||
}
|
}
|
||||||
_ => match (fragment, extra_fragment) {
|
_ => match (fragment, extra_fragment.clone()) {
|
||||||
(Some(fragment), Some(_)) => {
|
(Some(fragment), Some(_)) => {
|
||||||
// Shouldn't happen but who knows?
|
// Shouldn't happen but who knows?
|
||||||
Ok((res, Some(fragment)))
|
Ok((res, Some(fragment)))
|
||||||
|
@ -1359,11 +1367,11 @@ impl LinkCollector<'_, '_> {
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
resolution_failure(
|
resolution_failure(
|
||||||
self,
|
self,
|
||||||
&item,
|
diag.item,
|
||||||
path_str,
|
path_str,
|
||||||
disambiguator,
|
disambiguator,
|
||||||
dox,
|
diag.dox,
|
||||||
link_range,
|
diag.link_range,
|
||||||
candidates.into_iter().filter_map(|res| res.err()).collect(),
|
candidates.into_iter().filter_map(|res| res.err()).collect(),
|
||||||
);
|
);
|
||||||
// this could just be a normal link
|
// this could just be a normal link
|
||||||
|
@ -1382,10 +1390,10 @@ impl LinkCollector<'_, '_> {
|
||||||
let candidates = candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
|
let candidates = candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
|
||||||
ambiguity_error(
|
ambiguity_error(
|
||||||
self.cx,
|
self.cx,
|
||||||
&item,
|
diag.item,
|
||||||
path_str,
|
path_str,
|
||||||
dox,
|
diag.dox,
|
||||||
link_range,
|
diag.link_range,
|
||||||
candidates.present_items().collect(),
|
candidates.present_items().collect(),
|
||||||
);
|
);
|
||||||
return None;
|
return None;
|
||||||
|
@ -1393,12 +1401,12 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
Some(MacroNS) => {
|
Some(MacroNS) => {
|
||||||
match self.resolve_macro(path_str, base_node) {
|
match self.resolve_macro(path_str, base_node) {
|
||||||
Ok(res) => Some((res, extra_fragment)),
|
Ok(res) => Some((res, extra_fragment.clone())),
|
||||||
Err(mut kind) => {
|
Err(mut kind) => {
|
||||||
// `resolve_macro` only looks in the macro namespace. Try to give a better error if possible.
|
// `resolve_macro` only looks in the macro namespace. Try to give a better error if possible.
|
||||||
for &ns in &[TypeNS, ValueNS] {
|
for &ns in &[TypeNS, ValueNS] {
|
||||||
if let Some(res) =
|
if let Some(res) =
|
||||||
self.check_full_res(ns, path_str, base_node, &extra_fragment)
|
self.check_full_res(ns, path_str, base_node, extra_fragment)
|
||||||
{
|
{
|
||||||
kind = ResolutionFailure::WrongNamespace(res, MacroNS);
|
kind = ResolutionFailure::WrongNamespace(res, MacroNS);
|
||||||
break;
|
break;
|
||||||
|
@ -1406,11 +1414,11 @@ impl LinkCollector<'_, '_> {
|
||||||
}
|
}
|
||||||
resolution_failure(
|
resolution_failure(
|
||||||
self,
|
self,
|
||||||
&item,
|
diag.item,
|
||||||
path_str,
|
path_str,
|
||||||
disambiguator,
|
disambiguator,
|
||||||
dox,
|
diag.dox,
|
||||||
link_range,
|
diag.link_range,
|
||||||
smallvec![kind],
|
smallvec![kind],
|
||||||
);
|
);
|
||||||
return None;
|
return None;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue