Skip to content

Commit a5fbfab

Browse files
bugadaniJoshua Nelson
and
Joshua Nelson
committed
Refactor path resolution and use Symbols instead of &str
Co-authored-by: Joshua Nelson <[email protected]>
1 parent 3858c0f commit a5fbfab

File tree

2 files changed

+136
-115
lines changed

2 files changed

+136
-115
lines changed

src/librustdoc/clean/types.rs

+23
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::{slice, vec};
1212
use rustc_ast::attr;
1313
use rustc_ast::util::comments::beautify_doc_string;
1414
use rustc_ast::{self as ast, AttrStyle};
15+
use rustc_ast::{FloatTy, IntTy, UintTy};
1516
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1617
use rustc_hir as hir;
1718
use rustc_hir::def::Res;
@@ -1279,6 +1280,28 @@ impl GetDefId for Type {
12791280
}
12801281

12811282
impl PrimitiveType {
1283+
pub fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
1284+
match prim {
1285+
hir::PrimTy::Int(IntTy::Isize) => PrimitiveType::Isize,
1286+
hir::PrimTy::Int(IntTy::I8) => PrimitiveType::I8,
1287+
hir::PrimTy::Int(IntTy::I16) => PrimitiveType::I16,
1288+
hir::PrimTy::Int(IntTy::I32) => PrimitiveType::I32,
1289+
hir::PrimTy::Int(IntTy::I64) => PrimitiveType::I64,
1290+
hir::PrimTy::Int(IntTy::I128) => PrimitiveType::I128,
1291+
hir::PrimTy::Uint(UintTy::Usize) => PrimitiveType::Usize,
1292+
hir::PrimTy::Uint(UintTy::U8) => PrimitiveType::U8,
1293+
hir::PrimTy::Uint(UintTy::U16) => PrimitiveType::U16,
1294+
hir::PrimTy::Uint(UintTy::U32) => PrimitiveType::U32,
1295+
hir::PrimTy::Uint(UintTy::U64) => PrimitiveType::U64,
1296+
hir::PrimTy::Uint(UintTy::U128) => PrimitiveType::U128,
1297+
hir::PrimTy::Float(FloatTy::F32) => PrimitiveType::F32,
1298+
hir::PrimTy::Float(FloatTy::F64) => PrimitiveType::F64,
1299+
hir::PrimTy::Str => PrimitiveType::Str,
1300+
hir::PrimTy::Bool => PrimitiveType::Bool,
1301+
hir::PrimTy::Char => PrimitiveType::Char,
1302+
}
1303+
}
1304+
12821305
pub fn from_symbol(s: Symbol) -> Option<PrimitiveType> {
12831306
match s {
12841307
sym::isize => Some(PrimitiveType::Isize),

src/librustdoc/passes/collect_intra_doc_links.rs

+113-115
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_session::lint::{
1616
Lint,
1717
};
1818
use rustc_span::hygiene::MacroKind;
19+
use rustc_span::symbol::sym;
1920
use rustc_span::symbol::Ident;
2021
use rustc_span::symbol::Symbol;
2122
use rustc_span::DUMMY_SP;
@@ -234,6 +235,52 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
234235
}
235236
}
236237

238+
fn resolve_primitive_associated_item(
239+
&self,
240+
prim_ty: hir::PrimTy,
241+
prim: Res,
242+
ns: Namespace,
243+
module_id: DefId,
244+
item_name: Symbol,
245+
item_str: &'path str,
246+
) -> Result<(Res, Option<String>), ErrorKind<'path>> {
247+
let cx = self.cx;
248+
249+
PrimitiveType::from_hir(prim_ty)
250+
.impls(cx.tcx)
251+
.into_iter()
252+
.find_map(|&impl_| {
253+
cx.tcx
254+
.associated_items(impl_)
255+
.find_by_name_and_namespace(
256+
cx.tcx,
257+
Ident::with_dummy_span(item_name),
258+
ns,
259+
impl_,
260+
)
261+
.map(|item| match item.kind {
262+
ty::AssocKind::Fn => "method",
263+
ty::AssocKind::Const => "associatedconstant",
264+
ty::AssocKind::Type => "associatedtype",
265+
})
266+
.map(|out| (prim, Some(format!("{}#{}.{}", prim_ty.name(), out, item_str))))
267+
})
268+
.ok_or_else(|| {
269+
debug!(
270+
"returning primitive error for {}::{} in {} namespace",
271+
prim_ty.name(),
272+
item_name,
273+
ns.descr()
274+
);
275+
ResolutionFailure::NotResolved {
276+
module_id,
277+
partial_res: Some(prim),
278+
unresolved: item_str.into(),
279+
}
280+
.into()
281+
})
282+
}
283+
237284
/// Resolves a string as a macro.
238285
fn macro_resolve(
239286
&self,
@@ -275,6 +322,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
275322
})
276323
}
277324

