@@ -44,6 +44,7 @@ pub use self::object_safety::object_safety_violations;
4444pub use self :: object_safety:: ObjectSafetyViolation ;
4545pub use self :: object_safety:: MethodViolationCode ;
4646pub use self :: object_safety:: is_vtable_safe_method;
47+ pub use self :: select:: EvaluationCache ;
4748pub use self :: select:: SelectionContext ;
4849pub use self :: select:: SelectionCache ;
4950pub use self :: select:: { MethodMatchResult , MethodMatched , MethodAmbiguous , MethodDidNotMatch } ;
@@ -339,32 +340,53 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
339340 ty,
340341 bound) ;
341342
342- let mut fulfill_cx = FulfillmentContext :: new ( false ) ;
343-
344- // We can use a dummy node-id here because we won't pay any mind
345- // to region obligations that arise (there shouldn't really be any
346- // anyhow).
347343 let cause = ObligationCause :: misc ( span, ast:: DUMMY_NODE_ID ) ;
348-
349- fulfill_cx. register_builtin_bound ( infcx, ty, bound, cause) ;
350-
351- // Note: we only assume something is `Copy` if we can
352- // *definitively* show that it implements `Copy`. Otherwise,
353- // assume it is move; linear is always ok.
354- match fulfill_cx. select_all_or_error ( infcx) {
355- Ok ( ( ) ) => {
356- debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} success" ,
357- ty,
358- bound) ;
359- true
360- }
361- Err ( e) => {
362- debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}" ,
363- ty,
364- bound,
365- e) ;
366- false
344+ let obligation =
345+ util:: predicate_for_builtin_bound ( infcx. tcx , cause, bound, 0 , ty) ;
346+ let obligation = match obligation {
347+ Ok ( o) => o,
348+ Err ( ..) => return false
349+ } ;
350+ let result = SelectionContext :: new ( infcx)
351+ . evaluate_obligation_conservatively ( & obligation) ;
352+ debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}" ,
353+ ty, bound, result) ;
354+
355+ if result && ( ty. has_infer_types ( ) || ty. has_closure_types ( ) ) {
356+ // Because of inference "guessing", selection can sometimes claim
357+ // to succeed while the success requires a guess. To ensure
358+ // this function's result remains infallible, we must confirm
359+ // that guess. While imperfect, I believe this is sound.
360+
361+ let mut fulfill_cx = FulfillmentContext :: new ( false ) ;
362+
363+ // We can use a dummy node-id here because we won't pay any mind
364+ // to region obligations that arise (there shouldn't really be any
365+ // anyhow).
366+ let cause = ObligationCause :: misc ( span, ast:: DUMMY_NODE_ID ) ;
367+
368+ fulfill_cx. register_builtin_bound ( infcx, ty, bound, cause) ;
369+
370+ // Note: we only assume something is `Copy` if we can
371+ // *definitively* show that it implements `Copy`. Otherwise,
372+ // assume it is move; linear is always ok.
373+ match fulfill_cx. select_all_or_error ( infcx) {
374+ Ok ( ( ) ) => {
375+ debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} success" ,
376+ ty,
377+ bound) ;
378+ true
379+ }
380+ Err ( e) => {
381+ debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}" ,
382+ ty,
383+ bound,
384+ e) ;
385+ false
386+ }
367387 }
388+ } else {
389+ result
368390 }
369391}
370392
0 commit comments