@@ -30,75 +30,26 @@ where
30
30
) -> QueryResult < I > {
31
31
self . set_is_normalizes_to_goal ( ) ;
32
32
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 > {
91
33
let cx = self . cx ( ) ;
92
34
match goal. predicate . alias . kind ( cx) {
93
35
ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst => {
94
36
let candidates = self . assemble_and_evaluate_candidates ( goal) ;
37
+ let trait_ref = goal. predicate . alias . trait_ref ( cx) ;
95
38
let ( _, proven_via) =
96
39
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) ;
99
41
ecx. compute_trait_goal ( trait_goal)
100
42
} ) ?;
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
+ } )
102
53
}
103
54
ty:: AliasTermKind :: InherentTy => self . normalize_inherent_associated_type ( goal) ,
104
55
ty:: AliasTermKind :: OpaqueTy => self . normalize_opaque_type ( goal) ,
@@ -120,6 +71,17 @@ where
120
71
self . eq ( goal. param_env , goal. predicate . term , term)
121
72
. expect ( "expected goal term to be fully unconstrained" ) ;
122
73
}
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
+ }
123
85
}
124
86
125
87
impl < D , I > assembly:: GoalKind < D > for NormalizesTo < I >
@@ -850,12 +812,14 @@ where
850
812
todo ! ( "discr subgoal..." )
851
813
}
852
814
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.
857
818
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
+ } ) ;
859
823
}
860
824
861
825
ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
@@ -902,12 +866,14 @@ where
902
866
todo ! ( )
903
867
}
904
868
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.
909
872
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
+ } ) ;
911
877
}
912
878
913
879
ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
0 commit comments