@@ -80,37 +80,23 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
80
80
obligation. repr( selcx. tcx( ) ) ) ;
81
81
82
82
let infcx = selcx. infcx ( ) ;
83
- let result = infcx. try ( |snapshot| {
83
+ infcx. try ( |snapshot| {
84
84
let ( skol_predicate, skol_map) =
85
85
infcx. skolemize_late_bound_regions ( & obligation. predicate , snapshot) ;
86
86
87
87
let skol_obligation = obligation. with ( skol_predicate) ;
88
88
match project_and_unify_type ( selcx, & skol_obligation) {
89
- Ok ( Some ( obligations ) ) => {
89
+ Ok ( result ) => {
90
90
match infcx. leak_check ( & skol_map, snapshot) {
91
- Ok ( ( ) ) => Ok ( infcx. plug_leaks ( skol_map, snapshot, & obligations ) ) ,
92
- Err ( e) => Err ( Some ( MismatchedProjectionTypes { err : e } ) ) ,
91
+ Ok ( ( ) ) => Ok ( infcx. plug_leaks ( skol_map, snapshot, & result ) ) ,
92
+ Err ( e) => Err ( MismatchedProjectionTypes { err : e } ) ,
93
93
}
94
94
}
95
- Ok ( None ) => {
96
- // Signal ambiguity using Err just so that infcx.try()
97
- // rolls back the snapshot. We adapt below.
98
- Err ( None )
99
- }
100
95
Err ( e) => {
101
- Err ( Some ( e ) )
96
+ Err ( e )
102
97
}
103
98
}
104
- } ) ;
105
-
106
- // Above, we use Err(None) to signal ambiguity so that the
107
- // snapshot will be rolled back. But here, we want to translate to
108
- // Ok(None). Kind of weird.
109
- match result {
110
- Ok ( obligations) => Ok ( Some ( obligations) ) ,
111
- Err ( None ) => Ok ( None ) ,
112
- Err ( Some ( e) ) => Err ( e) ,
113
- }
99
+ } )
114
100
}
115
101
116
102
/// Evaluates constraints of the form:
@@ -132,7 +118,10 @@ fn project_and_unify_type<'cx,'tcx>(
132
118
obligation. cause . clone ( ) ,
133
119
obligation. recursion_depth ) {
134
120
Some ( n) => n,
135
- None => { return Ok ( None ) ; }
121
+ None => {
122
+ consider_unification_despite_ambiguity ( selcx, obligation) ;
123
+ return Ok ( None ) ;
124
+ }
136
125
} ;
137
126
138
127
debug ! ( "project_and_unify_type: normalized_ty={} obligations={}" ,
@@ -147,6 +136,50 @@ fn project_and_unify_type<'cx,'tcx>(
147
136
}
148
137
}
149
138
139
+ fn consider_unification_despite_ambiguity < ' cx , ' tcx > ( selcx : & mut SelectionContext < ' cx , ' tcx > ,
140
+ obligation : & ProjectionObligation < ' tcx > ) {
141
+ debug ! ( "consider_unification_despite_ambiguity(obligation={})" ,
142
+ obligation. repr( selcx. tcx( ) ) ) ;
143
+
144
+ let def_id = obligation. predicate . projection_ty . trait_ref . def_id ;
145
+ match selcx. tcx ( ) . lang_items . fn_trait_kind ( def_id) {
146
+ Some ( _) => { }
147
+ None => { return ; }
148
+ }
149
+
150
+ let infcx = selcx. infcx ( ) ;
151
+ let self_ty = obligation. predicate . projection_ty . trait_ref . self_ty ( ) ;
152
+ let self_ty = infcx. shallow_resolve ( self_ty) ;
153
+ debug ! ( "consider_unification_despite_ambiguity: self_ty.sty={:?}" ,
154
+ self_ty. sty) ;
155
+ match self_ty. sty {
156
+ ty:: ty_closure( closure_def_id, _, substs) => {
157
+ let closure_typer = selcx. closure_typer ( ) ;
158
+ let closure_type = closure_typer. closure_type ( closure_def_id, substs) ;
159
+ let ty:: Binder ( ( _, ret_type) ) =
160
+ util:: closure_trait_ref_and_return_type ( infcx. tcx ,
161
+ def_id,
162
+ self_ty,
163
+ & closure_type. sig ,
164
+ util:: TupleArgumentsFlag :: No ) ;
165
+ let ( ret_type, _) =
166
+ infcx. replace_late_bound_regions_with_fresh_var (
167
+ obligation. cause . span ,
168
+ infer:: AssocTypeProjection ( obligation. predicate . projection_ty . item_name ) ,
169
+ & ty:: Binder ( ret_type) ) ;
170
+ debug ! ( "consider_unification_despite_ambiguity: ret_type={:?}" ,
171
+ ret_type. repr( selcx. tcx( ) ) ) ;
172
+ let origin = infer:: RelateOutputImplTypes ( obligation. cause . span ) ;
173
+ let obligation_ty = obligation. predicate . ty ;
174
+ match infer:: mk_eqty ( infcx, true , origin, obligation_ty, ret_type) {
175
+ Ok ( ( ) ) => { }
176
+ Err ( _) => { /* ignore errors */ }
177
+ }
178
+ }
179
+ _ => { }
180
+ }
181
+ }
182
+
150
183
/// Normalizes any associated type projections in `value`, replacing
151
184
/// them with a fully resolved type where possible. The return value
152
185
/// combines the normalized result and any additional obligations that
0 commit comments