@@ -30,75 +30,26 @@ where
3030 ) -> QueryResult < I > {
3131 self . set_is_normalizes_to_goal ( ) ;
3232 debug_assert ! ( self . term_is_fully_unconstrained( goal) ) ;
33- let normalize_result = self
34- . probe ( |& result| ProbeKind :: TryNormalizeNonRigid { result } )
35- . enter ( |this| this. normalize_at_least_one_step ( goal) ) ;
36-
37- match normalize_result {
38- Ok ( res) => Ok ( res) ,
39- Err ( NoSolution ) => {
40- self . probe ( |& result| ProbeKind :: RigidAlias { result } ) . enter ( |this| {
41- let Goal { param_env, predicate : NormalizesTo { alias, term } } = goal;
42- this. add_rigid_constraints ( param_env, alias) ?;
43- this. relate_rigid_alias_non_alias ( param_env, alias, ty:: Invariant , term) ?;
44- this. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
45- } )
46- }
47- }
48- }
49-
50- /// Register any obligations that are used to validate that an alias should be
51- /// treated as rigid.
52- ///
53- /// An alias may be considered rigid if it fails normalization, but we also don't
54- /// want to consider aliases that are not well-formed to be rigid simply because
55- /// they fail normalization.
56- ///
57- /// For example, some `<T as Trait>::Assoc` where `T: Trait` does not hold, or an
58- /// opaque type whose hidden type doesn't actually satisfy the opaque item bounds.
59- fn add_rigid_constraints (
60- & mut self ,
61- param_env : I :: ParamEnv ,
62- rigid_alias : ty:: AliasTerm < I > ,
63- ) -> Result < ( ) , NoSolution > {
64- let cx = self . cx ( ) ;
65- match rigid_alias. kind ( cx) {
66- // Projections are rigid only if their trait ref holds,
67- // and the GAT where-clauses hold.
68- ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst => {
69- let trait_ref = rigid_alias. trait_ref ( cx) ;
70- self . add_goal ( GoalSource :: AliasWellFormed , Goal :: new ( cx, param_env, trait_ref) ) ;
71- Ok ( ( ) )
72- }
73- ty:: AliasTermKind :: OpaqueTy => {
74- if self . opaque_type_is_rigid ( rigid_alias. def_id ) {
75- Ok ( ( ) )
76- } else {
77- Err ( NoSolution )
78- }
79- }
80- // FIXME(generic_const_exprs): we would need to support generic consts here
81- ty:: AliasTermKind :: UnevaluatedConst => Err ( NoSolution ) ,
82- // Inherent and weak types are never rigid. This type must not be well-formed.
83- ty:: AliasTermKind :: WeakTy | ty:: AliasTermKind :: InherentTy => Err ( NoSolution ) ,
84- }
85- }
86-
87- /// Normalize the given alias by at least one step. If the alias is rigid, this
88- /// returns `NoSolution`.
89- #[ instrument( level = "trace" , skip( self ) , ret) ]
90- fn normalize_at_least_one_step ( & mut self , goal : Goal < I , NormalizesTo < I > > ) -> QueryResult < I > {
9133 let cx = self . cx ( ) ;
9234 match goal. predicate . alias . kind ( cx) {
9335 ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst => {
9436 let candidates = self . assemble_and_evaluate_candidates ( goal) ;
37+ let trait_ref = goal. predicate . alias . trait_ref ( cx) ;
9538 let ( _, proven_via) =
9639 self . probe ( |_| ProbeKind :: ShadowedEnvProbing ) . enter ( |ecx| {
97- let trait_goal: Goal < I , ty:: TraitPredicate < I > > =
98- goal. with ( cx, goal. predicate . alias . trait_ref ( cx) ) ;
40+ let trait_goal: Goal < I , ty:: TraitPredicate < I > > = goal. with ( cx, trait_ref) ;
9941 ecx. compute_trait_goal ( trait_goal)
10042 } ) ?;
101- self . merge_candidates ( proven_via, candidates)
43+ self . merge_candidates ( proven_via, candidates, |ecx| {
44+ ecx. probe ( |& result| ProbeKind :: RigidAlias { result } ) . enter ( |this| {
45+ this. structurally_instantiate_normalizes_to_term (
46+ goal,
47+ goal. predicate . alias ,
48+ ) ;
49+ this. add_goal ( GoalSource :: AliasWellFormed , goal. with ( cx, trait_ref) ) ;
50+ this. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
51+ } )
52+ } )
10253 }
10354 ty:: AliasTermKind :: InherentTy => self . normalize_inherent_associated_type ( goal) ,
10455 ty:: AliasTermKind :: OpaqueTy => self . normalize_opaque_type ( goal) ,
@@ -120,6 +71,17 @@ where
12071 self . eq ( goal. param_env , goal. predicate . term , term)
12172 . expect ( "expected goal term to be fully unconstrained" ) ;
12273 }
74+
75+ /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term
76+ /// with a rigid alias. Using this is pretty much always wrong.
77+ pub fn structurally_instantiate_normalizes_to_term (
78+ & mut self ,
79+ goal : Goal < I , NormalizesTo < I > > ,
80+ term : ty:: AliasTerm < I > ,
81+ ) {
82+ self . relate_rigid_alias_non_alias ( goal. param_env , term, ty:: Invariant , goal. predicate . term )
83+ . expect ( "expected goal term to be fully unconstrained" ) ;
84+ }
12385}
12486
12587impl < D , I > assembly:: GoalKind < D > for NormalizesTo < I >
@@ -576,80 +538,92 @@ where
576538 let cx = ecx. cx ( ) ;
577539 let metadata_def_id = cx. require_lang_item ( TraitSolverLangItem :: Metadata ) ;
578540 assert_eq ! ( metadata_def_id, goal. predicate. def_id( ) ) ;
579- ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
580- let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
581- ty:: Bool
582- | ty:: Char
583- | ty:: Int ( ..)
584- | ty:: Uint ( ..)
585- | ty:: Float ( ..)
586- | ty:: Array ( ..)
587- | ty:: Pat ( ..)
588- | ty:: RawPtr ( ..)
589- | ty:: Ref ( ..)
590- | ty:: FnDef ( ..)
591- | ty:: FnPtr ( ..)
592- | ty:: Closure ( ..)
593- | ty:: CoroutineClosure ( ..)
594- | ty:: Infer ( ty:: IntVar ( ..) | ty:: FloatVar ( ..) )
595- | ty:: Coroutine ( ..)
596- | ty:: CoroutineWitness ( ..)
597- | ty:: Never
598- | ty:: Foreign ( ..)
599- | ty:: Dynamic ( _, _, ty:: DynStar ) => Ty :: new_unit ( cx) ,
600-
601- ty:: Error ( e) => Ty :: new_error ( cx, e) ,
602-
603- ty:: Str | ty:: Slice ( _) => Ty :: new_usize ( cx) ,
604-
605- ty:: Dynamic ( _, _, ty:: Dyn ) => {
606- let dyn_metadata = cx. require_lang_item ( TraitSolverLangItem :: DynMetadata ) ;
607- cx. type_of ( dyn_metadata)
608- . instantiate ( cx, & [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] )
609- }
541+ let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
542+ ty:: Bool
543+ | ty:: Char
544+ | ty:: Int ( ..)
545+ | ty:: Uint ( ..)
546+ | ty:: Float ( ..)
547+ | ty:: Array ( ..)
548+ | ty:: Pat ( ..)
549+ | ty:: RawPtr ( ..)
550+ | ty:: Ref ( ..)
551+ | ty:: FnDef ( ..)
552+ | ty:: FnPtr ( ..)
553+ | ty:: Closure ( ..)
554+ | ty:: CoroutineClosure ( ..)
555+ | ty:: Infer ( ty:: IntVar ( ..) | ty:: FloatVar ( ..) )
556+ | ty:: Coroutine ( ..)
557+ | ty:: CoroutineWitness ( ..)
558+ | ty:: Never
559+ | ty:: Foreign ( ..)
560+ | ty:: Dynamic ( _, _, ty:: DynStar ) => Ty :: new_unit ( cx) ,
610561
611- ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
612- // This is the "fallback impl" for type parameters, unnormalizable projections
613- // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
614- // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
615- // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
616- let sized_predicate = ty:: TraitRef :: new (
617- cx,
618- cx. require_lang_item ( TraitSolverLangItem :: Sized ) ,
619- [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
620- ) ;
621- // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
622- ecx. add_goal ( GoalSource :: Misc , goal. with ( cx, sized_predicate) ) ;
623- Ty :: new_unit ( cx)
624- }
562+ ty:: Error ( e) => Ty :: new_error ( cx, e) ,
625563
626- ty:: Adt ( def, args) if def. is_struct ( ) => match def. struct_tail_ty ( cx) {
627- None => Ty :: new_unit ( cx) ,
628- Some ( tail_ty) => {
629- Ty :: new_projection ( cx, metadata_def_id, [ tail_ty. instantiate ( cx, args) ] )
630- }
631- } ,
632- ty:: Adt ( _, _) => Ty :: new_unit ( cx) ,
564+ ty:: Str | ty:: Slice ( _) => Ty :: new_usize ( cx) ,
633565
634- ty:: Tuple ( elements) => match elements. last ( ) {
635- None => Ty :: new_unit ( cx) ,
636- Some ( tail_ty) => Ty :: new_projection ( cx, metadata_def_id, [ tail_ty] ) ,
637- } ,
566+ ty:: Dynamic ( _, _, ty:: Dyn ) => {
567+ let dyn_metadata = cx. require_lang_item ( TraitSolverLangItem :: DynMetadata ) ;
568+ cx. type_of ( dyn_metadata)
569+ . instantiate ( cx, & [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] )
570+ }
571+
572+ ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
573+ // This is the "fallback impl" for type parameters, unnormalizable projections
574+ // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
575+ // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
576+ // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
577+ let alias_bound_result =
578+ ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
579+ let sized_predicate = ty:: TraitRef :: new (
580+ cx,
581+ cx. require_lang_item ( TraitSolverLangItem :: Sized ) ,
582+ [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
583+ ) ;
584+ ecx. add_goal ( GoalSource :: Misc , goal. with ( cx, sized_predicate) ) ;
585+ ecx. instantiate_normalizes_to_term ( goal, Ty :: new_unit ( cx) . into ( ) ) ;
586+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
587+ } ) ;
588+ // In case the dummy alias-bound candidate does not apply, we instead treat this projection
589+ // as rigid.
590+ return alias_bound_result. or_else ( |NoSolution | {
591+ ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |this| {
592+ this. structurally_instantiate_normalizes_to_term (
593+ goal,
594+ goal. predicate . alias ,
595+ ) ;
596+ this. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
597+ } )
598+ } ) ;
599+ }
638600
639- ty:: UnsafeBinder ( _) => {
640- // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
641- todo ! ( )
601+ ty:: Adt ( def, args) if def. is_struct ( ) => match def. struct_tail_ty ( cx) {
602+ None => Ty :: new_unit ( cx) ,
603+ Some ( tail_ty) => {
604+ Ty :: new_projection ( cx, metadata_def_id, [ tail_ty. instantiate ( cx, args) ] )
642605 }
606+ } ,
607+ ty:: Adt ( _, _) => Ty :: new_unit ( cx) ,
643608
644- ty:: Infer (
645- ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ,
646- )
647- | ty:: Bound ( ..) => panic ! (
648- "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`" ,
649- goal. predicate. self_ty( )
650- ) ,
651- } ;
609+ ty:: Tuple ( elements) => match elements. last ( ) {
610+ None => Ty :: new_unit ( cx) ,
611+ Some ( tail_ty) => Ty :: new_projection ( cx, metadata_def_id, [ tail_ty] ) ,
612+ } ,
652613
614+ ty:: UnsafeBinder ( _) => {
615+ // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
616+ todo ! ( )
617+ }
618+
619+ ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
620+ | ty:: Bound ( ..) => panic ! (
621+ "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`" ,
622+ goal. predicate. self_ty( )
623+ ) ,
624+ } ;
625+
626+ ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
653627 ecx. instantiate_normalizes_to_term ( goal, metadata_ty. into ( ) ) ;
654628 ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
655629 } )
@@ -850,12 +824,14 @@ where
850824 todo ! ( "discr subgoal..." )
851825 }
852826
853- // We do not call `Ty::discriminant_ty` on alias, param, or placeholder
854- // types, which return `<self_ty as DiscriminantKind>::Discriminant`
855- // (or ICE in the case of placeholders). Projecting a type to itself
856- // is never really productive.
827+ // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
828+ // alias. In case there's a where-bound further constraining this alias it is preferred over
829+ // this impl candidate anyways. It's still a bit scuffed.
857830 ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
858- return Err ( NoSolution ) ;
831+ return ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
832+ ecx. structurally_instantiate_normalizes_to_term ( goal, goal. predicate . alias ) ;
833+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
834+ } ) ;
859835 }
860836
861837 ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
@@ -902,12 +878,14 @@ where
902878 todo ! ( )
903879 }
904880
905- // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder
906- // types, which return `<self_ty as AsyncDestruct>::AsyncDestructor`
907- // (or ICE in the case of placeholders). Projecting a type to itself
908- // is never really productive.
881+ // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
882+ // alias. In case there's a where-bound further constraining this alias it is preferred over
883+ // this impl candidate anyways. It's still a bit scuffed.
909884 ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
910- return Err ( NoSolution ) ;
885+ return ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
886+ ecx. structurally_instantiate_normalizes_to_term ( goal, goal. predicate . alias ) ;
887+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
888+ } ) ;
911889 }
912890
913891 ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
0 commit comments