@@ -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,143 @@ 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, and in case it is in a nested opaque type, find that opaque type's
508+ // usage in the function signature and use the generic arguments from the usage site.
509+ let mut hidden_ty = tcx. type_of ( key. def_id ) . instantiate ( tcx, key. args ) ;
510+ if let hir:: OpaqueTyOrigin :: FnReturn ( ..) | hir:: OpaqueTyOrigin :: AsyncFn ( ..) = origin {
511+ if hidden_ty != ty. ty {
512+ hidden_ty = find_and_apply_rpit_substs (
513+ tcx,
514+ hidden_ty,
515+ defining_use_anchor. to_def_id ( ) ,
516+ key. def_id . to_def_id ( ) ,
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+ fn find_and_apply_rpit_substs < ' tcx > (
531+ tcx : TyCtxt < ' tcx > ,
532+ mut hidden_ty : Ty < ' tcx > ,
533+ function : DefId ,
534+ opaque : DefId ,
535+ ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
536+ // Find use of the RPIT in the function signature and thus find the right substs to
537+ // convert it into the parameter space of the function signature. This is needed,
538+ // because that's what `type_of` returns, against which we compare later.
539+ let ret = tcx. fn_sig ( function) . instantiate_identity ( ) . output ( ) ;
540+ struct Visitor < ' tcx > {
541+ tcx : TyCtxt < ' tcx > ,
542+ opaque : DefId ,
543+ function : DefId ,
544+ seen : FxHashSet < DefId > ,
545+ }
546+ impl < ' tcx > ty:: TypeVisitor < TyCtxt < ' tcx > > for Visitor < ' tcx > {
547+ type BreakTy = GenericArgsRef < ' tcx > ;
548+
549+ #[ instrument( level = "trace" , skip( self ) , ret) ]
550+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
551+ trace ! ( "{:#?}" , t. kind( ) ) ;
552+ match t. kind ( ) {
553+ ty:: Alias ( ty:: Opaque , alias) => {
554+ trace ! ( ?alias. def_id) ;
555+ if alias. def_id == self . opaque {
556+ return ControlFlow :: Break ( alias. args ) ;
557+ } else if self . seen . insert ( alias. def_id ) {
558+ for clause in self
559+ . tcx
560+ . explicit_item_bounds ( alias. def_id )
561+ . iter_instantiated_copied ( self . tcx , alias. args )
562+ {
563+ trace ! ( ?clause) ;
564+ clause. visit_with ( self ) ?;
565+ }
566+ }
567+ }
568+ ty:: Alias ( ty:: Projection , alias) => {
569+ if self . tcx . is_impl_trait_in_trait ( alias. def_id )
570+ && self . tcx . impl_trait_in_trait_parent_fn ( alias. def_id ) == self . function
571+ {
572+ // If we're lowering to associated item, install the opaque type which is just
573+ // the `type_of` of the trait's associated item. If we're using the old lowering
574+ // strategy, then just reinterpret the associated type like an opaque :^)
575+ self . tcx
576+ . type_of ( alias. def_id )
577+ . instantiate ( self . tcx , alias. args )
578+ . visit_with ( self ) ?;
579+ }
580+ }
581+ ty:: Alias ( ty:: Weak , alias) => {
582+ self . tcx
583+ . type_of ( alias. def_id )
584+ . instantiate ( self . tcx , alias. args )
585+ . visit_with ( self ) ?;
586+ }
587+ _ => ( ) ,
588+ }
589+
590+ t. super_visit_with ( self )
591+ }
592+ }
593+ if let ControlFlow :: Break ( args) =
594+ ret. visit_with ( & mut Visitor { tcx, function, opaque, seen : Default :: default ( ) } )
595+ {
596+ trace ! ( ?args) ;
597+ trace ! ( "expected: {hidden_ty:#?}" ) ;
598+ hidden_ty = ty:: EarlyBinder :: bind ( hidden_ty) . instantiate ( tcx, args) ;
599+ trace ! ( "expected: {hidden_ty:#?}" ) ;
600+ } else {
601+ tcx. sess
602+ . delay_span_bug ( tcx. def_span ( function) , format ! ( "{ret:?} does not contain {opaque:?}" ) ) ;
603+ }
604+ Ok ( hidden_ty)
605+ }
606+
472607fn is_enum_of_nonnullable_ptr < ' tcx > (
473608 tcx : TyCtxt < ' tcx > ,
474609 adt_def : AdtDef < ' tcx > ,
0 commit comments