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