@@ -19,11 +19,13 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
1919use rustc_middle:: hir:: nested_filter;
2020use rustc_middle:: middle:: stability:: EvalResult ;
2121use rustc_middle:: traits:: DefiningAnchor ;
22+ use rustc_middle:: ty:: fold:: BottomUpFolder ;
2223use rustc_middle:: ty:: layout:: { LayoutError , MAX_SIMD_LANES } ;
2324use rustc_middle:: ty:: util:: { Discr , IntTypeExt } ;
2425use rustc_middle:: ty:: GenericArgKind ;
2526use rustc_middle:: ty:: {
26- self , AdtDef , ParamEnv , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
27+ self , AdtDef , ParamEnv , RegionKind , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable ,
28+ TypeVisitableExt ,
2729} ;
2830use rustc_session:: lint:: builtin:: { UNINHABITED_STATIC , UNSUPPORTED_CALLING_CONVENTIONS } ;
2931use rustc_span:: symbol:: sym;
@@ -34,6 +36,7 @@ use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplem
3436use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt as _;
3537use rustc_trait_selection:: traits:: outlives_bounds:: InferCtxtExt as _;
3638use rustc_trait_selection:: traits:: { self , ObligationCtxt , TraitEngine , TraitEngineExt as _} ;
39+ use rustc_type_ir:: fold:: TypeFoldable ;
3740
3841use std:: ops:: ControlFlow ;
3942
@@ -437,7 +440,7 @@ fn check_opaque_meets_bounds<'tcx>(
437440 // hidden type is well formed even without those bounds.
438441 let predicate =
439442 ty:: Binder :: dummy ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: WellFormed ( hidden_ty. into ( ) ) ) ) ;
440- ocx. register_obligation ( Obligation :: new ( tcx, misc_cause, param_env, predicate) ) ;
443+ ocx. register_obligation ( Obligation :: new ( tcx, misc_cause. clone ( ) , param_env, predicate) ) ;
441444
442445 // Check that all obligations are satisfied by the implementation's
443446 // version.
@@ -464,11 +467,179 @@ fn check_opaque_meets_bounds<'tcx>(
464467 ocx. resolve_regions_and_report_errors ( defining_use_anchor, & outlives_env) ?;
465468 }
466469 }
467- // Clean up after ourselves
468- let _ = infcx. take_opaque_types ( ) ;
470+ // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
471+ for ( key, mut ty) in infcx. take_opaque_types ( ) {
472+ ty. hidden_type . ty = infcx. resolve_vars_if_possible ( ty. hidden_type . ty ) ;
473+ sanity_check_found_hidden_type ( tcx, key, ty. hidden_type , defining_use_anchor, origin) ?;
474+ }
469475 Ok ( ( ) )
470476}
471477
478+ fn sanity_check_found_hidden_type < ' tcx > (
479+ tcx : TyCtxt < ' tcx > ,
480+ key : ty:: OpaqueTypeKey < ' tcx > ,
481+ mut ty : ty:: OpaqueHiddenType < ' tcx > ,
482+ defining_use_anchor : LocalDefId ,
483+ origin : & hir:: OpaqueTyOrigin ,
484+ ) -> Result < ( ) , ErrorGuaranteed > {
485+ if ty. ty . is_ty_var ( ) {
486+ // Nothing was actually constrained.
487+ return Ok ( ( ) ) ;
488+ }
489+ if let ty:: Alias ( ty:: Opaque , alias) = ty. ty . kind ( ) {
490+ if alias. def_id == key. def_id . to_def_id ( ) && alias. args == key. args {
491+ // Nothing was actually constrained, this is an opaque usage that was
492+ // only discovered to be opaque after inference vars resolved.
493+ return Ok ( ( ) ) ;
494+ }
495+ }
496+ // Closures frequently end up containing erased lifetimes in their final representation.
497+ // These correspond to lifetime variables that never got resolved, so we patch this up here.
498+ ty. ty = ty. ty . fold_with ( & mut BottomUpFolder {
499+ tcx,
500+ ty_op : |t| t,
501+ ct_op : |c| c,
502+ lt_op : |l| match l. kind ( ) {
503+ RegionKind :: ReVar ( _) => tcx. lifetimes . re_erased ,
504+ _ => l,
505+ } ,
506+ } ) ;
507+ // Get the hidden type.
508+ let mut hidden_ty = tcx. type_of ( key. def_id ) . instantiate ( tcx, key. args ) ;
509+ if let hir:: OpaqueTyOrigin :: FnReturn ( ..) | hir:: OpaqueTyOrigin :: AsyncFn ( ..) = origin {
510+ if hidden_ty != ty. ty {
511+ hidden_ty = find_and_apply_rpit_args (
512+ tcx,
513+ hidden_ty,
514+ defining_use_anchor. to_def_id ( ) ,
515+ key. def_id . to_def_id ( ) ,
516+ ) ?;
517+ }
518+ }
519+
520+ // If the hidden types differ, emit a type mismatch diagnostic.
521+ if hidden_ty == ty. ty {
522+ Ok ( ( ) )
523+ } else {
524+ let span = tcx. def_span ( key. def_id ) ;
525+ let other = ty:: OpaqueHiddenType { ty : hidden_ty, span } ;
526+ Err ( ty. report_mismatch ( & other, key. def_id , tcx) . emit ( ) )
527+ }
528+ }
529+
530+ /// In case it is in a nested opaque type, find that opaque type's
531+ /// usage in the function signature and use the generic arguments from the usage site.
532+ /// We need to do because RPITs ignore the lifetimes of the function,
533+ /// as they have their own copies of all the lifetimes they capture.
534+ /// So the only way to get the lifetimes represented in terms of the function,
535+ /// is to look how they are used in the function signature (or do some other fancy
536+ /// recording of this mapping at ast -> hir lowering time).
537+ ///
538+ /// As an example:
539+ /// ```text
540+ /// trait Id {
541+ /// type Assoc;
542+ /// }
543+ /// impl<'a> Id for &'a () {
544+ /// type Assoc = &'a ();
545+ /// }
546+ /// fn func<'a>(x: &'a ()) -> impl Id<Assoc = impl Sized + 'a> { x }
547+ /// // desugared to
548+ /// fn func<'a>(x: &'a () -> Outer<'a> where <Outer<'a> as Id>::Assoc = Inner<'a> {
549+ /// // Note that in contrast to other nested items, RPIT type aliases can
550+ /// // access their parents' generics.
551+ ///
552+ /// // hidden type is `&'aDupOuter ()`
553+ /// // During wfcheck the hidden type of `Inner<'aDupOuter>` is `&'a ()`, but
554+ /// // `typeof(Inner<'aDupOuter>) = &'aDupOuter ()`.
555+ /// // So we walk the signature of `func` to find the use of `Inner<'a>`
556+ /// // and then use that to replace the lifetimes in the hidden type, obtaining
557+ /// // `&'a ()`.
558+ /// type Outer<'aDupOuter> = impl Id<Assoc = Inner<'aDupOuter>>;
559+ ///
560+ /// // hidden type is `&'aDupInner ()`
561+ /// type Inner<'aDupInner> = impl Sized + 'aDupInner;
562+ ///
563+ /// x
564+ /// }
565+ /// ```
566+ fn find_and_apply_rpit_args < ' tcx > (
567+ tcx : TyCtxt < ' tcx > ,
568+ mut hidden_ty : Ty < ' tcx > ,
569+ function : DefId ,
570+ opaque : DefId ,
571+ ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
572+ // Find use of the RPIT in the function signature and thus find the right args to
573+ // convert it into the parameter space of the function signature. This is needed,
574+ // because that's what `type_of` returns, against which we compare later.
575+ let ret = tcx. fn_sig ( function) . instantiate_identity ( ) . output ( ) ;
576+ struct Visitor < ' tcx > {
577+ tcx : TyCtxt < ' tcx > ,
578+ opaque : DefId ,
579+ function : DefId ,
580+ seen : FxHashSet < DefId > ,
581+ }
582+ impl < ' tcx > ty:: TypeVisitor < TyCtxt < ' tcx > > for Visitor < ' tcx > {
583+ type BreakTy = GenericArgsRef < ' tcx > ;
584+
585+ #[ instrument( level = "trace" , skip( self ) , ret) ]
586+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
587+ trace ! ( "{:#?}" , t. kind( ) ) ;
588+ match t. kind ( ) {
589+ ty:: Alias ( ty:: Opaque , alias) => {
590+ trace ! ( ?alias. def_id) ;
591+ if alias. def_id == self . opaque {
592+ return ControlFlow :: Break ( alias. args ) ;
593+ } else if self . seen . insert ( alias. def_id ) {
594+ for clause in self
595+ . tcx
596+ . explicit_item_bounds ( alias. def_id )
597+ . iter_instantiated_copied ( self . tcx , alias. args )
598+ {
599+ trace ! ( ?clause) ;
600+ clause. visit_with ( self ) ?;
601+ }
602+ }
603+ }
604+ ty:: Alias ( ty:: Projection , alias) => {
605+ if self . tcx . is_impl_trait_in_trait ( alias. def_id )
606+ && self . tcx . impl_trait_in_trait_parent_fn ( alias. def_id ) == self . function
607+ {
608+ // If we're lowering to associated item, install the opaque type which is just
609+ // the `type_of` of the trait's associated item. If we're using the old lowering
610+ // strategy, then just reinterpret the associated type like an opaque :^)
611+ self . tcx
612+ . type_of ( alias. def_id )
613+ . instantiate ( self . tcx , alias. args )
614+ . visit_with ( self ) ?;
615+ }
616+ }
617+ ty:: Alias ( ty:: Weak , alias) => {
618+ self . tcx
619+ . type_of ( alias. def_id )
620+ . instantiate ( self . tcx , alias. args )
621+ . visit_with ( self ) ?;
622+ }
623+ _ => ( ) ,
624+ }
625+
626+ t. super_visit_with ( self )
627+ }
628+ }
629+ if let ControlFlow :: Break ( args) =
630+ ret. visit_with ( & mut Visitor { tcx, function, opaque, seen : Default :: default ( ) } )
631+ {
632+ trace ! ( ?args) ;
633+ trace ! ( "expected: {hidden_ty:#?}" ) ;
634+ hidden_ty = ty:: EarlyBinder :: bind ( hidden_ty) . instantiate ( tcx, args) ;
635+ trace ! ( "expected: {hidden_ty:#?}" ) ;
636+ } else {
637+ tcx. sess
638+ . delay_span_bug ( tcx. def_span ( function) , format ! ( "{ret:?} does not contain {opaque:?}" ) ) ;
639+ }
640+ Ok ( hidden_ty)
641+ }
642+
472643fn is_enum_of_nonnullable_ptr < ' tcx > (
473644 tcx : TyCtxt < ' tcx > ,
474645 adt_def : AdtDef < ' tcx > ,
0 commit comments