@@ -310,6 +310,34 @@ pub fn unexpected_hidden_region_diagnostic(
310310 err
311311}
312312
313+ /// Structurally compares two types, modulo any inference variables.
314+ ///
315+ /// Returns `true` if two types are equal, or if one type is an inference variable compatible
316+ /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
317+ /// FloatVar inference type are compatible with themselves or their concrete types (Int and
318+ /// Float types, respectively). When comparing two ADTs, these rules apply recursively.
319+ pub fn same_type_modulo_infer ( a : Ty < ' tcx > , b : Ty < ' ctx > ) -> bool {
320+ match ( & a. kind ( ) , & b. kind ( ) ) {
321+ ( & ty:: Adt ( did_a, substs_a) , & ty:: Adt ( did_b, substs_b) ) => {
322+ if did_a != did_b {
323+ return false ;
324+ }
325+
326+ substs_a. types ( ) . zip ( substs_b. types ( ) ) . all ( |( a, b) | same_type_modulo_infer ( a, b) )
327+ }
328+ ( & ty:: Int ( _) , & ty:: Infer ( ty:: InferTy :: IntVar ( _) ) )
329+ | ( & ty:: Infer ( ty:: InferTy :: IntVar ( _) ) , & ty:: Int ( _) | & ty:: Infer ( ty:: InferTy :: IntVar ( _) ) )
330+ | ( & ty:: Float ( _) , & ty:: Infer ( ty:: InferTy :: FloatVar ( _) ) )
331+ | (
332+ & ty:: Infer ( ty:: InferTy :: FloatVar ( _) ) ,
333+ & ty:: Float ( _) | & ty:: Infer ( ty:: InferTy :: FloatVar ( _) ) ,
334+ )
335+ | ( & ty:: Infer ( ty:: InferTy :: TyVar ( _) ) , _)
336+ | ( _, & ty:: Infer ( ty:: InferTy :: TyVar ( _) ) ) => true ,
337+ _ => a == b,
338+ }
339+ }
340+
313341impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
314342 pub fn report_region_errors ( & self , errors : & Vec < RegionResolutionError < ' tcx > > ) {
315343 debug ! ( "report_region_errors(): {} errors to start" , errors. len( ) ) ;
@@ -1761,7 +1789,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17611789 self . get_impl_future_output_ty ( exp_found. expected ) ,
17621790 self . get_impl_future_output_ty ( exp_found. found ) ,
17631791 ) {
1764- ( Some ( exp) , Some ( found) ) if ty :: TyS :: same_type ( exp, found) => match & cause. code {
1792+ ( Some ( exp) , Some ( found) ) if same_type_modulo_infer ( exp, found) => match & cause. code {
17651793 ObligationCauseCode :: IfExpression ( box IfExpressionCause { then, .. } ) => {
17661794 diag. multipart_suggestion (
17671795 "consider `await`ing on both `Future`s" ,
@@ -1793,15 +1821,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17931821 diag. help ( "consider `await`ing on both `Future`s" ) ;
17941822 }
17951823 } ,
1796- ( _, Some ( ty) ) if ty :: TyS :: same_type ( exp_found. expected , ty) => {
1824+ ( _, Some ( ty) ) if same_type_modulo_infer ( exp_found. expected , ty) => {
17971825 diag. span_suggestion_verbose (
17981826 exp_span. shrink_to_hi ( ) ,
17991827 "consider `await`ing on the `Future`" ,
18001828 ".await" . to_string ( ) ,
18011829 Applicability :: MaybeIncorrect ,
18021830 ) ;
18031831 }
1804- ( Some ( ty) , _) if ty :: TyS :: same_type ( ty, exp_found. found ) => match cause. code {
1832+ ( Some ( ty) , _) if same_type_modulo_infer ( ty, exp_found. found ) => match cause. code {
18051833 ObligationCauseCode :: Pattern { span : Some ( span) , .. }
18061834 | ObligationCauseCode :: IfExpression ( box IfExpressionCause { then : span, .. } ) => {
18071835 diag. span_suggestion_verbose (
0 commit comments