325+
fn resolve_path(&self, path_str: &str, ns: Namespace, module_id: DefId) -> Option<Res> {
326+
let result = self.cx.enter_resolver(|resolver| {
327+
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
328+
});
329+
debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
330+
match result.map(|(_, res)| res) {
331+
Ok(Res::Err) | Err(()) => is_bool_value(path_str, ns).map(|(_, res)| res),
332+
333+
// resolver doesn't know about true and false so we'll have to resolve them
334+
// manually as bool
335+
Ok(res) => Some(res.map_id(|_| panic!("unexpected node_id"))),
336+
}
337+
}
338+
278339
/// Resolves a string as a path within a particular namespace. Also returns an optional
279340
/// URL fragment in the case of variants and methods.
280341
fn resolve<'path>(
@@ -287,32 +348,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
287348
) -> Result<(Res, Option<String>), ErrorKind<'path>> {
288349
let cx = self.cx;
289350

290-
let result = cx.enter_resolver(|resolver| {
291-
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
292-
});
293-
debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
294-
let result = match result.map(|(_, res)| res) {
295-
Ok(Res::Err) | Err(()) => {
296-
// resolver doesn't know about true and false so we'll have to resolve them
297-
// manually as bool
298-
if let Some((_, res)) = is_bool_value(path_str, ns) { Ok(res) } else { Err(()) }
299-
}
300-
Ok(res) => Ok(res.map_id(|_| panic!("unexpected node_id"))),
301-
};
302-
303-
if let Ok(res) = result {
351+
if let Some(res) = self.resolve_path(path_str, ns, module_id) {
304352
match res {
305353
Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => {
306-
if ns != ValueNS {
307-
return Err(ResolutionFailure::WrongNamespace(res, ns).into());
308-
}
354+
assert_eq!(ns, ValueNS);
309355
// Fall through: In case this is a trait item, skip the
310356
// early return and try looking for the trait.
311357
}
312358
Res::Def(DefKind::AssocTy, _) => {
313-
if ns != TypeNS {
314-
return Err(ResolutionFailure::WrongNamespace(res, ns).into());
315-
}
359+
assert_eq!(ns, TypeNS);
316360
// Fall through: In case this is a trait item, skip the
317361
// early return and try looking for the trait.
318362
}
@@ -362,70 +406,29 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
362406
}
363407
})?;
364408

365-
if let Some((path, prim)) = is_primitive(&path_root, TypeNS) {
366-
let impls =
367-
primitive_impl(cx, &path).ok_or_else(|| ResolutionFailure::NotResolved {
409+
let ty_res = if let Some(ty_res) = is_primitive(&path_root, TypeNS)
410+
.map(|(_, res)| res)
411+
.or_else(|| self.resolve_path(&path_root, TypeNS, module_id))
412+
{
413+
ty_res
414+
} else {
415+
// FIXME: this is duplicated on the end of this function.
416+
return if ns == Namespace::ValueNS {
417+
self.variant_field(path_str, current_item, module_id)
418+
} else {
419+
Err(ResolutionFailure::NotResolved {
368420
module_id,
369-
partial_res: Some(prim),
370-
unresolved: item_str.into(),
371-
})?;
372-
for &impl_ in impls {
373-
let link = cx
374-
.tcx
375-
.associated_items(impl_)
376-
.find_by_name_and_namespace(
377-
cx.tcx,
378-
Ident::with_dummy_span(item_name),
379-
ns,
380-
impl_,
381-
)
382-
.map(|item| match item.kind {
383-
ty::AssocKind::Fn => "method",
384-
ty::AssocKind::Const => "associatedconstant",
385-
ty::AssocKind::Type => "associatedtype",
386-
})
387-
.map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_str))));
388-
if let Some(link) = link {
389-
return Ok(link);
421+
partial_res: None,
422+
unresolved: path_root.into(),
390423
}
391-
}
392-
debug!(
393-
"returning primitive error for {}::{} in {} namespace",
394-
path,
395-
item_name,
396-
ns.descr()
397-
);
398-
return Err(ResolutionFailure::NotResolved {
399-
module_id,
400-
partial_res: Some(prim),
401-
unresolved: item_str.into(),
402-
}
403-
.into());
404-
}
405-
406-
let ty_res = cx
407-
.enter_resolver(|resolver| {
408-
// only types can have associated items
409-
resolver.resolve_str_path_error(DUMMY_SP, &path_root, TypeNS, module_id)
410-
})
411-
.map(|(_, res)| res);
412-
let ty_res = match ty_res {
413-
Err(()) | Ok(Res::Err) => {
414-
return if ns == Namespace::ValueNS {
415-
self.variant_field(path_str, current_item, module_id)
416-
} else {
417-
Err(ResolutionFailure::NotResolved {
418-
module_id,
419-
partial_res: None,
420-
unresolved: path_root.into(),
421-
}
422-
.into())
423-
};
424-
}
425-
Ok(res) => res,
424+
.into())
425+
};
426426
};
427-
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
427+
428428
let res = match ty_res {
429+
Res::PrimTy(prim) => Some(self.resolve_primitive_associated_item(
430+
prim, ty_res, ns, module_id, item_name, item_str,
431+
)),
429432
Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias, did) => {
430433
debug!("looking for associated item named {} for item {:?}", item_name, did);
431434
// Checks if item_name belongs to `impl SomeItem`
@@ -465,7 +468,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
465468
Some(if extra_fragment.is_some() {
466469
Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(ty_res)))
467470
} else {
468-
// HACK(jynelson): `clean` expects the type, not the associated item.
471+
// HACK(jynelson): `clean` expects the type, not the associated item
469472
// but the disambiguator logic expects the associated item.
470473
// Store the kind in a side channel so that only the disambiguator logic looks at it.
471474
self.kind_side_channel.set(Some((kind.as_def_kind(), id)));
@@ -511,13 +514,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
511514
_ => None,
512515
}
513516
} else {
514-
// We already know this isn't in ValueNS, so no need to check variant_field
515-
return Err(ResolutionFailure::NotResolved {
516-
module_id,
517-
partial_res: Some(ty_res),
518-
unresolved: item_str.into(),
519-
}
520-
.into());
517+
None
521518
}
522519
}
523520
Res::Def(DefKind::Trait, did) => cx
@@ -1089,7 +1086,7 @@ impl LinkCollector<'_, '_> {
10891086
return None;
10901087
}
10911088
res = prim;
1092-
fragment = Some(path.to_owned());
1089+
fragment = Some((*path.as_str()).to_owned());
10931090
} else {
10941091
// `[char]` when a `char` module is in scope
10951092
let candidates = vec![res, prim];
@@ -1956,44 +1953,45 @@ fn handle_variant(
19561953
)
19571954
}
19581955

