@@ -394,10 +394,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
394
394
ns,
395
395
impl_,
396
396
)
397
- . map ( |item| match item. kind {
398
- ty:: AssocKind :: Fn => "method" ,
399
- ty:: AssocKind :: Const => "associatedconstant" ,
400
- ty:: AssocKind :: Type => "associatedtype" ,
397
+ . map ( |item| {
398
+ let kind = item. kind ;
399
+ self . kind_side_channel . set ( Some ( ( kind. as_def_kind ( ) , item. def_id ) ) ) ;
400
+ match kind {
401
+ ty:: AssocKind :: Fn => "method" ,
402
+ ty:: AssocKind :: Const => "associatedconstant" ,
403
+ ty:: AssocKind :: Type => "associatedtype" ,
404
+ }
401
405
} )
402
406
. map ( |out| {
403
407
(
@@ -1142,55 +1146,75 @@ impl LinkCollector<'_, '_> {
1142
1146
callback,
1143
1147
) ;
1144
1148
} ;
1145
- match res {
1146
- Res :: Primitive ( _) => match disambiguator {
1147
- Some ( Disambiguator :: Primitive | Disambiguator :: Namespace ( _) ) | None => {
1148
- Some ( ItemLink { link : ori_link. link , link_text, did : None , fragment } )
1149
- }
1150
- Some ( other) => {
1151
- report_mismatch ( other, Disambiguator :: Primitive ) ;
1152
- None
1153
- }
1154
- } ,
1155
- Res :: Def ( kind, id) => {
1156
- debug ! ( "intra-doc link to {} resolved to {:?}" , path_str, res) ;
1157
-
1158
- // Disallow e.g. linking to enums with `struct@`
1159
- debug ! ( "saw kind {:?} with disambiguator {:?}" , kind, disambiguator) ;
1160
- match ( self . kind_side_channel . take ( ) . map ( |( kind, _) | kind) . unwrap_or ( kind) , disambiguator) {
1161
- | ( DefKind :: Const | DefKind :: ConstParam | DefKind :: AssocConst | DefKind :: AnonConst , Some ( Disambiguator :: Kind ( DefKind :: Const ) ) )
1162
- // NOTE: this allows 'method' to mean both normal functions and associated functions
1163
- // This can't cause ambiguity because both are in the same namespace.
1164
- | ( DefKind :: Fn | DefKind :: AssocFn , Some ( Disambiguator :: Kind ( DefKind :: Fn ) ) )
1165
- // These are namespaces; allow anything in the namespace to match
1166
- | ( _, Some ( Disambiguator :: Namespace ( _) ) )
1167
- // If no disambiguator given, allow anything
1168
- | ( _, None )
1169
- // All of these are valid, so do nothing
1170
- => { }
1171
- ( actual, Some ( Disambiguator :: Kind ( expected) ) ) if actual == expected => { }
1172
- ( _, Some ( specified @ Disambiguator :: Kind ( _) | specified @ Disambiguator :: Primitive ) ) => {
1173
- report_mismatch ( specified, Disambiguator :: Kind ( kind) ) ;
1174
- return None ;
1175
- }
1149
+
1150
+ let verify = |kind : DefKind , id : DefId | {
1151
+ debug ! ( "intra-doc link to {} resolved to {:?}" , path_str, res) ;
1152
+
1153
+ // Disallow e.g. linking to enums with `struct@`
1154
+ debug ! ( "saw kind {:?} with disambiguator {:?}" , kind, disambiguator) ;
1155
+ match ( self . kind_side_channel . take ( ) . map ( |( kind, _) | kind) . unwrap_or ( kind) , disambiguator) {
1156
+ | ( DefKind :: Const | DefKind :: ConstParam | DefKind :: AssocConst | DefKind :: AnonConst , Some ( Disambiguator :: Kind ( DefKind :: Const ) ) )
1157
+ // NOTE: this allows 'method' to mean both normal functions and associated functions
1158
+ // This can't cause ambiguity because both are in the same namespace.
1159
+ | ( DefKind :: Fn | DefKind :: AssocFn , Some ( Disambiguator :: Kind ( DefKind :: Fn ) ) )
1160
+ // These are namespaces; allow anything in the namespace to match
1161
+ | ( _, Some ( Disambiguator :: Namespace ( _) ) )
1162
+ // If no disambiguator given, allow anything
1163
+ | ( _, None )
1164
+ // All of these are valid, so do nothing
1165
+ => { }
1166
+ ( actual, Some ( Disambiguator :: Kind ( expected) ) ) if actual == expected => { }
1167
+ ( _, Some ( specified @ Disambiguator :: Kind ( _) | specified @ Disambiguator :: Primitive ) ) => {
1168
+ report_mismatch ( specified, Disambiguator :: Kind ( kind) ) ;
1169
+ return None ;
1176
1170
}
1171
+ }
1172
+
1173
+ // item can be non-local e.g. when using #[doc(primitive = "pointer")]
1174
+ if let Some ( ( src_id, dst_id) ) = id
1175
+ . as_local ( )
1176
+ . and_then ( |dst_id| item. def_id . as_local ( ) . map ( |src_id| ( src_id, dst_id) ) )
1177
+ {
1178
+ use rustc_hir:: def_id:: LOCAL_CRATE ;
1177
1179
1178
- // item can be non-local e.g. when using #[doc(primitive = "pointer")]
1179
- if let Some ( ( src_id, dst_id) ) = id
1180
- . as_local ( )
1181
- . and_then ( |dst_id| item. def_id . as_local ( ) . map ( |src_id| ( src_id, dst_id) ) )
1180
+ let hir_src = self . cx . tcx . hir ( ) . local_def_id_to_hir_id ( src_id) ;
1181
+ let hir_dst = self . cx . tcx . hir ( ) . local_def_id_to_hir_id ( dst_id) ;
1182
+
1183
+ if self . cx . tcx . privacy_access_levels ( LOCAL_CRATE ) . is_exported ( hir_src)
1184
+ && !self . cx . tcx . privacy_access_levels ( LOCAL_CRATE ) . is_exported ( hir_dst)
1182
1185
{
1183
- use rustc_hir:: def_id:: LOCAL_CRATE ;
1186
+ privacy_error ( cx, & item, & path_str, dox, & ori_link) ;
1187
+ }
1188
+ }
1184
1189
1185
- let hir_src = self . cx . tcx . hir ( ) . local_def_id_to_hir_id ( src_id ) ;
1186
- let hir_dst = self . cx . tcx . hir ( ) . local_def_id_to_hir_id ( dst_id ) ;
1190
+ Some ( ( kind , id ) )
1191
+ } ;
1187
1192
1188
- if self . cx . tcx . privacy_access_levels ( LOCAL_CRATE ) . is_exported ( hir_src)
1189
- && !self . cx . tcx . privacy_access_levels ( LOCAL_CRATE ) . is_exported ( hir_dst)
1190
- {
1191
- privacy_error ( cx, & item, & path_str, dox, & ori_link) ;
1193
+ match res {
1194
+ Res :: Primitive ( _) => {
1195
+ if let Some ( ( kind, id) ) = self . kind_side_channel . take ( ) {
1196
+ // We're actually resolving an associated item of a primitive, so we need to
1197
+ // verify the disambiguator (if any) matches the type of the associated item.
1198
+ // This case should really follow the same flow as the `Res::Def` branch below,
1199
+ // but attempting to add a call to `clean::register_res` causes an ICE. @jyn514
1200
+ // thinks `register_res` is only needed for cross-crate re-exports, but Rust
1201
+ // doesn't allow statements like `use str::trim;`, making this a (hopefully)
1202
+ // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
1203
+ // for discussion on the matter.
1204
+ verify ( kind, id) ?;
1205
+ } else {
1206
+ match disambiguator {
1207
+ Some ( Disambiguator :: Primitive | Disambiguator :: Namespace ( _) ) | None => { }
1208
+ Some ( other) => {
1209
+ report_mismatch ( other, Disambiguator :: Primitive ) ;
1210
+ return None ;
1211
+ }
1192
1212
}
1193
1213
}
1214
+ Some ( ItemLink { link : ori_link. link , link_text, did : None , fragment } )
1215
+ }
1216
+ Res :: Def ( kind, id) => {
1217
+ let ( kind, id) = verify ( kind, id) ?;
1194
1218
let id = clean:: register_res ( cx, rustc_hir:: def:: Res :: Def ( kind, id) ) ;
1195
1219
Some ( ItemLink { link : ori_link. link , link_text, did : Some ( id) , fragment } )
1196
1220
}
0 commit comments