@@ -15,16 +15,18 @@ pub use self::FulfillmentErrorCode::*;
1515pub use self :: Vtable :: * ;
1616pub use self :: ObligationCauseCode :: * ;
1717
18+ use middle:: mem_categorization:: Typer ;
1819use middle:: subst;
1920use middle:: ty:: { mod, Ty } ;
2021use middle:: infer:: InferCtxt ;
2122use std:: slice:: Iter ;
2223use std:: rc:: Rc ;
2324use syntax:: ast;
2425use syntax:: codemap:: { Span , DUMMY_SP } ;
25- use util:: ppaux:: Repr ;
26+ use util:: ppaux:: { Repr , UserString } ;
2627
2728pub use self :: error_reporting:: report_fulfillment_errors;
29+ pub use self :: error_reporting:: suggest_new_overflow_limit;
2830pub use self :: coherence:: orphan_check;
2931pub use self :: coherence:: OrphanCheckErr ;
3032pub use self :: fulfill:: { FulfillmentContext , RegionObligation } ;
@@ -288,29 +290,62 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
288290/// `bound` or is not known to meet bound (note that this is
289291/// conservative towards *no impl*, which is the opposite of the
290292/// `evaluate` methods).
291- pub fn type_known_to_meet_builtin_bound < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
292- param_env : & ty:: ParameterEnvironment < ' tcx > ,
293- ty : Ty < ' tcx > ,
294- bound : ty:: BuiltinBound )
295- -> bool
293+ pub fn evaluate_builtin_bound < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
294+ typer : & ty:: UnboxedClosureTyper < ' tcx > ,
295+ ty : Ty < ' tcx > ,
296+ bound : ty:: BuiltinBound ,
297+ span : Span )
298+ -> SelectionResult < ' tcx , ( ) >
296299{
297300 debug ! ( "type_known_to_meet_builtin_bound(ty={}, bound={})" ,
298301 ty. repr( infcx. tcx) ,
299302 bound) ;
300303
301304 let mut fulfill_cx = FulfillmentContext :: new ( ) ;
302305
303- // We can use dummy values here because we won't report any errors
304- // that result nor will we pay any mind to region obligations that arise
305- // (there shouldn't really be any anyhow).
306- let cause = ObligationCause :: misc ( DUMMY_SP , ast:: DUMMY_NODE_ID ) ;
306+ // We can use a dummy node-id here because we won't pay any mind
307+ // to region obligations that arise (there shouldn't really be any
308+ // anyhow).
309+ let cause = ObligationCause :: misc ( span , ast:: DUMMY_NODE_ID ) ;
307310
308311 fulfill_cx. register_builtin_bound ( infcx, ty, bound, cause) ;
309312
310313 // Note: we only assume something is `Copy` if we can
311314 // *definitively* show that it implements `Copy`. Otherwise,
312315 // assume it is move; linear is always ok.
313- let result = fulfill_cx. select_all_or_error ( infcx, param_env, infcx. tcx ) . is_ok ( ) ;
316+ let result = match fulfill_cx. select_all_or_error ( infcx, typer) {
317+ Ok ( ( ) ) => Ok ( Some ( ( ) ) ) , // Success, we know it implements Copy.
318+ Err ( errors) => {
319+ // Check if overflow occurred anywhere and propagate that.
320+ if errors. iter ( ) . any (
321+ |err| match err. code { CodeSelectionError ( Overflow ) => true , _ => false } )
322+ {
323+ return Err ( Overflow ) ;
324+ }
325+
326+ // Otherwise, if there were any hard errors, propagate an
327+ // arbitrary one of those. If no hard errors at all,
328+ // report ambiguity.
329+ let sel_error =
330+ errors. iter ( )
331+ . filter_map ( |err| {
332+ match err. code {
333+ CodeAmbiguity => None ,
334+ CodeSelectionError ( ref e) => Some ( e. clone ( ) ) ,
335+ CodeProjectionError ( _) => {
336+ infcx. tcx . sess . span_bug (
337+ span,
338+ "projection error while selecting?" )
339+ }
340+ }
341+ } )
342+ . next ( ) ;
343+ match sel_error {
344+ None => { Ok ( None ) }
345+ Some ( e) => { Err ( e) }
346+ }
347+ }
348+ } ;
314349
315350 debug ! ( "type_known_to_meet_builtin_bound: ty={} bound={} result={}" ,
316351 ty. repr( infcx. tcx) ,
@@ -320,6 +355,40 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
320355 result
321356}
322357
358+ pub fn type_known_to_meet_builtin_bound < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
359+ typer : & ty:: UnboxedClosureTyper < ' tcx > ,
360+ ty : Ty < ' tcx > ,
361+ bound : ty:: BuiltinBound ,
362+ span : Span )
363+ -> bool
364+ {
365+ match evaluate_builtin_bound ( infcx, typer, ty, bound, span) {
366+ Ok ( Some ( ( ) ) ) => {
367+ // definitely impl'd
368+ true
369+ }
370+ Ok ( None ) => {
371+ // ambiguous: if coherence check was successful, shouldn't
372+ // happen, but we might have reported an error and been
373+ // soldering on, so just treat this like not implemented
374+ false
375+ }
376+ Err ( Overflow ) => {
377+ infcx. tcx . sess . span_err (
378+ span,
379+ format ! ( "overflow evaluating whether `{}` is `{}`" ,
380+ ty. user_string( infcx. tcx) ,
381+ bound. user_string( infcx. tcx) ) [ ] ) ;
382+ suggest_new_overflow_limit ( infcx. tcx , span) ;
383+ false
384+ }
385+ Err ( _) => {
386+ // other errors: not implemented.
387+ false
388+ }
389+ }
390+ }
391+
323392impl < ' tcx , O > Obligation < ' tcx , O > {
324393 pub fn new ( cause : ObligationCause < ' tcx > ,
325394 trait_ref : O )
0 commit comments