1+ use rustc_ast as ast;
12use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
23use rustc_data_structures:: sync:: { self , Lrc } ;
34use rustc_driver:: abort_on_err;
@@ -22,7 +23,7 @@ use rustc_session::DiagnosticOutput;
2223use rustc_session:: Session ;
2324use rustc_span:: source_map;
2425use rustc_span:: symbol:: sym;
25- use rustc_span:: { Span , DUMMY_SP } ;
26+ use rustc_span:: Span ;
2627
2728use std:: cell:: RefCell ;
2829use std:: collections:: hash_map:: Entry ;
@@ -348,42 +349,65 @@ crate fn create_config(
348349}
349350
350351crate fn create_resolver < ' a > (
351- externs : config:: Externs ,
352352 queries : & Queries < ' a > ,
353353 sess : & Session ,
354354) -> Rc < RefCell < interface:: BoxedResolver > > {
355- let extern_names: Vec < String > = externs
356- . iter ( )
357- . filter ( |( _, entry) | entry. add_prelude )
358- . map ( |( name, _) | name)
359- . cloned ( )
360- . collect ( ) ;
361-
362355 let parts = abort_on_err ( queries. expansion ( ) , sess) . peek ( ) ;
363- let resolver = parts. 1 . borrow ( ) ;
364-
365- // Before we actually clone it, let's force all the extern'd crates to
366- // actually be loaded, just in case they're only referred to inside
367- // intra-doc links
368- resolver. borrow_mut ( ) . access ( |resolver| {
369- sess. time ( "load_extern_crates" , || {
370- for extern_name in & extern_names {
371- debug ! ( "loading extern crate {}" , extern_name) ;
372- if let Err ( ( ) ) = resolver
373- . resolve_str_path_error (
374- DUMMY_SP ,
375- extern_name,
376- TypeNS ,
377- LocalDefId { local_def_index : CRATE_DEF_INDEX } . to_def_id ( ) ,
378- ) {
379- warn ! ( "unable to resolve external crate {} (do you have an unused `--extern` crate?)" , extern_name)
380- }
356+ let ( krate, resolver, _) = & * parts;
357+ let resolver = resolver. borrow ( ) . clone ( ) ;
358+
359+ // Letting the resolver escape at the end of the function leads to inconsistencies between the
360+ // crates the TyCtxt sees and the resolver sees (because the resolver could load more crates
361+ // after escaping). Hopefully `IntraLinkCrateLoader` gets all the crates we need ...
362+ struct IntraLinkCrateLoader {
363+ current_mod : DefId ,
364+ resolver : Rc < RefCell < interface:: BoxedResolver > > ,
365+ }
366+ impl ast:: visit:: Visitor < ' _ > for IntraLinkCrateLoader {
367+ fn visit_attribute ( & mut self , attr : & ast:: Attribute ) {
368+ use crate :: html:: markdown:: { markdown_links, MarkdownLink } ;
369+ use crate :: passes:: collect_intra_doc_links:: Disambiguator ;
370+
371+ if let Some ( doc) = attr. doc_str ( ) {
372+ for MarkdownLink { link, .. } in markdown_links ( & doc. as_str ( ) ) {
373+ // FIXME: this misses a *lot* of the preprocessing done in collect_intra_doc_links
374+ // I think most of it shouldn't be necessary since we only need the crate prefix?
375+ let path_str = match Disambiguator :: from_str ( & link) {
376+ Ok ( x) => x. map_or ( link. as_str ( ) , |( _, p) | p) ,
377+ Err ( _) => continue ,
378+ } ;
379+ self . resolver . borrow_mut ( ) . access ( |resolver| {
380+ let _ = resolver. resolve_str_path_error (
381+ attr. span ,
382+ path_str,
383+ TypeNS ,
384+ self . current_mod ,
385+ ) ;
386+ } ) ;
387+ }
381388 }
382- } ) ;
383- } ) ;
389+ ast:: visit:: walk_attribute ( self , attr) ;
390+ }
391+
392+ fn visit_item ( & mut self , item : & ast:: Item ) {
393+ use rustc_ast_lowering:: ResolverAstLowering ;
394+
395+ if let ast:: ItemKind :: Mod ( ..) = item. kind {
396+ let new_mod =
397+ self . resolver . borrow_mut ( ) . access ( |resolver| resolver. local_def_id ( item. id ) ) ;
398+ let old_mod = mem:: replace ( & mut self . current_mod , new_mod. to_def_id ( ) ) ;
399+ ast:: visit:: walk_item ( self , item) ;
400+ self . current_mod = old_mod;
401+ } else {
402+ ast:: visit:: walk_item ( self , item) ;
403+ }
404+ }
405+ }
406+ let crate_id = LocalDefId { local_def_index : CRATE_DEF_INDEX } . to_def_id ( ) ;
407+ let mut loader = IntraLinkCrateLoader { current_mod : crate_id, resolver } ;
408+ ast:: visit:: walk_crate ( & mut loader, krate) ;
384409
385- // Now we're good to clone the resolver because everything should be loaded
386- resolver. clone ( )
410+ loader. resolver
387411}
388412
389413crate fn run_global_ctxt (
0 commit comments