clippy_utils/
res.rs

1use rustc_hir::def::{DefKind, Res};
2use rustc_hir::def_id::DefId;
3use rustc_hir::{
4    self as hir, Expr, ExprKind, HirId, LangItem, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, TyKind,
5};
6use rustc_lint::LateContext;
7use rustc_middle::ty::layout::HasTyCtxt;
8use rustc_middle::ty::{AdtDef, AdtKind, Binder, EarlyBinder, Ty, TypeckResults};
9use rustc_span::{Ident, Symbol};
10
11/// Either a `HirId` or a type which can be identified by one.
12pub trait HasHirId: Copy {
13    fn hir_id(self) -> HirId;
14}
15impl HasHirId for HirId {
16    #[inline]
17    fn hir_id(self) -> HirId {
18        self
19    }
20}
21impl HasHirId for &Expr<'_> {
22    #[inline]
23    fn hir_id(self) -> HirId {
24        self.hir_id
25    }
26}
27
28type DefRes = (DefKind, DefId);
29
30pub trait MaybeTypeckRes<'tcx> {
31    /// Gets the contained `TypeckResults`.
32    ///
33    /// With debug assertions enabled this will always return `Some`. `None` is
34    /// only returned so logic errors can be handled by not emitting a lint on
35    /// release builds.
36    fn typeck_res(&self) -> Option<&TypeckResults<'tcx>>;
37
38    /// Gets the type-dependent resolution of the specified node.
39    ///
40    /// With debug assertions enabled this will always return `Some`. `None` is
41    /// only returned so logic errors can be handled by not emitting a lint on
42    /// release builds.
43    #[inline]
44    #[cfg_attr(debug_assertions, track_caller)]
45    fn ty_based_def(&self, node: impl HasHirId) -> Option<DefRes> {
46        #[inline]
47        #[cfg_attr(debug_assertions, track_caller)]
48        fn f(typeck: &TypeckResults<'_>, id: HirId) -> Option<DefRes> {
49            if typeck.hir_owner == id.owner {
50                let def = typeck.type_dependent_def(id);
51                debug_assert!(
52                    def.is_some(),
53                    "attempted type-dependent lookup for a node with no definition\
54                        \n  node `{id:?}`",
55                );
56                def
57            } else {
58                debug_assert!(
59                    false,
60                    "attempted type-dependent lookup for a node in the wrong body\
61                        \n  in body `{:?}`\
62                        \n  expected body `{:?}`",
63                    typeck.hir_owner, id.owner,
64                );
65                None
66            }
67        }
68        self.typeck_res().and_then(|typeck| f(typeck, node.hir_id()))
69    }
70}
71impl<'tcx> MaybeTypeckRes<'tcx> for LateContext<'tcx> {
72    #[inline]
73    #[cfg_attr(debug_assertions, track_caller)]
74    fn typeck_res(&self) -> Option<&TypeckResults<'tcx>> {
75        if let Some(typeck) = self.maybe_typeck_results() {
76            Some(typeck)
77        } else {
78            // It's possible to get the `TypeckResults` for any other body, but
79            // attempting to lookup the type of something across bodies like this
80            // is a good indication of a bug.
81            debug_assert!(false, "attempted type-dependent lookup in a non-body context");
82            None
83        }
84    }
85}
86impl<'tcx> MaybeTypeckRes<'tcx> for TypeckResults<'tcx> {
87    #[inline]
88    fn typeck_res(&self) -> Option<&TypeckResults<'tcx>> {
89        Some(self)
90    }
91}
92
93/// A `QPath` with the `HirId` of the node containing it.
94type QPathId<'tcx> = (&'tcx QPath<'tcx>, HirId);
95
96/// A HIR node which might be a `QPath`.
97pub trait MaybeQPath<'a>: Copy {
98    /// If this node is a path gets both the contained path and the `HirId` to
99    /// use for type dependant lookup.
100    fn opt_qpath(self) -> Option<QPathId<'a>>;
101
102    /// If this is a path gets its resolution. Returns `Res::Err` otherwise.
103    #[inline]
104    #[cfg_attr(debug_assertions, track_caller)]
105    fn res<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>) -> Res {
106        #[cfg_attr(debug_assertions, track_caller)]
107        fn f(qpath: &QPath<'_>, id: HirId, typeck: &TypeckResults<'_>) -> Res {
108            match *qpath {
109                QPath::Resolved(_, p) => p.res,
110                QPath::TypeRelative(..) if let Some((kind, id)) = typeck.ty_based_def(id) => Res::Def(kind, id),
111                QPath::TypeRelative(..) => Res::Err,
112            }
113        }
114        match self.opt_qpath() {
115            Some((qpath, id)) if let Some(typeck) = typeck.typeck_res() => f(qpath, id, typeck),
116            _ => Res::Err,
117        }
118    }
119
120    /// If this is a path with the specified name as its final segment gets its
121    /// resolution. Returns `Res::Err` otherwise.
122    #[inline]
123    #[cfg_attr(debug_assertions, track_caller)]
124    fn res_if_named<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>, name: Symbol) -> Res {
125        #[cfg_attr(debug_assertions, track_caller)]
126        fn f(qpath: &QPath<'_>, id: HirId, typeck: &TypeckResults<'_>, name: Symbol) -> Res {
127            match *qpath {
128                QPath::Resolved(_, p)
129                    if let [.., seg] = p.segments
130                        && seg.ident.name == name =>
131                {
132                    p.res
133                },
134                QPath::TypeRelative(_, seg)
135                    if seg.ident.name == name
136                        && let Some((kind, id)) = typeck.ty_based_def(id) =>
137                {
138                    Res::Def(kind, id)
139                },
140                QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err,
141            }
142        }
143        match self.opt_qpath() {
144            Some((qpath, id)) if let Some(typeck) = typeck.typeck_res() => f(qpath, id, typeck, name),
145            _ => Res::Err,
146        }
147    }
148
149    /// If this is a path gets both its resolution and final segment.
150    #[inline]
151    #[cfg_attr(debug_assertions, track_caller)]
152    fn res_with_seg<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>) -> (Res, Option<&'a PathSegment<'a>>) {
153        #[cfg_attr(debug_assertions, track_caller)]
154        fn f<'a>(qpath: &QPath<'a>, id: HirId, typeck: &TypeckResults<'_>) -> (Res, Option<&'a PathSegment<'a>>) {
155            match *qpath {
156                QPath::Resolved(_, p) if let [.., seg] = p.segments => (p.res, Some(seg)),
157                QPath::TypeRelative(_, seg) if let Some((kind, id)) = typeck.ty_based_def(id) => {
158                    (Res::Def(kind, id), Some(seg))
159                },
160                QPath::Resolved(..) | QPath::TypeRelative(..) => (Res::Err, None),
161            }
162        }
163        match self.opt_qpath() {
164            Some((qpath, id)) if let Some(typeck) = typeck.typeck_res() => f(qpath, id, typeck),
165            _ => (Res::Err, None),
166        }
167    }
168
169    /// If this is a path without an explicit `Self` type gets its resolution.
170    /// Returns `Res::Err` otherwise.
171    ///
172    /// Only paths to trait items can optionally contain a `Self` type.
173    #[inline]
174    #[cfg_attr(debug_assertions, track_caller)]
175    fn typeless_res<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>) -> Res {
176        #[cfg_attr(debug_assertions, track_caller)]
177        fn f(qpath: &QPath<'_>, id: HirId, typeck: &TypeckResults<'_>) -> Res {
178            match *qpath {
179                QPath::Resolved(
180                    None
181                    | Some(&hir::Ty {
182                        kind: TyKind::Infer(()),
183                        ..
184                    }),
185                    p,
186                ) => p.res,
187                QPath::TypeRelative(
188                    &hir::Ty {
189                        kind: TyKind::Infer(()),
190                        ..
191                    },
192                    _,
193                ) if let Some((kind, id)) = typeck.ty_based_def(id) => Res::Def(kind, id),
194                QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err,
195            }
196        }
197        match self.opt_qpath() {
198            Some((qpath, id)) if let Some(typeck) = typeck.typeck_res() => f(qpath, id, typeck),
199            _ => Res::Err,
200        }
201    }
202
203    /// If this is a path without an explicit `Self` type to an item with the
204    /// specified name gets its resolution. Returns `Res::Err` otherwise.
205    ///
206    /// Only paths to trait items can optionally contain a `Self` type.
207    #[inline]
208    #[cfg_attr(debug_assertions, track_caller)]
209    fn typeless_res_if_named<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>, name: Symbol) -> Res {
210        #[cfg_attr(debug_assertions, track_caller)]
211        fn f(qpath: &QPath<'_>, id: HirId, typeck: &TypeckResults<'_>, name: Symbol) -> Res {
212            match *qpath {
213                QPath::Resolved(
214                    None
215                    | Some(&hir::Ty {
216                        kind: TyKind::Infer(()),
217                        ..
218                    }),
219                    p,
220                ) if let [.., seg] = p.segments
221                    && seg.ident.name == name =>
222                {
223                    p.res
224                },
225                QPath::TypeRelative(
226                    &hir::Ty {
227                        kind: TyKind::Infer(()),
228                        ..
229                    },
230                    seg,
231                ) if seg.ident.name == name
232                    && let Some((kind, id)) = typeck.ty_based_def(id) =>
233                {
234                    Res::Def(kind, id)
235                },
236                QPath::Resolved(..) | QPath::TypeRelative(..) => Res::Err,
237            }
238        }
239        match self.opt_qpath() {
240            Some((qpath, id)) if let Some(typeck) = typeck.typeck_res() => f(qpath, id, typeck, name),
241            _ => Res::Err,
242        }
243    }
244
245    /// If this is a type-relative path gets the definition it resolves to.
246    ///
247    /// Only inherent associated items require a type-relative path.
248    #[inline]
249    #[cfg_attr(debug_assertions, track_caller)]
250    fn ty_rel_def<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>) -> Option<DefRes> {
251        match self.opt_qpath() {
252            Some((QPath::TypeRelative(..), id)) => typeck.ty_based_def(id),
253            _ => None,
254        }
255    }
256
257    /// If this is a type-relative path to an item with the specified name gets
258    /// the definition it resolves to.
259    ///
260    /// Only inherent associated items require a type-relative path.
261    #[inline]
262    #[cfg_attr(debug_assertions, track_caller)]
263    fn ty_rel_def_if_named<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>, name: Symbol) -> Option<DefRes> {
264        match self.opt_qpath() {
265            Some((&QPath::TypeRelative(_, seg), id)) if seg.ident.name == name => typeck.ty_based_def(id),
266            _ => None,
267        }
268    }
269
270    /// If this is a type-relative path gets the definition it resolves to and
271    /// its final segment.
272    ///
273    /// Only inherent associated items require a type-relative path.
274    #[inline]
275    #[cfg_attr(debug_assertions, track_caller)]
276    fn ty_rel_def_with_seg<'tcx>(self, typeck: &impl MaybeTypeckRes<'tcx>) -> Option<(DefRes, &'a PathSegment<'a>)> {
277        match self.opt_qpath() {
278            Some((QPath::TypeRelative(_, seg), id)) if let Some(def) = typeck.ty_based_def(id) => Some((def, seg)),
279            _ => None,
280        }
281    }
282}
283
284impl<'tcx> MaybeQPath<'tcx> for QPathId<'tcx> {
285    #[inline]
286    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
287        Some((self.0, self.1))
288    }
289}
290impl<'tcx> MaybeQPath<'tcx> for &'tcx Expr<'_> {
291    #[inline]
292    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
293        match &self.kind {
294            ExprKind::Path(qpath) => Some((qpath, self.hir_id)),
295            _ => None,
296        }
297    }
298}
299impl<'tcx> MaybeQPath<'tcx> for &'tcx PatExpr<'_> {
300    #[inline]
301    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
302        match &self.kind {
303            PatExprKind::Path(qpath) => Some((qpath, self.hir_id)),
304            _ => None,
305        }
306    }
307}
308impl<'tcx, AmbigArg> MaybeQPath<'tcx> for &'tcx hir::Ty<'_, AmbigArg> {
309    #[inline]
310    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
311        match &self.kind {
312            TyKind::Path(qpath) => Some((qpath, self.hir_id)),
313            _ => None,
314        }
315    }
316}
317impl<'tcx> MaybeQPath<'tcx> for &'_ Pat<'tcx> {
318    #[inline]
319    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
320        match self.kind {
321            PatKind::Expr(e) => e.opt_qpath(),
322            _ => None,
323        }
324    }
325}
326impl<'tcx, T: MaybeQPath<'tcx>> MaybeQPath<'tcx> for Option<T> {
327    #[inline]
328    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
329        self.and_then(T::opt_qpath)
330    }
331}
332impl<'tcx, T: Copy + MaybeQPath<'tcx>> MaybeQPath<'tcx> for &Option<T> {
333    #[inline]
334    fn opt_qpath(self) -> Option<QPathId<'tcx>> {
335        self.and_then(T::opt_qpath)
336    }
337}
338
339/// A resolved path and the explicit `Self` type if there is one.
340type OptResPath<'tcx> = (Option<&'tcx hir::Ty<'tcx>>, Option<&'tcx Path<'tcx>>);
341
342/// A HIR node which might be a `QPath::Resolved`.
343///
344/// The following are resolved paths:
345/// * A path to a module or crate item.
346/// * A path to a trait item via the trait's name.
347/// * A path to a struct or variant constructor via the original type's path.
348/// * A local.
349///
350/// All other paths are `TypeRelative` and require using `PathRes` to lookup the
351/// resolution.
352pub trait MaybeResPath<'a>: Copy {
353    /// If this node is a resolved path gets both the contained path and the
354    /// type associated with it.
355    fn opt_res_path(self) -> OptResPath<'a>;
356
357    /// If this node is a resolved path gets it's resolution. Returns `Res::Err`
358    /// otherwise.
359    #[inline]
360    fn basic_res(self) -> &'a Res {
361        self.opt_res_path().1.map_or(&Res::Err, |p| &p.res)
362    }
363
364    /// If this node is a path to a local gets the local's `HirId`.
365    #[inline]
366    fn res_local_id(self) -> Option<HirId> {
367        if let (_, Some(p)) = self.opt_res_path()
368            && let Res::Local(id) = p.res
369        {
370            Some(id)
371        } else {
372            None
373        }
374    }
375
376    /// If this node is a path to a local gets the local's `HirId` and identifier.
377    fn res_local_id_and_ident(self) -> Option<(HirId, &'a Ident)> {
378        if let (_, Some(p)) = self.opt_res_path()
379            && let Res::Local(id) = p.res
380            && let [seg] = p.segments
381        {
382            Some((id, &seg.ident))
383        } else {
384            None
385        }
386    }
387}
388impl<'a> MaybeResPath<'a> for &'a Path<'a> {
389    #[inline]
390    fn opt_res_path(self) -> OptResPath<'a> {
391        (None, Some(self))
392    }
393
394    #[inline]
395    fn basic_res(self) -> &'a Res {
396        &self.res
397    }
398}
399impl<'a> MaybeResPath<'a> for &QPath<'a> {
400    #[inline]
401    fn opt_res_path(self) -> OptResPath<'a> {
402        match *self {
403            QPath::Resolved(ty, path) => (ty, Some(path)),
404            QPath::TypeRelative(..) => (None, None),
405        }
406    }
407}
408impl<'a> MaybeResPath<'a> for &Expr<'a> {
409    #[inline]
410    fn opt_res_path(self) -> OptResPath<'a> {
411        match &self.kind {
412            ExprKind::Path(qpath) => qpath.opt_res_path(),
413            _ => (None, None),
414        }
415    }
416}
417impl<'a> MaybeResPath<'a> for &PatExpr<'a> {
418    #[inline]
419    fn opt_res_path(self) -> OptResPath<'a> {
420        match &self.kind {
421            PatExprKind::Path(qpath) => qpath.opt_res_path(),
422            _ => (None, None),
423        }
424    }
425}
426impl<'a, AmbigArg> MaybeResPath<'a> for &hir::Ty<'a, AmbigArg> {
427    #[inline]
428    fn opt_res_path(self) -> OptResPath<'a> {
429        match &self.kind {
430            TyKind::Path(qpath) => qpath.opt_res_path(),
431            _ => (None, None),
432        }
433    }
434}
435impl<'a> MaybeResPath<'a> for &Pat<'a> {
436    #[inline]
437    fn opt_res_path(self) -> OptResPath<'a> {
438        match self.kind {
439            PatKind::Expr(e) => e.opt_res_path(),
440            _ => (None, None),
441        }
442    }
443}
444impl<'a, T: MaybeResPath<'a>> MaybeResPath<'a> for Option<T> {
445    #[inline]
446    fn opt_res_path(self) -> OptResPath<'a> {
447        match self {
448            Some(x) => T::opt_res_path(x),
449            None => (None, None),
450        }
451    }
452
453    #[inline]
454    fn basic_res(self) -> &'a Res {
455        self.map_or(&Res::Err, T::basic_res)
456    }
457}
458
459/// A type which may either contain a `DefId` or be referred to by a `DefId`.
460pub trait MaybeDef: Copy {
461    fn opt_def_id(self) -> Option<DefId>;
462
463    /// Gets this definition's id and kind. This will lookup the kind in the def
464    /// tree if needed.
465    fn opt_def<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)>;
466
467    /// Gets the diagnostic name of this definition if it has one.
468    #[inline]
469    fn opt_diag_name<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<Symbol> {
470        self.opt_def_id().and_then(|id| tcx.tcx().get_diagnostic_name(id))
471    }
472
473    /// Checks if this definition has the specified diagnostic name.
474    #[inline]
475    fn is_diag_item<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>, name: Symbol) -> bool {
476        self.opt_def_id()
477            .is_some_and(|id| tcx.tcx().is_diagnostic_item(name, id))
478    }
479
480    /// Checks if this definition is the specified `LangItem`.
481    #[inline]
482    fn is_lang_item<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>, item: LangItem) -> bool {
483        self.opt_def_id()
484            .is_some_and(|id| tcx.tcx().lang_items().get(item) == Some(id))
485    }
486
487    /// If this definition is an impl block gets its type.
488    #[inline]
489    fn opt_impl_ty<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<EarlyBinder<'tcx, Ty<'tcx>>> {
490        match self.opt_def(tcx) {
491            Some((DefKind::Impl { .. }, id)) => Some(tcx.tcx().type_of(id)),
492            _ => None,
493        }
494    }
495
496    /// Gets the parent of this definition if it has one.
497    #[inline]
498    fn opt_parent<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<DefId> {
499        self.opt_def_id().and_then(|id| tcx.tcx().opt_parent(id))
500    }
501
502    /// Checks if this definition is an impl block.
503    #[inline]
504    fn is_impl<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> bool {
505        matches!(self.opt_def(tcx), Some((DefKind::Impl { .. }, _)))
506    }
507
508    /// If this definition is a constructor gets the `DefId` of it's type or variant.
509    #[inline]
510    fn ctor_parent<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<DefId> {
511        match self.opt_def(tcx) {
512            Some((DefKind::Ctor(..), id)) => tcx.tcx().opt_parent(id),
513            _ => None,
514        }
515    }
516
517    /// If this definition is an associated item of an impl or trait gets the
518    /// `DefId` of its parent.
519    #[inline]
520    fn assoc_parent<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<DefId> {
521        match self.opt_def(tcx) {
522            Some((DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, id)) => tcx.tcx().opt_parent(id),
523            _ => None,
524        }
525    }
526
527    /// If this definition is an associated function of an impl or trait gets the
528    /// `DefId` of its parent.
529    #[inline]
530    fn assoc_fn_parent<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<DefId> {
531        match self.opt_def(tcx) {
532            Some((DefKind::AssocFn, id)) => tcx.tcx().opt_parent(id),
533            _ => None,
534        }
535    }
536}
537impl MaybeDef for DefId {
538    #[inline]
539    fn opt_def_id(self) -> Option<DefId> {
540        Some(self)
541    }
542
543    #[inline]
544    fn opt_def<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
545        self.opt_def_id().map(|id| (tcx.tcx().def_kind(id), id))
546    }
547}
548impl MaybeDef for (DefKind, DefId) {
549    #[inline]
550    fn opt_def_id(self) -> Option<DefId> {
551        Some(self.1)
552    }
553
554    #[inline]
555    fn opt_def<'tcx>(self, _: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
556        Some(self)
557    }
558}
559impl MaybeDef for AdtDef<'_> {
560    #[inline]
561    fn opt_def_id(self) -> Option<DefId> {
562        Some(self.did())
563    }
564
565    #[inline]
566    fn opt_def<'tcx>(self, _: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
567        let did = self.did();
568        match self.adt_kind() {
569            AdtKind::Enum => Some((DefKind::Enum, did)),
570            AdtKind::Struct => Some((DefKind::Struct, did)),
571            AdtKind::Union => Some((DefKind::Union, did)),
572        }
573    }
574}
575impl MaybeDef for Ty<'_> {
576    #[inline]
577    fn opt_def_id(self) -> Option<DefId> {
578        self.ty_adt_def().opt_def_id()
579    }
580
581    #[inline]
582    fn opt_def<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
583        self.ty_adt_def().opt_def(tcx)
584    }
585}
586impl MaybeDef for Res {
587    #[inline]
588    fn opt_def_id(self) -> Option<DefId> {
589        Res::opt_def_id(&self)
590    }
591
592    #[inline]
593    fn opt_def<'tcx>(self, _: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
594        match self {
595            Res::Def(kind, id) => Some((kind, id)),
596            _ => None,
597        }
598    }
599}
600impl<T: MaybeDef> MaybeDef for Option<T> {
601    #[inline]
602    fn opt_def_id(self) -> Option<DefId> {
603        self.and_then(T::opt_def_id)
604    }
605
606    #[inline]
607    fn opt_def<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
608        self.and_then(|x| T::opt_def(x, tcx))
609    }
610}
611impl<T: MaybeDef> MaybeDef for EarlyBinder<'_, T> {
612    #[inline]
613    fn opt_def_id(self) -> Option<DefId> {
614        self.skip_binder().opt_def_id()
615    }
616
617    #[inline]
618    fn opt_def<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
619        self.skip_binder().opt_def(tcx)
620    }
621}
622impl<T: MaybeDef> MaybeDef for Binder<'_, T> {
623    #[inline]
624    fn opt_def_id(self) -> Option<DefId> {
625        self.skip_binder().opt_def_id()
626    }
627
628    #[inline]
629    fn opt_def<'tcx>(self, tcx: &impl HasTyCtxt<'tcx>) -> Option<(DefKind, DefId)> {
630        self.skip_binder().opt_def(tcx)
631    }
632}