@@ -74,8 +74,6 @@ enum ResolutionFailure<'a> {
74
74
NoAssocItem ( Res , Symbol ) ,
75
75
/// should not ever happen
76
76
NoParentItem ,
77
- /// the root of this path resolved, but it was not an enum.
78
- NotAnEnum ( Res ) ,
79
77
/// this could be an enum variant, but the last path fragment wasn't resolved.
80
78
/// the `String` is the variant that didn't exist
81
79
NotAVariant ( Res , Symbol ) ,
@@ -91,7 +89,6 @@ impl ResolutionFailure<'a> {
91
89
NoPrimitiveAssocItem { res, .. }
92
90
| NoAssocItem ( res, _)
93
91
| NoPrimitiveImpl ( res, _)
94
- | NotAnEnum ( res)
95
92
| NotAVariant ( res, _)
96
93
| WrongNamespace ( res, _)
97
94
| CannotHaveAssociatedItems ( res, _) => Some ( * res) ,
@@ -133,6 +130,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
133
130
path_str : & ' path str ,
134
131
current_item : & Option < String > ,
135
132
module_id : DefId ,
133
+ extra_fragment : & Option < String > ,
136
134
) -> Result < ( Res , Option < String > ) , ErrorKind < ' path > > {
137
135
let cx = self . cx ;
138
136
@@ -202,7 +200,28 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
202
200
_ => unreachable ! ( ) ,
203
201
}
204
202
}
205
- _ => Err ( ErrorKind :: Resolve ( ResolutionFailure :: NotAnEnum ( ty_res) ) ) ,
203
+ // `variant_field` looks at 3 different path segments in a row.
204
+ // But `NoAssocItem` assumes there are only 2. Check to see if there's
205
+ // an intermediate segment that resolves.
206
+ _ => {
207
+ let intermediate_path = format ! ( "{}::{}" , path, variant_name) ;
208
+ // NOTE: we have to be careful here, because we're already in `resolve`.
209
+ // We know this doesn't recurse forever because we use a shorter path each time.
210
+ // NOTE: this uses `TypeNS` because nothing else has a valid path segment after
211
+ let kind = if let Some ( intermediate) = self . check_full_res (
212
+ TypeNS ,
213
+ & intermediate_path,
214
+ Some ( module_id) ,
215
+ current_item,
216
+ extra_fragment,
217
+ ) {
218
+ ResolutionFailure :: NoAssocItem ( intermediate, variant_field_name)
219
+ } else {
220
+ // Even with the shorter path, it didn't resolve, so say that.
221
+ ResolutionFailure :: NoAssocItem ( ty_res, variant_name)
222
+ } ;
223
+ Err ( ErrorKind :: Resolve ( kind) )
224
+ }
206
225
}
207
226
}
208
227
@@ -376,7 +395,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
376
395
let ty_res = match ty_res {
377
396
Err ( ( ) ) | Ok ( Res :: Err ) => {
378
397
return if ns == Namespace :: ValueNS {
379
- self . variant_field ( path_str, current_item, module_id)
398
+ self . variant_field ( path_str, current_item, module_id, extra_fragment )
380
399
} else {
381
400
// See if it only broke because of the namespace.
382
401
let kind = cx. enter_resolver ( |resolver| {
@@ -533,7 +552,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
533
552
} ;
534
553
res. unwrap_or_else ( || {
535
554
if ns == Namespace :: ValueNS {
536
- self . variant_field ( path_str, current_item, module_id)
555
+ self . variant_field ( path_str, current_item, module_id, extra_fragment )
537
556
} else {
538
557
Err ( ErrorKind :: Resolve ( ResolutionFailure :: NoAssocItem ( ty_res, item_name) ) )
539
558
}
@@ -543,6 +562,41 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
543
562
Err ( ErrorKind :: Resolve ( ResolutionFailure :: NoParentItem ) )
544
563
}
545
564
}
565
+
566
+ // used for reporting better errors
567
+ fn check_full_res (
568
+ & self ,
569
+ ns : Namespace ,
570
+ path_str : & str ,
571
+ base_node : Option < DefId > ,
572
+ current_item : & Option < String > ,
573
+ extra_fragment : & Option < String > ,
574
+ ) -> Option < Res > {
575
+ let check_full_res_inner = |this : & Self , result : Result < Res , ErrorKind < ' _ > > | {
576
+ let res = match result {
577
+ Ok ( res) => Some ( res) ,
578
+ Err ( ErrorKind :: Resolve ( kind) ) => kind. full_res ( ) ,
579
+ Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: RustdocAnchorConflict ( res) ) ) => {
580
+ Some ( res)
581
+ }
582
+ Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: MultipleAnchors ) ) => None ,
583
+ } ;
584
+ this. kind_side_channel . take ( ) . map ( |( kind, id) | Res :: Def ( kind, id) ) . or ( res)
585
+ } ;
586
+ // cannot be used for macro namespace
587
+ let check_full_res = |this : & Self , ns| {
588
+ let result = this. resolve ( path_str, ns, current_item, base_node, extra_fragment) ;
589
+ check_full_res_inner ( this, result. map ( |( res, _) | res) )
590
+ } ;
591
+ let check_full_res_macro = |this : & Self | {
592
+ let result = this. macro_resolve ( path_str, base_node) ;
593
+ check_full_res_inner ( this, result. map_err ( ErrorKind :: Resolve ) )
594
+ } ;
595
+ match ns {
596
+ Namespace :: MacroNS => check_full_res_macro ( self ) ,
597
+ Namespace :: TypeNS | Namespace :: ValueNS => check_full_res ( self , ns) ,
598
+ }
599
+ }
546
600
}
547
601
548
602
fn resolve_associated_trait_item (
@@ -652,7 +706,7 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
652
706
let trait_ref = cx. tcx . impl_trait_ref ( impl_) . expect ( "this is not an inherent impl" ) ;
653
707
// Check if these are the same type.
654
708
let impl_type = trait_ref. self_ty ( ) ;
655
- debug ! (
709
+ trace ! (
656
710
"comparing type {} with kind {:?} against type {:?}" ,
657
711
impl_type,
658
712
impl_type. kind( ) ,
@@ -875,40 +929,26 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
875
929
}
876
930
}
877
931
878
- // used for reporting better errors
879
- let check_full_res = |this : & mut Self , ns| {
880
- let res =
881
- match this. resolve ( path_str, ns, & current_item, base_node, & extra_fragment)
882
- {
883
- Ok ( res) => {
884
- debug ! (
885
- "check_full_res: saw res for {} in {:?} ns: {:?}" ,
886
- path_str, ns, res. 0
887
- ) ;
888
- Some ( res. 0 )
889
- }
890
- Err ( ErrorKind :: Resolve ( kind) ) => kind. full_res ( ) ,
891
- Err ( ErrorKind :: AnchorFailure (
892
- AnchorFailure :: RustdocAnchorConflict ( res) ,
893
- ) ) => Some ( res) ,
894
- Err ( ErrorKind :: AnchorFailure ( AnchorFailure :: MultipleAnchors ) ) => None ,
895
- } ;
896
- this. kind_side_channel . take ( ) . map ( |( kind, id) | Res :: Def ( kind, id) ) . or ( res)
897
- } ;
898
-
899
932
match disambiguator. map ( Disambiguator :: ns) {
900
933
Some ( ns @ ( ValueNS | TypeNS ) ) => {
901
934
match self . resolve ( path_str, ns, & current_item, base_node, & extra_fragment)
902
935
{
903
936
Ok ( res) => res,
904
937
Err ( ErrorKind :: Resolve ( mut kind) ) => {
905
938
// We only looked in one namespace. Try to give a better error if possible.
906
- // TODO: handle MacroNS too
907
939
if kind. full_res ( ) . is_none ( ) {
908
940
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS } ;
909
- if let Some ( res) = check_full_res ( self , other_ns) {
910
- // recall that this stores the _expected_ namespace
911
- kind = ResolutionFailure :: WrongNamespace ( res, ns) ;
941
+ for & ns in & [ other_ns, MacroNS ] {
942
+ if let Some ( res) = self . check_full_res (
943
+ ns,
944
+ path_str,
945
+ base_node,
946
+ & current_item,
947
+ & extra_fragment,
948
+ ) {
949
+ kind = ResolutionFailure :: WrongNamespace ( res, ns) ;
950
+ break ;
951
+ }
912
952
}
913
953
}
914
954
resolution_failure (
@@ -1033,7 +1073,13 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
1033
1073
Err ( mut kind) => {
1034
1074
// `macro_resolve` only looks in the macro namespace. Try to give a better error if possible.
1035
1075
for & ns in & [ TypeNS , ValueNS ] {
1036
- if let Some ( res) = check_full_res ( self , ns) {
1076
+ if let Some ( res) = self . check_full_res (
1077
+ ns,
1078
+ path_str,
1079
+ base_node,
1080
+ & current_item,
1081
+ & extra_fragment,
1082
+ ) {
1037
1083
kind = ResolutionFailure :: WrongNamespace ( res, MacroNS ) ;
1038
1084
break ;
1039
1085
}
@@ -1525,13 +1571,6 @@ fn resolution_failure(
1525
1571
ResolutionFailure :: CannotHaveAssociatedItems ( res, _) => {
1526
1572
assoc_item_not_allowed ( res, diag)
1527
1573
}
1528
- // TODO: is there ever a case where this happens?
1529
- ResolutionFailure :: NotAnEnum ( res) => {
1530
- let note =
1531
- format ! ( "this link resolves to {}, which is not an enum" , item( res) ) ;
1532
- diag. note ( & note) ;
1533
- diag. note ( "if this were an enum, it might have a variant which resolved" ) ;
1534
- }
1535
1574
ResolutionFailure :: NotAVariant ( res, variant) => {
1536
1575
let note = format ! (
1537
1576
"this link partially resolves to {}, but there is no variant named {}" ,
0 commit comments