11// ignore-tidy-filelength
22use std:: borrow:: Cow ;
33use std:: fmt;
4+ use std:: ops:: ControlFlow ;
45
56use rustc_abi:: ExternAbi ;
67use rustc_ast:: attr:: AttributeExt ;
@@ -16,6 +17,7 @@ pub use rustc_ast::{
1617 MetaItemInner , MetaItemLit , Movability , Mutability , Pinnedness , UnOp ,
1718} ;
1819use rustc_data_structures:: fingerprint:: Fingerprint ;
20+ use rustc_data_structures:: fx:: FxHashSet ;
1921use rustc_data_structures:: sorted_map:: SortedMap ;
2022use rustc_data_structures:: tagged_ptr:: TaggedRef ;
2123use rustc_error_messages:: { DiagArgValue , IntoDiagArg } ;
@@ -35,7 +37,7 @@ use crate::attrs::AttributeKind;
3537use crate :: def:: { CtorKind , DefKind , MacroKinds , PerNS , Res } ;
3638use crate :: def_id:: { DefId , LocalDefIdMap } ;
3739pub ( crate ) use crate :: hir_id:: { HirId , ItemLocalId , ItemLocalMap , OwnerId } ;
38- use crate :: intravisit:: { FnKind , VisitorExt } ;
40+ use crate :: intravisit:: { FnKind , Visitor , VisitorExt } ;
3941use crate :: lints:: DelayedLints ;
4042
4143#[ derive( Debug , Copy , Clone , PartialEq , Eq , HashStable_Generic ) ]
@@ -4445,6 +4447,70 @@ pub struct Impl<'hir> {
44454447 pub constness : Constness ,
44464448}
44474449
4450+ impl Impl < ' _ > {
4451+ pub fn is_fully_generic_for_reflection ( & self ) -> bool {
4452+ #[ derive( Default ) ]
4453+ struct LifetimeFinder {
4454+ seen : FxHashSet < LocalDefId > ,
4455+ }
4456+ impl < ' v > Visitor < ' v > for LifetimeFinder {
4457+ type Result = ControlFlow < ( ) > ;
4458+ fn visit_lifetime ( & mut self , lifetime : & ' v Lifetime ) -> Self :: Result {
4459+ match lifetime. kind {
4460+ LifetimeKind :: Param ( def_id) => {
4461+ if self . seen . insert ( def_id) {
4462+ ControlFlow :: Continue ( ( ) )
4463+ } else {
4464+ ControlFlow :: Break ( ( ) )
4465+ }
4466+ }
4467+ LifetimeKind :: ImplicitObjectLifetimeDefault
4468+ | LifetimeKind :: Error
4469+ | LifetimeKind :: Infer
4470+ | LifetimeKind :: Static => ControlFlow :: Break ( ( ) ) ,
4471+ }
4472+ }
4473+ }
4474+ let mut ty_lifetimes = LifetimeFinder :: default ( ) ;
4475+ if ty_lifetimes. visit_ty_unambig ( self . self_ty ) . is_break ( ) {
4476+ return false ;
4477+ }
4478+ let ty_lifetimes = ty_lifetimes. seen ;
4479+
4480+ #[ derive( Default ) ]
4481+ struct LifetimeChecker {
4482+ ty_lifetimes : FxHashSet < LocalDefId > ,
4483+ }
4484+ impl < ' v > Visitor < ' v > for LifetimeChecker {
4485+ type Result = ControlFlow < ( ) > ;
4486+ fn visit_lifetime ( & mut self , lifetime : & ' v Lifetime ) -> Self :: Result {
4487+ match lifetime. kind {
4488+ LifetimeKind :: Param ( def_id) => {
4489+ if self . ty_lifetimes . contains ( & def_id) {
4490+ ControlFlow :: Break ( ( ) )
4491+ } else {
4492+ ControlFlow :: Continue ( ( ) )
4493+ }
4494+ }
4495+ LifetimeKind :: ImplicitObjectLifetimeDefault
4496+ | LifetimeKind :: Error
4497+ | LifetimeKind :: Infer
4498+ | LifetimeKind :: Static => ControlFlow :: Continue ( ( ) ) ,
4499+ }
4500+ }
4501+ }
4502+
4503+ let mut checker = LifetimeChecker { ty_lifetimes } ;
4504+
4505+ // Pessimistic: if any of the lifetimes used in the type show up in where bounds
4506+ // don't allow this impl to be used.
4507+ self . generics
4508+ . predicates
4509+ . iter ( )
4510+ . all ( |pred| checker. visit_where_predicate ( pred) . is_continue ( ) )
4511+ }
4512+ }
4513+
44484514#[ derive( Debug , Clone , Copy , HashStable_Generic ) ]
44494515pub struct TraitImplHeader < ' hir > {
44504516 pub safety : Safety ,
0 commit comments