@@ -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 >
@@ -850,12 +812,14 @@ where
850812 todo ! ( "discr subgoal..." )
851813 }
852814
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.
815+ // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
816+ // alias. In case there's a where-bound further constraining this alias it is preferred over
817+ // this impl candidate anyways. It's still a bit scuffed.
857818 ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
858- return Err ( NoSolution ) ;
819+ return ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
820+ ecx. structurally_instantiate_normalizes_to_term ( goal, goal. predicate . alias ) ;
821+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
822+ } ) ;
859823 }
860824
861825 ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
@@ -902,12 +866,14 @@ where
902866 todo ! ( )
903867 }
904868
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.
869+ // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
870+ // alias. In case there's a where-bound further constraining this alias it is preferred over
871+ // this impl candidate anyways. It's still a bit scuffed.
909872 ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
910- return Err ( NoSolution ) ;
873+ return ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
874+ ecx. structurally_instantiate_normalizes_to_term ( goal, goal. predicate . alias ) ;
875+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
876+ } ) ;
911877 }
912878
913879 ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
0 commit comments