11use crate :: infer:: { InferCtxt , TyCtxtInferExt } ;
22use crate :: traits:: ObligationCause ;
3- use crate :: traits:: { self , ConstPatternStructural , TraitEngine } ;
3+ use crate :: traits:: { self , TraitEngine } ;
44
55use rustc_data_structures:: fx:: FxHashSet ;
66use rustc_hir as hir;
77use rustc_hir:: lang_items:: { StructuralPeqTraitLangItem , StructuralTeqTraitLangItem } ;
8+ use rustc_middle:: ty:: query:: Providers ;
89use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt , TypeFoldable , TypeVisitor } ;
910use rustc_span:: Span ;
1011
@@ -45,14 +46,14 @@ pub enum NonStructuralMatchTy<'tcx> {
4546/// that arose when the requirement was not enforced completely, see
4647/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
4748pub fn search_for_structural_match_violation < ' tcx > (
48- id : hir:: HirId ,
49+ _id : hir:: HirId ,
4950 span : Span ,
5051 tcx : TyCtxt < ' tcx > ,
5152 ty : Ty < ' tcx > ,
5253) -> Option < NonStructuralMatchTy < ' tcx > > {
5354 // FIXME: we should instead pass in an `infcx` from the outside.
5455 tcx. infer_ctxt ( ) . enter ( |infcx| {
55- let mut search = Search { id , span, infcx , found : None , seen : FxHashSet :: default ( ) } ;
56+ let mut search = Search { infcx , span, found : None , seen : FxHashSet :: default ( ) } ;
5657 ty. visit_with ( & mut search) ;
5758 search. found
5859 } )
@@ -65,27 +66,26 @@ pub fn search_for_structural_match_violation<'tcx>(
6566///
6667/// Note that this does *not* recursively check if the substructure of `adt_ty`
6768/// implements the traits.
68- pub fn type_marked_structural (
69- id : hir:: HirId ,
70- span : Span ,
69+ fn type_marked_structural (
7170 infcx : & InferCtxt < ' _ , ' tcx > ,
7271 adt_ty : Ty < ' tcx > ,
72+ cause : ObligationCause < ' tcx > ,
7373) -> bool {
7474 let mut fulfillment_cx = traits:: FulfillmentContext :: new ( ) ;
75- let cause = ObligationCause :: new ( span, id, ConstPatternStructural ) ;
7675 // require `#[derive(PartialEq)]`
77- let structural_peq_def_id = infcx. tcx . require_lang_item ( StructuralPeqTraitLangItem , Some ( span) ) ;
76+ let structural_peq_def_id =
77+ infcx. tcx . require_lang_item ( StructuralPeqTraitLangItem , Some ( cause. span ) ) ;
7878 fulfillment_cx. register_bound (
7979 infcx,
8080 ty:: ParamEnv :: empty ( ) ,
8181 adt_ty,
8282 structural_peq_def_id,
83- cause,
83+ cause. clone ( ) ,
8484 ) ;
8585 // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
8686 // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
87- let cause = ObligationCause :: new ( span , id , ConstPatternStructural ) ;
88- let structural_teq_def_id = infcx. tcx . require_lang_item ( StructuralTeqTraitLangItem , Some ( span) ) ;
87+ let structural_teq_def_id =
88+ infcx. tcx . require_lang_item ( StructuralTeqTraitLangItem , Some ( cause . span ) ) ;
8989 fulfillment_cx. register_bound (
9090 infcx,
9191 ty:: ParamEnv :: empty ( ) ,
@@ -110,7 +110,6 @@ pub fn type_marked_structural(
110110/// find instances of ADTs (specifically structs or enums) that do not implement
111111/// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
112112struct Search < ' a , ' tcx > {
113- id : hir:: HirId ,
114113 span : Span ,
115114
116115 infcx : InferCtxt < ' a , ' tcx > ,
@@ -129,7 +128,7 @@ impl Search<'a, 'tcx> {
129128 }
130129
131130 fn type_marked_structural ( & self , adt_ty : Ty < ' tcx > ) -> bool {
132- type_marked_structural ( self . id , self . span , & self . infcx , adt_ty )
131+ adt_ty . is_structural_eq_shallow ( self . tcx ( ) )
133132 }
134133}
135134
@@ -266,3 +265,12 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
266265 false
267266 }
268267}
268+
269+ pub fn provide ( providers : & mut Providers < ' _ > ) {
270+ providers. has_structural_eq_impls = |tcx, ty| {
271+ tcx. infer_ctxt ( ) . enter ( |infcx| {
272+ let cause = ObligationCause :: dummy ( ) ;
273+ type_marked_structural ( & infcx, ty, cause)
274+ } )
275+ } ;
276+ }
0 commit comments