11use rustc_errors:: { Applicability , StashKey } ;
22use rustc_hir as hir;
33use 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 ;
85use rustc_middle:: ty:: print:: with_forced_trimmed_paths;
96use rustc_middle:: ty:: subst:: InternalSubsts ;
107use rustc_middle:: ty:: util:: IntTypeExt ;
@@ -14,7 +11,8 @@ use rustc_span::{Span, DUMMY_SP};
1411
1512use super :: ItemCtxt ;
1613use super :: { bad_placeholder, is_suggestable_infer_ty} ;
17- use crate :: errors:: UnconstrainedOpaqueType ;
14+
15+ mod opaque;
1816
1917fn anon_const_type_of < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> Ty < ' tcx > {
2018 use hir:: * ;
@@ -429,7 +427,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
429427 ItemKind :: OpaqueTy ( OpaqueTy {
430428 origin : hir:: OpaqueTyOrigin :: TyAlias { .. } ,
431429 ..
432- } ) => find_opaque_ty_constraints_for_tait ( tcx, def_id) ,
430+ } ) => opaque :: find_opaque_ty_constraints_for_tait ( tcx, def_id) ,
433431 // Opaque types desugared from `impl Trait`.
434432 ItemKind :: OpaqueTy ( OpaqueTy {
435433 origin :
@@ -443,7 +441,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
443441 "tried to get type of this RPITIT with no definition"
444442 ) ;
445443 }
446- find_opaque_ty_constraints_for_rpit ( tcx, def_id, owner)
444+ opaque :: find_opaque_ty_constraints_for_rpit ( tcx, def_id, owner)
447445 }
448446 ItemKind :: Trait ( ..)
449447 | ItemKind :: TraitAlias ( ..)
@@ -502,304 +500,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
502500 ty:: EarlyBinder ( output)
503501}
504502
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-
803503fn infer_placeholder_type < ' a > (
804504 tcx : TyCtxt < ' a > ,
805505 def_id : LocalDefId ,
0 commit comments