@@ -25,46 +25,21 @@ use util::ppaux::Repr;
2525pub fn check_expr_closure < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
2626 expr : & ast:: Expr ,
2727 _capture : ast:: CaptureClause ,
28- opt_kind : Option < ast:: ClosureKind > ,
2928 decl : & ' tcx ast:: FnDecl ,
3029 body : & ' tcx ast:: Block ,
3130 expected : Expectation < ' tcx > ) {
3231 debug ! ( "check_expr_closure(expr={},expected={})" ,
3332 expr. repr( fcx. tcx( ) ) ,
3433 expected. repr( fcx. tcx( ) ) ) ;
3534
36- let expected_sig_and_kind = expected. to_option ( fcx) . and_then ( |ty| {
37- deduce_expectations_from_expected_type ( fcx, ty)
38- } ) ;
39-
40- match opt_kind {
41- None => {
42- // If users didn't specify what sort of closure they want,
43- // examine the expected type. For now, if we see explicit
44- // evidence than an unboxed closure is desired, we'll use
45- // that. Otherwise, we leave it unspecified, to be filled
46- // in by upvar inference.
47- match expected_sig_and_kind {
48- None => { // don't have information about the kind, request explicit annotation
49- check_closure ( fcx, expr, None , decl, body, None ) ;
50- } ,
51- Some ( ( sig, kind) ) => {
52- check_closure ( fcx, expr, Some ( kind) , decl, body, Some ( sig) ) ;
53- }
54- }
55- }
56-
57- Some ( kind) => {
58- let kind = match kind {
59- ast:: FnClosureKind => ty:: FnClosureKind ,
60- ast:: FnMutClosureKind => ty:: FnMutClosureKind ,
61- ast:: FnOnceClosureKind => ty:: FnOnceClosureKind ,
62- } ;
63-
64- let expected_sig = expected_sig_and_kind. map ( |t| t. 0 ) ;
65- check_closure ( fcx, expr, Some ( kind) , decl, body, expected_sig) ;
66- }
67- }
35+ // It's always helpful for inference if we know the kind of
36+ // closure sooner rather than later, so first examine the expected
37+ // type, and see if can glean a closure kind from there.
38+ let ( expected_sig, expected_kind) = match expected. to_option ( fcx) {
39+ Some ( ty) => deduce_expectations_from_expected_type ( fcx, ty) ,
40+ None => ( None , None )
41+ } ;
42+ check_closure ( fcx, expr, expected_kind, decl, body, expected_sig)
6843}
6944
7045fn check_closure < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
@@ -133,55 +108,92 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
133108fn deduce_expectations_from_expected_type < ' a , ' tcx > (
134109 fcx : & FnCtxt < ' a , ' tcx > ,
135110 expected_ty : Ty < ' tcx > )
136- -> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
111+ -> ( Option < ty:: FnSig < ' tcx > > , Option < ty:: ClosureKind > )
137112{
113+ debug ! ( "deduce_expectations_from_expected_type(expected_ty={})" ,
114+ expected_ty. repr( fcx. tcx( ) ) ) ;
115+
138116 match expected_ty. sty {
139117 ty:: ty_trait( ref object_type) => {
140118 let proj_bounds = object_type. projection_bounds_with_self_ty ( fcx. tcx ( ) ,
141119 fcx. tcx ( ) . types . err ) ;
142- proj_bounds. iter ( )
143- . filter_map ( |pb| deduce_expectations_from_projection ( fcx, pb) )
144- . next ( )
120+ let expectations =
121+ proj_bounds. iter ( )
122+ . filter_map ( |pb| deduce_expectations_from_projection ( fcx, pb) )
123+ . next ( ) ;
124+
125+ match expectations {
126+ Some ( ( sig, kind) ) => ( Some ( sig) , Some ( kind) ) ,
127+ None => ( None , None )
128+ }
145129 }
146130 ty:: ty_infer( ty:: TyVar ( vid) ) => {
147131 deduce_expectations_from_obligations ( fcx, vid)
148132 }
149133 _ => {
150- None
134+ ( None , None )
151135 }
152136 }
153137}
154138
155139fn deduce_expectations_from_obligations < ' a , ' tcx > (
156140 fcx : & FnCtxt < ' a , ' tcx > ,
157141 expected_vid : ty:: TyVid )
158- -> Option < ( ty:: FnSig < ' tcx > , ty:: ClosureKind ) >
142+ -> ( Option < ty:: FnSig < ' tcx > > , Option < ty:: ClosureKind > )
159143{
160144 let fulfillment_cx = fcx. inh . fulfillment_cx . borrow ( ) ;
161145 // Here `expected_ty` is known to be a type inference variable.
162146
163- fulfillment_cx. pending_obligations ( )
164- . iter ( )
165- . filter_map ( |obligation| {
166- match obligation. predicate {
167- ty:: Predicate :: Projection ( ref proj_predicate) => {
168- let trait_ref = proj_predicate. to_poly_trait_ref ( ) ;
169- let self_ty = fcx. infcx ( ) . shallow_resolve ( trait_ref. self_ty ( ) ) ;
170- match self_ty. sty {
171- ty:: ty_infer( ty:: TyVar ( v) ) if expected_vid == v => {
172- deduce_expectations_from_projection ( fcx, proj_predicate)
173- }
174- _ => {
175- None
176- }
177- }
178- }
179- _ => {
180- None
181- }
182- }
183- } )
184- . next ( )
147+ let expected_sig_and_kind =
148+ fulfillment_cx
149+ . pending_obligations ( )
150+ . iter ( )
151+ . filter_map ( |obligation| {
152+ debug ! ( "deduce_expectations_from_obligations: obligation.predicate={}" ,
153+ obligation. predicate. repr( fcx. tcx( ) ) ) ;
154+
155+ match obligation. predicate {
156+ // Given a Projection predicate, we can potentially infer
157+ // the complete signature.
158+ ty:: Predicate :: Projection ( ref proj_predicate) => {
159+ let trait_ref = proj_predicate. to_poly_trait_ref ( ) ;
160+ self_type_matches_expected_vid ( fcx, trait_ref, expected_vid)
161+ . and_then ( |_| deduce_expectations_from_projection ( fcx, proj_predicate) )
162+ }
163+ _ => {
164+ None
165+ }
166+ }
167+ } )
168+ . next ( ) ;
169+
170+ match expected_sig_and_kind {
171+ Some ( ( sig, kind) ) => { return ( Some ( sig) , Some ( kind) ) ; }
172+ None => { }
173+ }
174+
175+ // Even if we can't infer the full signature, we may be able to
176+ // infer the kind. This can occur if there is a trait-reference
177+ // like `F : Fn<A>`.
178+ let expected_kind =
179+ fulfillment_cx
180+ . pending_obligations ( )
181+ . iter ( )
182+ . filter_map ( |obligation| {
183+ let opt_trait_ref = match obligation. predicate {
184+ ty:: Predicate :: Projection ( ref data) => Some ( data. to_poly_trait_ref ( ) ) ,
185+ ty:: Predicate :: Trait ( ref data) => Some ( data. to_poly_trait_ref ( ) ) ,
186+ ty:: Predicate :: Equate ( ..) => None ,
187+ ty:: Predicate :: RegionOutlives ( ..) => None ,
188+ ty:: Predicate :: TypeOutlives ( ..) => None ,
189+ } ;
190+ opt_trait_ref
191+ . and_then ( |trait_ref| self_type_matches_expected_vid ( fcx, trait_ref, expected_vid) )
192+ . and_then ( |trait_ref| fcx. tcx ( ) . lang_items . fn_trait_kind ( trait_ref. def_id ( ) ) )
193+ } )
194+ . next ( ) ;
195+
196+ ( None , expected_kind)
185197}
186198
187199/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
@@ -229,3 +241,20 @@ fn deduce_expectations_from_projection<'a,'tcx>(
229241 return Some ( ( fn_sig, kind) ) ;
230242}
231243
244+ fn self_type_matches_expected_vid < ' a , ' tcx > (
245+ fcx : & FnCtxt < ' a , ' tcx > ,
246+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
247+ expected_vid : ty:: TyVid )
248+ -> Option < ty:: PolyTraitRef < ' tcx > >
249+ {
250+ let self_ty = fcx. infcx ( ) . shallow_resolve ( trait_ref. self_ty ( ) ) ;
251+ debug ! ( "self_type_matches_expected_vid(trait_ref={}, self_ty={})" ,
252+ trait_ref. repr( fcx. tcx( ) ) ,
253+ self_ty. repr( fcx. tcx( ) ) ) ;
254+ match self_ty. sty {
255+ ty:: ty_infer( ty:: TyVar ( v) ) if expected_vid == v => Some ( trait_ref) ,
256+ _ => None ,
257+ }
258+ }
259+
260+
0 commit comments