@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, MultiSpan};
44use rustc_hir:: { self as hir, ExprKind } ;
55use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
66use rustc_infer:: traits:: Obligation ;
7- use rustc_middle:: ty:: { self , ToPredicate , Ty , TypeVisitable } ;
7+ use rustc_middle:: ty:: { self , ToPredicate , Ty } ;
88use rustc_span:: Span ;
99use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
1010use rustc_trait_selection:: traits:: {
@@ -94,7 +94,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9494 let arm_ty = self . check_expr_with_expectation ( & arm. body , expected) ;
9595 all_arms_diverge &= self . diverges . get ( ) ;
9696
97- let opt_suggest_box_span = self . opt_suggest_box_span ( arm_ty, orig_expected) ;
97+ let opt_suggest_box_span = prior_arm. and_then ( |( _, prior_arm_ty, _) | {
98+ self . opt_suggest_box_span ( prior_arm_ty, arm_ty, orig_expected)
99+ } ) ;
98100
99101 let ( arm_block_id, arm_span) = if let hir:: ExprKind :: Block ( blk, _) = arm. body . kind {
100102 ( Some ( blk. hir_id ) , self . find_block_span ( blk) )
@@ -473,43 +475,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
473475 // provide a structured suggestion in that case.
474476 pub ( crate ) fn opt_suggest_box_span (
475477 & self ,
476- outer_ty : Ty < ' tcx > ,
478+ first_ty : Ty < ' tcx > ,
479+ second_ty : Ty < ' tcx > ,
477480 orig_expected : Expectation < ' tcx > ,
478481 ) -> Option < Span > {
479482 match orig_expected {
480483 Expectation :: ExpectHasType ( expected)
481484 if self . in_tail_expr
482- && self . ret_coercion . as_ref ( ) ?. borrow ( ) . merged_ty ( ) . has_opaque_types ( )
483- && self . can_coerce ( outer_ty, expected) =>
485+ && self . return_type_has_opaque
486+ && self . can_coerce ( first_ty, expected)
487+ && self . can_coerce ( second_ty, expected) =>
484488 {
485489 let obligations = self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ;
486490 let mut suggest_box = !obligations. is_empty ( ) ;
487- for o in obligations {
488- match o. predicate . kind ( ) . skip_binder ( ) {
489- ty:: PredicateKind :: Trait ( t) => {
490- let pred =
491- ty:: Binder :: dummy ( ty:: PredicateKind :: Trait ( ty:: TraitPredicate {
492- trait_ref : ty:: TraitRef {
493- def_id : t. def_id ( ) ,
494- substs : self . tcx . mk_substs_trait ( outer_ty, & [ ] ) ,
491+ ' outer: for o in obligations {
492+ for outer_ty in & [ first_ty, second_ty] {
493+ match o. predicate . kind ( ) . skip_binder ( ) {
494+ ty:: PredicateKind :: Trait ( t) => {
495+ let pred = ty:: Binder :: dummy ( ty:: PredicateKind :: Trait (
496+ ty:: TraitPredicate {
497+ trait_ref : ty:: TraitRef {
498+ def_id : t. def_id ( ) ,
499+ substs : self . tcx . mk_substs_trait ( * outer_ty, & [ ] ) ,
500+ } ,
501+ constness : t. constness ,
502+ polarity : t. polarity ,
495503 } ,
496- constness : t. constness ,
497- polarity : t. polarity ,
498- } ) ) ;
499- let obl = Obligation :: new (
500- o. cause . clone ( ) ,
501- self . param_env ,
502- pred. to_predicate ( self . tcx ) ,
503- ) ;
504- suggest_box &= self . predicate_must_hold_modulo_regions ( & obl) ;
505- if !suggest_box {
506- // We've encountered some obligation that didn't hold, so the
507- // return expression can't just be boxed. We don't need to
508- // evaluate the rest of the obligations.
509- break ;
504+ ) ) ;
505+ let obl = Obligation :: new (
506+ o. cause . clone ( ) ,
507+ self . param_env ,
508+ pred. to_predicate ( self . tcx ) ,
509+ ) ;
510+ suggest_box &= self . predicate_must_hold_modulo_regions ( & obl) ;
511+ if !suggest_box {
512+ // We've encountered some obligation that didn't hold, so the
513+ // return expression can't just be boxed. We don't need to
514+ // evaluate the rest of the obligations.
515+ break ' outer;
516+ }
510517 }
518+ _ => { }
511519 }
512- _ => { }
513520 }
514521 }
515522 // If all the obligations hold (or there are no obligations) the tail expression
0 commit comments