@@ -16,6 +16,7 @@ use rustc_session::lint::{
1616 Lint ,
1717} ;
1818use rustc_span:: hygiene:: MacroKind ;
19+ use rustc_span:: symbol:: sym;
1920use rustc_span:: symbol:: Ident ;
2021use rustc_span:: symbol:: Symbol ;
2122use 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-
19971995fn 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