1
Fork 0

Review suggestions

This commit is contained in:
Dániel Buga 2020-11-30 23:16:50 +01:00
parent 850437b6f9
commit cc31b992b1

View file

@ -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;