1212//! may apply, then we can compute the "intersection" of both normalizes-to by
1313//! performing them together. This is used specifically to resolve ambiguities.
1414use super :: EvalCtxt ;
15+ use rustc_infer:: infer:: DefineOpaqueTypes ;
1516use rustc_infer:: traits:: query:: NoSolution ;
1617use rustc_middle:: traits:: solve:: { Certainty , Goal , QueryResult } ;
1718use rustc_middle:: ty;
@@ -44,38 +45,46 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
4445 self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
4546 }
4647
47- ( Some ( _ ) , None ) => {
48+ ( Some ( alias ) , None ) => {
4849 if rhs. is_infer ( ) {
4950 self . relate ( param_env, lhs, variance, rhs) ?;
5051 self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
52+ } else if alias. is_opaque ( tcx) {
53+ self . define_opaque ( param_env, alias, rhs)
5154 } else {
5255 Err ( NoSolution )
5356 }
5457 }
55- ( None , Some ( _ ) ) => {
58+ ( None , Some ( alias ) ) => {
5659 if lhs. is_infer ( ) {
5760 self . relate ( param_env, lhs, variance, rhs) ?;
5861 self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
62+ } else if alias. is_opaque ( tcx) {
63+ self . define_opaque ( param_env, alias, lhs)
5964 } else {
6065 Err ( NoSolution )
6166 }
6267 }
6368
6469 ( Some ( alias_lhs) , Some ( alias_rhs) ) => {
65- self . relate ( param_env, alias_lhs, variance, alias_rhs) ?;
66- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
70+ self . relate_rigid_alias_or_opaque ( param_env, alias_lhs, variance, alias_rhs)
6771 }
6872 }
6973 }
7074
71- /// Normalize the `term` to equate it later.
75+ /// Normalize the `term` to equate it later. This does not define opaque types.
7276 fn try_normalize_term (
7377 & mut self ,
7478 param_env : ty:: ParamEnv < ' tcx > ,
7579 term : ty:: Term < ' tcx > ,
7680 ) -> Result < Option < ty:: Term < ' tcx > > , NoSolution > {
7781 match term. unpack ( ) {
78- ty:: TermKind :: Ty ( ty) => Ok ( self . try_normalize_ty ( param_env, ty) . map ( Into :: into) ) ,
82+ ty:: TermKind :: Ty ( ty) => {
83+ // We do no define opaque types here but instead do so in `relate_rigid_alias_or_opaque`.
84+ Ok ( self
85+ . try_normalize_ty_recur ( param_env, DefineOpaqueTypes :: No , 0 , ty)
86+ . map ( Into :: into) )
87+ }
7988 ty:: TermKind :: Const ( _) => {
8089 if let Some ( alias) = term. to_alias_ty ( self . tcx ( ) ) {
8190 let term = self . next_term_infer_of_kind ( term) ;
@@ -92,4 +101,53 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
92101 }
93102 }
94103 }
104+
105+ fn define_opaque (
106+ & mut self ,
107+ param_env : ty:: ParamEnv < ' tcx > ,
108+ opaque : ty:: AliasTy < ' tcx > ,
109+ term : ty:: Term < ' tcx > ,
110+ ) -> QueryResult < ' tcx > {
111+ self . add_goal ( Goal :: new (
112+ self . tcx ( ) ,
113+ param_env,
114+ ty:: ProjectionPredicate { projection_ty : opaque, term } ,
115+ ) ) ;
116+ self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
117+ }
118+
119+ fn relate_rigid_alias_or_opaque (
120+ & mut self ,
121+ param_env : ty:: ParamEnv < ' tcx > ,
122+ lhs : ty:: AliasTy < ' tcx > ,
123+ variance : ty:: Variance ,
124+ rhs : ty:: AliasTy < ' tcx > ,
125+ ) -> QueryResult < ' tcx > {
126+ let tcx = self . tcx ( ) ;
127+ let mut candidates = vec ! [ ] ;
128+ if lhs. is_opaque ( tcx) {
129+ candidates. extend (
130+ self . probe_misc_candidate ( "define-lhs-opaque" )
131+ . enter ( |ecx| ecx. define_opaque ( param_env, lhs, rhs. to_ty ( tcx) . into ( ) ) ) ,
132+ ) ;
133+ }
134+
135+ if rhs. is_opaque ( tcx) {
136+ candidates. extend (
137+ self . probe_misc_candidate ( "define-rhs-opaque" )
138+ . enter ( |ecx| ecx. define_opaque ( param_env, rhs, lhs. to_ty ( tcx) . into ( ) ) ) ,
139+ ) ;
140+ }
141+
142+ candidates. extend ( self . probe_misc_candidate ( "args-relate" ) . enter ( |ecx| {
143+ ecx. relate ( param_env, lhs, variance, rhs) ?;
144+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
145+ } ) ) ;
146+
147+ if let Some ( result) = self . try_merge_responses ( & candidates) {
148+ Ok ( result)
149+ } else {
150+ self . flounder ( & candidates)
151+ }
152+ }
95153}
0 commit comments