From f6f5d72ab2dfd794b7fc4f61d79ea1935bfaaf71 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Aug 2024 11:43:43 -0400 Subject: [PATCH] Don't do expected type fudging if the inputs don't need inference guidance --- compiler/rustc_hir_typeck/src/expr.rs | 24 ++++---- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 59 +++++++++++-------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 92affab722c9..3325c4c6a9a4 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1669,17 +1669,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let adt_ty = self.resolve_vars_with_obligations(adt_ty); - let adt_ty_hint = expected.only_has_type(self).and_then(|expected| { - self.fudge_inference_if_ok(|| { - let ocx = ObligationCtxt::new(self); - ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?; - if !ocx.select_where_possible().is_empty() { - return Err(TypeError::Mismatch); - } - Ok(self.resolve_vars_if_possible(adt_ty)) + let adt_ty_hint = if adt_ty.has_non_region_infer() { + expected.only_has_type(self).and_then(|expected| { + self.fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); + } + Ok(self.resolve_vars_if_possible(adt_ty)) + }) + .ok() }) - .ok() - }); + } else { + None + }; if let Some(adt_ty_hint) = adt_ty_hint { // re-link the variables that the fudging above can create. self.demand_eqtype(span, adt_ty_hint, adt_ty); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index acc8243b7fb7..0b6b1e7de2fa 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -211,35 +211,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We use this to guide coercion inference; it's output is "fudged" which means // any remaining type variables are assigned to new, unrelated variables. This // is because the inference guidance here is only speculative. + // + // We only do this if the formals have non-region infer vars, since this is only + // meant to guide inference. let formal_output = self.resolve_vars_with_obligations(formal_output); - let expected_input_tys: Option> = expectation - .only_has_type(self) - .and_then(|expected_output| { - self.fudge_inference_if_ok(|| { - let ocx = ObligationCtxt::new(self); - - // Attempt to apply a subtyping relationship between the formal - // return type (likely containing type variables if the function - // is polymorphic) and the expected return type. - // No argument expectations are produced if unification fails. - let origin = self.misc(call_span); - ocx.sup(&origin, self.param_env, expected_output, formal_output)?; - if !ocx.select_where_possible().is_empty() { - return Err(TypeError::Mismatch); - } + let expected_input_tys: Option> = if formal_input_tys.has_non_region_infer() { + expectation + .only_has_type(self) + .and_then(|expected_output| { + self.fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + + // Attempt to apply a subtyping relationship between the formal + // return type (likely containing type variables if the function + // is polymorphic) and the expected return type. + // No argument expectations are produced if unification fails. + let origin = self.misc(call_span); + ocx.sup(&origin, self.param_env, expected_output, formal_output)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); + } - // Record all the argument types, with the args - // produced from the above subtyping unification. - Ok(Some( - formal_input_tys - .iter() - .map(|&ty| self.resolve_vars_if_possible(ty)) - .collect(), - )) + // Record all the argument types, with the args + // produced from the above subtyping unification. + Ok(Some( + formal_input_tys + .iter() + .map(|&ty| self.resolve_vars_if_possible(ty)) + .collect(), + )) + }) + .ok() }) - .ok() - }) - .unwrap_or_default(); + .unwrap_or_default() + } else { + None + }; let mut err_code = E0061;