@@ -80,37 +80,23 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
8080 obligation. repr( selcx. tcx( ) ) ) ;
8181
8282 let infcx = selcx. infcx ( ) ;
83- let result = infcx. try ( |snapshot| {
83+ infcx. try ( |snapshot| {
8484 let ( skol_predicate, skol_map) =
8585 infcx. skolemize_late_bound_regions ( & obligation. predicate , snapshot) ;
8686
8787 let skol_obligation = obligation. with ( skol_predicate) ;
8888 match project_and_unify_type ( selcx, & skol_obligation) {
89- Ok ( Some ( obligations ) ) => {
89+ Ok ( result ) => {
9090 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 } ) ,
9393 }
9494 }
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- }
10095 Err ( e) => {
101- Err ( Some ( e ) )
96+ Err ( e )
10297 }
10398 }
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+ } )
114100}
115101
116102/// Evaluates constraints of the form:
@@ -132,7 +118,10 @@ fn project_and_unify_type<'cx,'tcx>(
132118 obligation. cause . clone ( ) ,
133119 obligation. recursion_depth ) {
134120 Some ( n) => n,
135- None => { return Ok ( None ) ; }
121+ None => {
122+ consider_unification_despite_ambiguity ( selcx, obligation) ;
123+ return Ok ( None ) ;
124+ }
136125 } ;
137126
138127 debug ! ( "project_and_unify_type: normalized_ty={} obligations={}" ,
@@ -147,6 +136,50 @@ fn project_and_unify_type<'cx,'tcx>(
147136 }
148137}
149138
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+
150183/// Normalizes any associated type projections in `value`, replacing
151184/// them with a fully resolved type where possible. The return value
152185/// combines the normalized result and any additional obligations that
0 commit comments