@@ -51,7 +51,7 @@ use syntax::symbol::{kw, sym, Symbol};
51
51
use syntax_pos:: Span ;
52
52
53
53
use smallvec;
54
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
54
+ use rustc_data_structures:: fx:: { FxIndexMap } ;
55
55
use rustc_data_structures:: stable_hasher:: { StableHasher , HashStable } ;
56
56
use rustc_index:: vec:: { Idx , IndexVec } ;
57
57
@@ -84,6 +84,10 @@ pub use self::context::{
84
84
85
85
pub use self :: instance:: { Instance , InstanceDef } ;
86
86
87
+ pub use self :: structural_match:: search_for_structural_match_violation;
88
+ pub use self :: structural_match:: type_marked_structural;
89
+ pub use self :: structural_match:: NonStructuralMatchTy ;
90
+
87
91
pub use self :: trait_def:: TraitDef ;
88
92
89
93
pub use self :: query:: queries;
@@ -116,6 +120,7 @@ pub mod util;
116
120
mod context;
117
121
mod instance;
118
122
mod structural_impls;
123
+ mod structural_match;
119
124
mod sty;
120
125
121
126
// Data types
@@ -3396,130 +3401,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
3396
3401
fn_like. asyncness ( )
3397
3402
}
3398
3403
3399
- pub enum NonStructuralMatchTy < ' tcx > {
3400
- Adt ( & ' tcx AdtDef ) ,
3401
- Param ,
3402
- }
3403
-
3404
- /// This method traverses the structure of `ty`, trying to find an
3405
- /// instance of an ADT (i.e. struct or enum) that was declared without
3406
- /// the `#[structural_match]` attribute, or a generic type parameter
3407
- /// (which cannot be determined to be `structural_match`).
3408
- ///
3409
- /// The "structure of a type" includes all components that would be
3410
- /// considered when doing a pattern match on a constant of that
3411
- /// type.
3412
- ///
3413
- /// * This means this method descends into fields of structs/enums,
3414
- /// and also descends into the inner type `T` of `&T` and `&mut T`
3415
- ///
3416
- /// * The traversal doesn't dereference unsafe pointers (`*const T`,
3417
- /// `*mut T`), and it does not visit the type arguments of an
3418
- /// instantiated generic like `PhantomData<T>`.
3419
- ///
3420
- /// The reason we do this search is Rust currently require all ADTs
3421
- /// reachable from a constant's type to be annotated with
3422
- /// `#[structural_match]`, an attribute which essentially says that
3423
- /// the implementation of `PartialEq::eq` behaves *equivalently* to a
3424
- /// comparison against the unfolded structure.
3425
- ///
3426
- /// For more background on why Rust has this requirement, and issues
3427
- /// that arose when the requirement was not enforced completely, see
3428
- /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
3429
- pub fn search_for_structural_match_violation < ' tcx > (
3430
- tcx : TyCtxt < ' tcx > ,
3431
- ty : Ty < ' tcx > ,
3432
- ) -> Option < NonStructuralMatchTy < ' tcx > > {
3433
- let mut search = Search { tcx, found : None , seen : FxHashSet :: default ( ) } ;
3434
- ty. visit_with ( & mut search) ;
3435
- return search. found ;
3436
-
3437
- struct Search < ' tcx > {
3438
- tcx : TyCtxt < ' tcx > ,
3439
-
3440
- // Records the first ADT or type parameter we find without `#[structural_match`.
3441
- found : Option < NonStructuralMatchTy < ' tcx > > ,
3442
-
3443
- // Tracks ADTs previously encountered during search, so that
3444
- // we will not recurse on them again.
3445
- seen : FxHashSet < hir:: def_id:: DefId > ,
3446
- }
3447
-
3448
- impl < ' tcx > TypeVisitor < ' tcx > for Search < ' tcx > {
3449
- fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> bool {
3450
- debug ! ( "Search visiting ty: {:?}" , ty) ;
3451
-
3452
- let ( adt_def, substs) = match ty. kind {
3453
- ty:: Adt ( adt_def, substs) => ( adt_def, substs) ,
3454
- ty:: Param ( _) => {
3455
- self . found = Some ( NonStructuralMatchTy :: Param ) ;
3456
- return true ; // Stop visiting.
3457
- }
3458
- ty:: RawPtr ( ..) => {
3459
- // `#[structural_match]` ignores substructure of
3460
- // `*const _`/`*mut _`, so skip super_visit_with
3461
- //
3462
- // (But still tell caller to continue search.)
3463
- return false ;
3464
- }
3465
- ty:: FnDef ( ..) | ty:: FnPtr ( ..) => {
3466
- // types of formals and return in `fn(_) -> _` are also irrelevant
3467
- //
3468
- // (But still tell caller to continue search.)
3469
- return false ;
3470
- }
3471
- ty:: Array ( _, n) if n. try_eval_usize ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) == Some ( 0 )
3472
- => {
3473
- // rust-lang/rust#62336: ignore type of contents
3474
- // for empty array.
3475
- return false ;
3476
- }
3477
- _ => {
3478
- ty. super_visit_with ( self ) ;
3479
- return false ;
3480
- }
3481
- } ;
3482
-
3483
- if !self . tcx . has_attr ( adt_def. did , sym:: structural_match) {
3484
- self . found = Some ( NonStructuralMatchTy :: Adt ( & adt_def) ) ;
3485
- debug ! ( "Search found adt_def: {:?}" , adt_def) ;
3486
- return true ; // Stop visiting.
3487
- }
3488
-
3489
- if !self . seen . insert ( adt_def. did ) {
3490
- debug ! ( "Search already seen adt_def: {:?}" , adt_def) ;
3491
- // let caller continue its search
3492
- return false ;
3493
- }
3494
-
3495
- // `#[structural_match]` does not care about the
3496
- // instantiation of the generics in an ADT (it
3497
- // instead looks directly at its fields outside
3498
- // this match), so we skip super_visit_with.
3499
- //
3500
- // (Must not recur on substs for `PhantomData<T>` cf
3501
- // rust-lang/rust#55028 and rust-lang/rust#55837; but also
3502
- // want to skip substs when only uses of generic are
3503
- // behind unsafe pointers `*const T`/`*mut T`.)
3504
-
3505
- // even though we skip super_visit_with, we must recur on
3506
- // fields of ADT.
3507
- let tcx = self . tcx ;
3508
- for field_ty in adt_def. all_fields ( ) . map ( |field| field. ty ( tcx, substs) ) {
3509
- if field_ty. visit_with ( self ) {
3510
- // found an ADT without `#[structural_match]`; halt visiting!
3511
- assert ! ( self . found. is_some( ) ) ;
3512
- return true ;
3513
- }
3514
- }
3515
-
3516
- // Even though we do not want to recur on substs, we do
3517
- // want our caller to continue its own search.
3518
- false
3519
- }
3520
- }
3521
- }
3522
-
3523
3404
pub fn provide ( providers : & mut ty:: query:: Providers < ' _ > ) {
3524
3405
context:: provide ( providers) ;
3525
3406
erase_regions:: provide ( providers) ;
0 commit comments