1959-
const PRIMITIVES: &[(&str, Res)] = &[
1960-
("u8", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U8))),
1961-
("u16", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U16))),
1962-
("u32", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U32))),
1963-
("u64", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U64))),
1964-
("u128", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U128))),
1965-
("usize", Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::Usize))),
1966-
("i8", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I8))),
1967-
("i16", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I16))),
1968-
("i32", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I32))),
1969-
("i64", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I64))),
1970-
("i128", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I128))),
1971-
("isize", Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::Isize))),
1972-
("f32", Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F32))),
1973-
("f64", Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F64))),
1974-
("str", Res::PrimTy(hir::PrimTy::Str)),
1975-
("bool", Res::PrimTy(hir::PrimTy::Bool)),
1976-
("char", Res::PrimTy(hir::PrimTy::Char)),
1956+
// FIXME: At this point, this is basically a copy of the PrimitiveTypeTable
1957+
const PRIMITIVES: &[(Symbol, Res)] = &[
1958+
(sym::u8, Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U8))),
1959+
(sym::u16, Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U16))),
1960+
(sym::u32, Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U32))),
1961+
(sym::u64, Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U64))),
1962+
(sym::u128, Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::U128))),
1963+
(sym::usize, Res::PrimTy(hir::PrimTy::Uint(rustc_ast::UintTy::Usize))),
1964+
(sym::i8, Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I8))),
1965+
(sym::i16, Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I16))),
1966+
(sym::i32, Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I32))),
1967+
(sym::i64, Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I64))),
1968+
(sym::i128, Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::I128))),
1969+
(sym::isize, Res::PrimTy(hir::PrimTy::Int(rustc_ast::IntTy::Isize))),
1970+
(sym::f32, Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F32))),
1971+
(sym::f64, Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F64))),
1972+
(sym::str, Res::PrimTy(hir::PrimTy::Str)),
1973+
(sym::bool, Res::PrimTy(hir::PrimTy::Bool)),
1974+
(sym::char, Res::PrimTy(hir::PrimTy::Char)),
19771975
];
19781976

1979-
fn is_primitive(path_str: &str, ns: Namespace) -> Option<(&'static str, Res)> {
1977+
fn is_primitive(path_str: &str, ns: Namespace) -> Option<(Symbol, Res)> {
19801978
is_bool_value(path_str, ns).or_else(|| {
1981-
if ns == TypeNS { PRIMITIVES.iter().find(|x| x.0 == path_str).copied() } else { None }
1979+
if ns == TypeNS {
1980+
PRIMITIVES.iter().find(|x| x.0.as_str() == path_str).copied()
1981+
} else {
1982+
None
1983+
}
19821984
})
19831985
}
19841986

1985-
fn is_bool_value(path_str: &str, ns: Namespace) -> Option<(&'static str, Res)> {
1987+
fn is_bool_value(path_str: &str, ns: Namespace) -> Option<(Symbol, Res)> {
19861988
if ns == TypeNS && (path_str == "true" || path_str == "false") {
1987-
Some(("bool", Res::PrimTy(hir::PrimTy::Bool)))
1989+
Some((sym::bool, Res::PrimTy(hir::PrimTy::Bool)))
19881990
} else {
19891991
None
19901992
}
19911993
}
19921994

1993-
fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option<&'static SmallVec<[DefId; 4]>> {
1994-
Some(PrimitiveType::from_symbol(Symbol::intern(path_str))?.impls(cx.tcx))
1995-
}
1996-
19971995
fn strip_generics_from_path(path_str: &str) -> Result<String, ResolutionFailure<'static>> {
19981996
let mut stripped_segments = vec![];
19991997
let mut path = path_str.chars().peekable();

0 commit comments

Comments
 (0)