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