@@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
15
15
use crate :: solve:: inspect:: ProbeKind ;
16
16
use crate :: solve:: {
17
17
BuiltinImplSource , CandidateSource , Certainty , EvalCtxt , Goal , GoalSource , MaybeCause ,
18
- NoSolution , QueryResult ,
18
+ NoSolution , QueryResult , Reveal ,
19
19
} ;
20
20
21
21
impl < D , I > EvalCtxt < ' _ , D >
@@ -39,11 +39,58 @@ where
39
39
Err ( NoSolution ) => {
40
40
let Goal { param_env, predicate : NormalizesTo { alias, term } } = goal;
41
41
self . relate_rigid_alias_non_alias ( param_env, alias, ty:: Invariant , term) ?;
42
+ self . add_rigid_constraints ( param_env, alias) ?;
42
43
self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
43
44
}
44
45
}
45
46
}
46
47
48
+ /// Register any obligations that are used to validate that an alias should be
49
+ /// treated as rigid.
50
+ ///
51
+ /// An alias may be considered rigid if it fails normalization, but we also don't
52
+ /// want to consider aliases that are not well-formed to be rigid simply because
53
+ /// they fail normalization.
54
+ ///
55
+ /// For example, some `<T as Trait>::Assoc` where `T: Trait` does not hold, or an
56
+ /// opaque type whose hidden type doesn't actually satisfy the opaque item bounds.
57
+ fn add_rigid_constraints (
58
+ & mut self ,
59
+ param_env : I :: ParamEnv ,
60
+ rigid_alias : ty:: AliasTerm < I > ,
61
+ ) -> Result < ( ) , NoSolution > {
62
+ match rigid_alias. kind ( self . cx ( ) ) {
63
+ // Projections are rigid only if their trait ref holds.
64
+ ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst => {
65
+ let trait_ref = rigid_alias. trait_ref ( self . cx ( ) ) ;
66
+ self . add_goal ( GoalSource :: Misc , Goal :: new ( self . cx ( ) , param_env, trait_ref) ) ;
67
+ Ok ( ( ) )
68
+ }
69
+ ty:: AliasTermKind :: OpaqueTy => {
70
+ match param_env. reveal ( ) {
71
+ // In user-facing mode, paques are only rigid if we may not define it.
72
+ Reveal :: UserFacing => {
73
+ if rigid_alias
74
+ . def_id
75
+ . as_local ( )
76
+ . is_some_and ( |def_id| self . can_define_opaque_ty ( def_id) )
77
+ {
78
+ Err ( NoSolution )
79
+ } else {
80
+ Ok ( ( ) )
81
+ }
82
+ }
83
+ // Opaques are never rigid in reveal-all mode.
84
+ Reveal :: All => Err ( NoSolution ) ,
85
+ }
86
+ }
87
+ // FIXME(generic_const_exprs): we would need to support generic consts here
88
+ ty:: AliasTermKind :: UnevaluatedConst => Err ( NoSolution ) ,
89
+ // Inherent and weak types are never rigid. This type must not be well-formed.
90
+ ty:: AliasTermKind :: WeakTy | ty:: AliasTermKind :: InherentTy => Err ( NoSolution ) ,
91
+ }
92
+ }
93
+
47
94
/// Normalize the given alias by at least one step. If the alias is rigid, this
48
95
/// returns `NoSolution`.
49
96
#[ instrument( level = "trace" , skip( self ) , ret) ]
@@ -124,6 +171,7 @@ where
124
171
ecx. instantiate_normalizes_to_term ( goal, assumption_projection_pred. term ) ;
125
172
126
173
// Add GAT where clauses from the trait's definition
174
+ // FIXME: We don't need these, since these are the type's own WF obligations.
127
175
ecx. add_goals (
128
176
GoalSource :: Misc ,
129
177
cx. own_predicates_of ( goal. predicate . def_id ( ) )
@@ -179,7 +227,8 @@ where
179
227
. map ( |pred| goal. with ( cx, pred) ) ;
180
228
ecx. add_goals ( GoalSource :: ImplWhereBound , where_clause_bounds) ;
181
229
182
- // Add GAT where clauses from the trait's definition
230
+ // Add GAT where clauses from the trait's definition.
231
+ // FIXME: We don't need these, since these are the type's own WF obligations.
183
232
ecx. add_goals (
184
233
GoalSource :: Misc ,
185
234
cx. own_predicates_of ( goal. predicate . def_id ( ) )
0 commit comments