1
1
use rustc_errors:: { Applicability , StashKey } ;
2
2
use rustc_hir as hir;
3
3
use rustc_hir:: def_id:: LocalDefId ;
4
- use rustc_hir:: intravisit;
5
- use rustc_hir:: intravisit:: Visitor ;
6
- use rustc_hir:: { HirId , Node } ;
7
- use rustc_middle:: hir:: nested_filter;
4
+ use rustc_hir:: HirId ;
8
5
use rustc_middle:: ty:: print:: with_forced_trimmed_paths;
9
6
use rustc_middle:: ty:: subst:: InternalSubsts ;
10
7
use rustc_middle:: ty:: util:: IntTypeExt ;
@@ -14,7 +11,8 @@ use rustc_span::{Span, DUMMY_SP};
14
11
15
12
use super :: ItemCtxt ;
16
13
use super :: { bad_placeholder, is_suggestable_infer_ty} ;
17
- use crate :: errors:: UnconstrainedOpaqueType ;
14
+
15
+ mod opaque;
18
16
19
17
fn anon_const_type_of < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> Ty < ' tcx > {
20
18
use hir:: * ;
@@ -429,7 +427,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
429
427
ItemKind :: OpaqueTy ( OpaqueTy {
430
428
origin : hir:: OpaqueTyOrigin :: TyAlias { .. } ,
431
429
..
432
- } ) => find_opaque_ty_constraints_for_tait ( tcx, def_id) ,
430
+ } ) => opaque :: find_opaque_ty_constraints_for_tait ( tcx, def_id) ,
433
431
// Opaque types desugared from `impl Trait`.
434
432
ItemKind :: OpaqueTy ( OpaqueTy {
435
433
origin :
@@ -443,7 +441,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
443
441
"tried to get type of this RPITIT with no definition"
444
442
) ;
445
443
}
446
- find_opaque_ty_constraints_for_rpit ( tcx, def_id, owner)
444
+ opaque :: find_opaque_ty_constraints_for_rpit ( tcx, def_id, owner)
447
445
}
448
446
ItemKind :: Trait ( ..)
449
447
| ItemKind :: TraitAlias ( ..)
@@ -502,304 +500,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
502
500
ty:: EarlyBinder ( output)
503
501
}
504
502
505
- #[ instrument( skip( tcx) , level = "debug" ) ]
506
- /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
507
- /// laid for "higher-order pattern unification".
508
- /// This ensures that inference is tractable.
509
- /// In particular, definitions of opaque types can only use other generics as arguments,
510
- /// and they cannot repeat an argument. Example:
511
- ///
512
- /// ```ignore (illustrative)
513
- /// type Foo<A, B> = impl Bar<A, B>;
514
- ///
515
- /// // Okay -- `Foo` is applied to two distinct, generic types.
516
- /// fn a<T, U>() -> Foo<T, U> { .. }
517
- ///
518
- /// // Not okay -- `Foo` is applied to `T` twice.
519
- /// fn b<T>() -> Foo<T, T> { .. }
520
- ///
521
- /// // Not okay -- `Foo` is applied to a non-generic type.
522
- /// fn b<T>() -> Foo<T, u32> { .. }
523
- /// ```
524
- ///
525
- fn find_opaque_ty_constraints_for_tait ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Ty < ' _ > {
526
- use rustc_hir:: { Expr , ImplItem , Item , TraitItem } ;
527
-
528
- struct ConstraintLocator < ' tcx > {
529
- tcx : TyCtxt < ' tcx > ,
530
-
531
- /// def_id of the opaque type whose defining uses are being checked
532
- def_id : LocalDefId ,
533
-
534
- /// as we walk the defining uses, we are checking that all of them
535
- /// define the same hidden type. This variable is set to `Some`
536
- /// with the first type that we find, and then later types are
537
- /// checked against it (we also carry the span of that first
538
- /// type).
539
- found : Option < ty:: OpaqueHiddenType < ' tcx > > ,
540
-
541
- /// In the presence of dead code, typeck may figure out a hidden type
542
- /// while borrowck will not. We collect these cases here and check at
543
- /// the end that we actually found a type that matches (modulo regions).
544
- typeck_types : Vec < ty:: OpaqueHiddenType < ' tcx > > ,
545
- }
546
-
547
- impl ConstraintLocator < ' _ > {
548
- #[ instrument( skip( self ) , level = "debug" ) ]
549
- fn check ( & mut self , item_def_id : LocalDefId ) {
550
- // Don't try to check items that cannot possibly constrain the type.
551
- if !self . tcx . has_typeck_results ( item_def_id) {
552
- debug ! ( "no constraint: no typeck results" ) ;
553
- return ;
554
- }
555
- // Calling `mir_borrowck` can lead to cycle errors through
556
- // const-checking, avoid calling it if we don't have to.
557
- // ```rust
558
- // type Foo = impl Fn() -> usize; // when computing type for this
559
- // const fn bar() -> Foo {
560
- // || 0usize
561
- // }
562
- // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
563
- // // because we again need to reveal `Foo` so we can check whether the
564
- // // constant does not contain interior mutability.
565
- // ```
566
- let tables = self . tcx . typeck ( item_def_id) ;
567
- if let Some ( guar) = tables. tainted_by_errors {
568
- self . found =
569
- Some ( ty:: OpaqueHiddenType { span : DUMMY_SP , ty : self . tcx . ty_error ( guar) } ) ;
570
- return ;
571
- }
572
- let Some ( & typeck_hidden_ty) = tables. concrete_opaque_types . get ( & self . def_id ) else {
573
- debug ! ( "no constraints in typeck results" ) ;
574
- return ;
575
- } ;
576
- if self . typeck_types . iter ( ) . all ( |prev| prev. ty != typeck_hidden_ty. ty ) {
577
- self . typeck_types . push ( typeck_hidden_ty) ;
578
- }
579
-
580
- // Use borrowck to get the type with unerased regions.
581
- let concrete_opaque_types = & self . tcx . mir_borrowck ( item_def_id) . concrete_opaque_types ;
582
- debug ! ( ?concrete_opaque_types) ;
583
- if let Some ( & concrete_type) = concrete_opaque_types. get ( & self . def_id ) {
584
- debug ! ( ?concrete_type, "found constraint" ) ;
585
- if let Some ( prev) = & mut self . found {
586
- if concrete_type. ty != prev. ty && !( concrete_type, prev. ty ) . references_error ( ) {
587
- let guar =
588
- prev. report_mismatch ( & concrete_type, self . def_id , self . tcx ) . emit ( ) ;
589
- prev. ty = self . tcx . ty_error ( guar) ;
590
- }
591
- } else {
592
- self . found = Some ( concrete_type) ;
593
- }
594
- }
595
- }
596
- }
597
-
598
- impl < ' tcx > intravisit:: Visitor < ' tcx > for ConstraintLocator < ' tcx > {
599
- type NestedFilter = nested_filter:: All ;
600
-
601
- fn nested_visit_map ( & mut self ) -> Self :: Map {
602
- self . tcx . hir ( )
603
- }
604
- fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
605
- if let hir:: ExprKind :: Closure ( closure) = ex. kind {
606
- self . check ( closure. def_id ) ;
607
- }
608
- intravisit:: walk_expr ( self , ex) ;
609
- }
610
- fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
611
- trace ! ( ?it. owner_id) ;
612
- // The opaque type itself or its children are not within its reveal scope.
613
- if it. owner_id . def_id != self . def_id {
614
- self . check ( it. owner_id . def_id ) ;
615
- intravisit:: walk_item ( self , it) ;
616
- }
617
- }
618
- fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
619
- trace ! ( ?it. owner_id) ;
620
- // The opaque type itself or its children are not within its reveal scope.
621
- if it. owner_id . def_id != self . def_id {
622
- self . check ( it. owner_id . def_id ) ;
623
- intravisit:: walk_impl_item ( self , it) ;
624
- }
625
- }
626
- fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
627
- trace ! ( ?it. owner_id) ;
628
- self . check ( it. owner_id . def_id ) ;
629
- intravisit:: walk_trait_item ( self , it) ;
630
- }
631
- }
632
-
633
- let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
634
- let scope = tcx. hir ( ) . get_defining_scope ( hir_id) ;
635
- let mut locator = ConstraintLocator { def_id, tcx, found : None , typeck_types : vec ! [ ] } ;
636
-
637
- debug ! ( ?scope) ;
638
-
639
- if scope == hir:: CRATE_HIR_ID {
640
- tcx. hir ( ) . walk_toplevel_module ( & mut locator) ;
641
- } else {
642
- trace ! ( "scope={:#?}" , tcx. hir( ) . get( scope) ) ;
643
- match tcx. hir ( ) . get ( scope) {
644
- // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
645
- // This allows our visitor to process the defining item itself, causing
646
- // it to pick up any 'sibling' defining uses.
647
- //
648
- // For example, this code:
649
- // ```
650
- // fn foo() {
651
- // type Blah = impl Debug;
652
- // let my_closure = || -> Blah { true };
653
- // }
654
- // ```
655
- //
656
- // requires us to explicitly process `foo()` in order
657
- // to notice the defining usage of `Blah`.
658
- Node :: Item ( it) => locator. visit_item ( it) ,
659
- Node :: ImplItem ( it) => locator. visit_impl_item ( it) ,
660
- Node :: TraitItem ( it) => locator. visit_trait_item ( it) ,
661
- other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
662
- }
663
- }
664
-
665
- let Some ( hidden) = locator. found else {
666
- let reported = tcx. sess . emit_err ( UnconstrainedOpaqueType {
667
- span : tcx. def_span ( def_id) ,
668
- name : tcx. item_name ( tcx. local_parent ( def_id) . to_def_id ( ) ) ,
669
- what : match tcx. hir ( ) . get ( scope) {
670
- _ if scope == hir:: CRATE_HIR_ID => "module" ,
671
- Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Mod ( _) , .. } ) => "module" ,
672
- Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Impl ( _) , .. } ) => "impl" ,
673
- _ => "item" ,
674
- } ,
675
- } ) ;
676
- return tcx. ty_error ( reported) ;
677
- } ;
678
-
679
- // Only check against typeck if we didn't already error
680
- if !hidden. ty . references_error ( ) {
681
- for concrete_type in locator. typeck_types {
682
- if concrete_type. ty != tcx. erase_regions ( hidden. ty )
683
- && !( concrete_type, hidden) . references_error ( )
684
- {
685
- hidden. report_mismatch ( & concrete_type, def_id, tcx) . emit ( ) ;
686
- }
687
- }
688
- }
689
-
690
- hidden. ty
691
- }
692
-
693
- fn find_opaque_ty_constraints_for_rpit (
694
- tcx : TyCtxt < ' _ > ,
695
- def_id : LocalDefId ,
696
- owner_def_id : LocalDefId ,
697
- ) -> Ty < ' _ > {
698
- use rustc_hir:: { Expr , ImplItem , Item , TraitItem } ;
699
-
700
- struct ConstraintChecker < ' tcx > {
701
- tcx : TyCtxt < ' tcx > ,
702
-
703
- /// def_id of the opaque type whose defining uses are being checked
704
- def_id : LocalDefId ,
705
-
706
- found : ty:: OpaqueHiddenType < ' tcx > ,
707
- }
708
-
709
- impl ConstraintChecker < ' _ > {
710
- #[ instrument( skip( self ) , level = "debug" ) ]
711
- fn check ( & self , def_id : LocalDefId ) {
712
- // Use borrowck to get the type with unerased regions.
713
- let concrete_opaque_types = & self . tcx . mir_borrowck ( def_id) . concrete_opaque_types ;
714
- debug ! ( ?concrete_opaque_types) ;
715
- for ( & def_id, & concrete_type) in concrete_opaque_types {
716
- if def_id != self . def_id {
717
- // Ignore constraints for other opaque types.
718
- continue ;
719
- }
720
-
721
- debug ! ( ?concrete_type, "found constraint" ) ;
722
-
723
- if concrete_type. ty != self . found . ty
724
- && !( concrete_type, self . found ) . references_error ( )
725
- {
726
- self . found . report_mismatch ( & concrete_type, self . def_id , self . tcx ) . emit ( ) ;
727
- }
728
- }
729
- }
730
- }
731
-
732
- impl < ' tcx > intravisit:: Visitor < ' tcx > for ConstraintChecker < ' tcx > {
733
- type NestedFilter = nested_filter:: OnlyBodies ;
734
-
735
- fn nested_visit_map ( & mut self ) -> Self :: Map {
736
- self . tcx . hir ( )
737
- }
738
- fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
739
- if let hir:: ExprKind :: Closure ( closure) = ex. kind {
740
- self . check ( closure. def_id ) ;
741
- }
742
- intravisit:: walk_expr ( self , ex) ;
743
- }
744
- fn visit_item ( & mut self , it : & ' tcx Item < ' tcx > ) {
745
- trace ! ( ?it. owner_id) ;
746
- // The opaque type itself or its children are not within its reveal scope.
747
- if it. owner_id . def_id != self . def_id {
748
- self . check ( it. owner_id . def_id ) ;
749
- intravisit:: walk_item ( self , it) ;
750
- }
751
- }
752
- fn visit_impl_item ( & mut self , it : & ' tcx ImplItem < ' tcx > ) {
753
- trace ! ( ?it. owner_id) ;
754
- // The opaque type itself or its children are not within its reveal scope.
755
- if it. owner_id . def_id != self . def_id {
756
- self . check ( it. owner_id . def_id ) ;
757
- intravisit:: walk_impl_item ( self , it) ;
758
- }
759
- }
760
- fn visit_trait_item ( & mut self , it : & ' tcx TraitItem < ' tcx > ) {
761
- trace ! ( ?it. owner_id) ;
762
- self . check ( it. owner_id . def_id ) ;
763
- intravisit:: walk_trait_item ( self , it) ;
764
- }
765
- }
766
-
767
- let concrete = tcx. mir_borrowck ( owner_def_id) . concrete_opaque_types . get ( & def_id) . copied ( ) ;
768
-
769
- if let Some ( concrete) = concrete {
770
- let scope = tcx. hir ( ) . local_def_id_to_hir_id ( owner_def_id) ;
771
- debug ! ( ?scope) ;
772
- let mut locator = ConstraintChecker { def_id, tcx, found : concrete } ;
773
-
774
- match tcx. hir ( ) . get ( scope) {
775
- Node :: Item ( it) => intravisit:: walk_item ( & mut locator, it) ,
776
- Node :: ImplItem ( it) => intravisit:: walk_impl_item ( & mut locator, it) ,
777
- Node :: TraitItem ( it) => intravisit:: walk_trait_item ( & mut locator, it) ,
778
- other => bug ! ( "{:?} is not a valid scope for an opaque type item" , other) ,
779
- }
780
- }
781
-
782
- concrete. map ( |concrete| concrete. ty ) . unwrap_or_else ( || {
783
- let table = tcx. typeck ( owner_def_id) ;
784
- if let Some ( guar) = table. tainted_by_errors {
785
- // Some error in the
786
- // owner fn prevented us from populating
787
- // the `concrete_opaque_types` table.
788
- tcx. ty_error ( guar)
789
- } else {
790
- table. concrete_opaque_types . get ( & def_id) . map ( |ty| ty. ty ) . unwrap_or_else ( || {
791
- // We failed to resolve the opaque type or it
792
- // resolves to itself. We interpret this as the
793
- // no values of the hidden type ever being constructed,
794
- // so we can just make the hidden type be `!`.
795
- // For backwards compatibility reasons, we fall back to
796
- // `()` until we the diverging default is changed.
797
- tcx. mk_diverging_default ( )
798
- } )
799
- }
800
- } )
801
- }
802
-
803
503
fn infer_placeholder_type < ' a > (
804
504
tcx : TyCtxt < ' a > ,
805
505
def_id : LocalDefId ,
0 commit comments