@@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
1515use crate :: solve:: inspect:: ProbeKind ;
1616use crate :: solve:: {
1717 BuiltinImplSource , CandidateSource , Certainty , EvalCtxt , Goal , GoalSource , MaybeCause ,
18- NoSolution , QueryResult ,
18+ NoSolution , QueryResult , Reveal ,
1919} ;
2020
2121impl < D , I > EvalCtxt < ' _ , D >
@@ -37,10 +37,61 @@ where
3737 match normalize_result {
3838 Ok ( res) => Ok ( res) ,
3939 Err ( NoSolution ) => {
40- let Goal { param_env, predicate : NormalizesTo { alias, term } } = goal;
41- self . relate_rigid_alias_non_alias ( param_env, alias, ty:: Invariant , term) ?;
42- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
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+ match param_env. reveal ( ) {
75+ // In user-facing mode, paques are only rigid if we may not define it.
76+ Reveal :: UserFacing => {
77+ if rigid_alias
78+ . def_id
79+ . as_local ( )
80+ . is_some_and ( |def_id| self . can_define_opaque_ty ( def_id) )
81+ {
82+ Err ( NoSolution )
83+ } else {
84+ Ok ( ( ) )
85+ }
86+ }
87+ // Opaques are never rigid in reveal-all mode.
88+ Reveal :: All => Err ( NoSolution ) ,
89+ }
4390 }
91+ // FIXME(generic_const_exprs): we would need to support generic consts here
92+ ty:: AliasTermKind :: UnevaluatedConst => Err ( NoSolution ) ,
93+ // Inherent and weak types are never rigid. This type must not be well-formed.
94+ ty:: AliasTermKind :: WeakTy | ty:: AliasTermKind :: InherentTy => Err ( NoSolution ) ,
4495 }
4596 }
4697
@@ -124,6 +175,7 @@ where
124175 ecx. instantiate_normalizes_to_term ( goal, assumption_projection_pred. term ) ;
125176
126177 // Add GAT where clauses from the trait's definition
178+ // FIXME: We don't need these, since these are the type's own WF obligations.
127179 ecx. add_goals (
128180 GoalSource :: Misc ,
129181 cx. own_predicates_of ( goal. predicate . def_id ( ) )
@@ -179,7 +231,8 @@ where
179231 . map ( |pred| goal. with ( cx, pred) ) ;
180232 ecx. add_goals ( GoalSource :: ImplWhereBound , where_clause_bounds) ;
181233
182- // Add GAT where clauses from the trait's definition
234+ // Add GAT where clauses from the trait's definition.
235+ // FIXME: We don't need these, since these are the type's own WF obligations.
183236 ecx. add_goals (
184237 GoalSource :: Misc ,
185238 cx. own_predicates_of ( goal. predicate . def_id ( ) )
0 commit comments