@@ -340,47 +340,53 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
340
340
ty,
341
341
bound) ;
342
342
343
- if !ty. has_infer_types ( ) && !ty. has_closure_types ( ) {
344
- let cause = ObligationCause :: misc ( span, ast:: DUMMY_NODE_ID ) ;
345
- let obligation =
346
- util:: predicate_for_builtin_bound ( infcx. tcx , cause, bound, 0 , ty) ;
347
- let obligation = match obligation {
348
- Ok ( o) => o,
349
- Err ( ..) => return false
350
- } ;
351
- let result = SelectionContext :: new ( infcx)
352
- . evaluate_obligation_conservatively ( & obligation) ;
353
- debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}" ,
354
- ty, bound, result) ;
355
- return result;
356
- }
357
-
358
- let mut fulfill_cx = FulfillmentContext :: new ( false ) ;
359
-
360
- // We can use a dummy node-id here because we won't pay any mind
361
- // to region obligations that arise (there shouldn't really be any
362
- // anyhow).
363
343
let cause = ObligationCause :: misc ( span, ast:: DUMMY_NODE_ID ) ;
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 ) ;
364
367
365
- fulfill_cx. register_builtin_bound ( infcx, ty, bound, cause) ;
366
-
367
- // Note: we only assume something is `Copy` if we can
368
- // *definitively* show that it implements `Copy`. Otherwise,
369
- // assume it is move; linear is always ok.
370
- match fulfill_cx. select_all_or_error ( infcx) {
371
- Ok ( ( ) ) => {
372
- debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} success" ,
373
- ty,
374
- bound) ;
375
- true
376
- }
377
- Err ( e) => {
378
- debug ! ( "type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}" ,
379
- ty,
380
- bound,
381
- e) ;
382
- false
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
+ }
383
387
}
388
+ } else {
389
+ result
384
390
}
385
391
}
386
392
0 commit comments