From f20efc4c61a0d5deaf86988565a0214733ff0e6b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 09:49:24 +0000 Subject: [PATCH 1/7] Handle `UnsafePointer` coercions in one place --- compiler/rustc_hir_typeck/src/coercion.rs | 60 +++++++++-------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index f1571cf4c8317..c19e0a0574013 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -247,7 +247,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::FnPtr(a_sig_tys, a_hdr) => { // We permit coercion of fn pointers to drop the // unsafe qualifier. - self.coerce_from_fn_pointer(a, a_sig_tys.with(a_hdr), b) + self.coerce_from_fn_pointer(a_sig_tys.with(a_hdr), b) } ty::Closure(closure_def_id_a, args_a) => { // Non-capturing closures are coercible to @@ -813,18 +813,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }) } - fn coerce_from_safe_fn( + fn coerce_from_safe_fn( &self, - a: Ty<'tcx>, fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>, - to_unsafe: F, - normal: G, - ) -> CoerceResult<'tcx> - where - F: FnOnce(Ty<'tcx>) -> Vec>, - G: FnOnce(Ty<'tcx>) -> Vec>, - { + adjustment: Option, + ) -> CoerceResult<'tcx> { self.commit_if_ok(|snapshot| { let outer_universe = self.infcx.universe(); @@ -833,9 +827,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - self.unify_and(unsafe_a, b, to_unsafe) + self.unify_and(unsafe_a, b, |target| match adjustment { + Some(kind) => vec![ + Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }, + Adjustment { + kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + target, + }, + ], + None => simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer))(target), + }) } else { - self.unify_and(a, b, normal) + let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); + self.unify_and(a, b, |target| match adjustment { + None => vec![], + Some(kind) => vec![Adjustment { kind, target }], + }) }; // FIXME(#73154): This is a hack. Currently LUB can generate @@ -852,7 +859,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn coerce_from_fn_pointer( &self, - a: Ty<'tcx>, fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>, ) -> CoerceResult<'tcx> { @@ -861,15 +867,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { //! let b = self.shallow_resolve(b); - debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b); - - self.coerce_from_safe_fn( - a, - fn_ty_a, - b, - simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer)), - identity, - ) + debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer"); + + self.coerce_from_safe_fn(fn_ty_a, b, None) } fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { @@ -916,24 +916,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.at(&self.cause, self.param_env).normalize(a_sig); obligations.extend(o1); - let a_fn_pointer = Ty::new_fn_ptr(self.tcx, a_sig); let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn( - a_fn_pointer, a_sig, b, - |unsafe_ty| { - vec![ - Adjustment { - kind: Adjust::Pointer(PointerCoercion::ReifyFnPointer), - target: a_fn_pointer, - }, - Adjustment { - kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - target: unsafe_ty, - }, - ] - }, - simple(Adjust::Pointer(PointerCoercion::ReifyFnPointer)), + Some(Adjust::Pointer(PointerCoercion::ReifyFnPointer)), )?; obligations.extend(o2); From 697768a6645468e2a67a2df3c022b32d450a7f06 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 12:46:08 +0000 Subject: [PATCH 2/7] Simplify some `unify_and` calls --- compiler/rustc_hir_typeck/src/coercion.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index c19e0a0574013..9e1a4703b9957 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -191,7 +191,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // we have no information about the source type. This will always // ultimately fall back to some form of subtyping. if a.is_ty_var() { - return self.coerce_from_inference_variable(a, b, identity); + return self.coerce_from_inference_variable(a, b); } // Consider coercing the subtype to a DST @@ -265,12 +265,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { /// Coercing *from* an inference variable. In this case, we have no information /// about the source type, so we can't really do a true coercion and we always /// fall back to subtyping (`unify_and`). - fn coerce_from_inference_variable( - &self, - a: Ty<'tcx>, - b: Ty<'tcx>, - make_adjustments: impl FnOnce(Ty<'tcx>) -> Vec>, - ) -> CoerceResult<'tcx> { + fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b); assert!(a.is_ty_var() && self.shallow_resolve(a) == a); assert!(self.shallow_resolve(b) == b); @@ -298,12 +293,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { "coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}", target_ty, obligations ); - let adjustments = make_adjustments(target_ty); - InferResult::Ok(InferOk { value: (adjustments, target_ty), obligations }) + success(vec![], target_ty, obligations) } else { // One unresolved type variable: just apply subtyping, we may be able // to do something useful. - self.unify_and(a, b, make_adjustments) + self.unify_and(a, b, identity) } } @@ -708,7 +702,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && let ty::Dynamic(b_data, _, ty::DynStar) = b.kind() && a_data.principal_def_id() == b_data.principal_def_id() { - return self.unify_and(a, b, |_| vec![]); + return self.unify_and(a, b, identity); } // Check the obligations of the cast -- for example, when casting @@ -808,9 +802,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // To complete the reborrow, we need to make sure we can unify the inner types, and if so we // add the adjustments. - self.unify_and(a, b, |_inner_ty| { - vec![Adjustment { kind: Adjust::ReborrowPin(mut_b), target: b }] - }) + self.unify_and(a, b, simple(Adjust::ReborrowPin(mut_b))) } fn coerce_from_safe_fn( From 804b6c963688a78f041bab93247c3cf0c78d7f2b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 12:57:43 +0000 Subject: [PATCH 3/7] Rename `unify` to `unify_raw` --- compiler/rustc_hir_typeck/src/coercion.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9e1a4703b9957..44b966e610edb 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -131,7 +131,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Coerce { fcx, cause, allow_two_phase, use_lub: false, coerce_never } } - fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { + fn unify_raw(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.commit_if_ok(|_| { let at = self.at(&self.cause, self.fcx.param_env); @@ -166,7 +166,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { where F: FnOnce(Ty<'tcx>) -> Vec>, { - self.unify(a, b) + self.unify_raw(a, b) .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations)) } @@ -431,7 +431,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { referent_ty, mutbl_b, // [1] above ); - match self.unify(derefd_ty_a, b) { + match self.unify_raw(derefd_ty_a, b) { Ok(ok) => { found = Some(ok); break; @@ -1096,9 +1096,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion. let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); - coerce - .autoderef(DUMMY_SP, expr_ty) - .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps)) + coerce.autoderef(DUMMY_SP, expr_ty).find_map(|(ty, steps)| { + self.probe(|_| coerce.unify_raw(ty, target)).ok().map(|_| steps) + }) } /// Given a type, this function will calculate and return the type given From 34258d62cd61c7cca7d1b957724717cd7df6c2ec Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 12:58:33 +0000 Subject: [PATCH 4/7] Add a dedicated function for the common `unify_and(identity)` case --- compiler/rustc_hir_typeck/src/coercion.rs | 29 ++++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 44b966e610edb..80592ea53d984 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -103,11 +103,6 @@ fn coerce_mutbls<'tcx>( if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) } } -/// Do not require any adjustments, i.e. coerce `x -> x`. -fn identity(_: Ty<'_>) -> Vec> { - vec![] -} - fn simple<'tcx>(kind: Adjust) -> impl FnOnce(Ty<'tcx>) -> Vec> { move |target| vec![Adjustment { kind, target }] } @@ -161,6 +156,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }) } + /// Unify two types (using sub or lub). + fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { + self.unify_raw(a, b) + .and_then(|InferOk { value: ty, obligations }| success(vec![], ty, obligations)) + } + /// Unify two types (using sub or lub) and produce a specific coercion. fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, f: F) -> CoerceResult<'tcx> where @@ -183,7 +184,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new()); } else { // Otherwise the only coercion we can do is unification. - return self.unify_and(a, b, identity); + return self.unify(a, b); } } @@ -257,7 +258,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } _ => { // Otherwise, just use unification rules. - self.unify_and(a, b, identity) + self.unify(a, b) } } } @@ -297,7 +298,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } else { // One unresolved type variable: just apply subtyping, we may be able // to do something useful. - self.unify_and(a, b, identity) + self.unify(a, b) } } @@ -325,7 +326,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { coerce_mutbls(mt_a.mutbl, mutbl_b)?; (r_a, mt_a) } - _ => return self.unify_and(a, b, identity), + _ => return self.unify(a, b), }; let span = self.cause.span; @@ -702,7 +703,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && let ty::Dynamic(b_data, _, ty::DynStar) = b.kind() && a_data.principal_def_id() == b_data.principal_def_id() { - return self.unify_and(a, b, identity); + return self.unify(a, b); } // Check the obligations of the cast -- for example, when casting @@ -917,7 +918,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { obligations.extend(o2); Ok(InferOk { value, obligations }) } - _ => self.unify_and(a, b, identity), + _ => self.unify(a, b), } } @@ -964,7 +965,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety))), ) } - _ => self.unify_and(a, b, identity), + _ => self.unify(a, b), } } @@ -979,7 +980,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let (is_ref, mt_a) = match *a.kind() { ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }), ty::RawPtr(ty, mutbl) => (false, ty::TypeAndMut { ty, mutbl }), - _ => return self.unify_and(a, b, identity), + _ => return self.unify(a, b), }; coerce_mutbls(mt_a.mutbl, mutbl_b)?; @@ -998,7 +999,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } else if mt_a.mutbl != mutbl_b { self.unify_and(a_raw, b, simple(Adjust::Pointer(PointerCoercion::MutToConstPointer))) } else { - self.unify_and(a_raw, b, identity) + self.unify(a_raw, b) } } } From 3528a65dd75c9f0ace6aa8dd8ce75e2ce97027b0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 13:03:45 +0000 Subject: [PATCH 5/7] Deduplicate `target` type setting in `unify_and` callbacks --- compiler/rustc_hir_typeck/src/coercion.rs | 90 +++++++++++++---------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 80592ea53d984..4f95d20251f2b 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -103,10 +103,6 @@ fn coerce_mutbls<'tcx>( if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) } } -fn simple<'tcx>(kind: Adjust) -> impl FnOnce(Ty<'tcx>) -> Vec> { - move |target| vec![Adjustment { kind, target }] -} - /// This always returns `Ok(...)`. fn success<'tcx>( adj: Vec>, @@ -163,12 +159,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } /// Unify two types (using sub or lub) and produce a specific coercion. - fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, f: F) -> CoerceResult<'tcx> - where - F: FnOnce(Ty<'tcx>) -> Vec>, - { - self.unify_raw(a, b) - .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations)) + fn unify_and( + &self, + a: Ty<'tcx>, + b: Ty<'tcx>, + mut adjustments: Vec>, + final_adjustment: Adjust, + ) -> CoerceResult<'tcx> { + self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| { + adjustments.push(Adjustment { target: ty, kind: final_adjustment }); + success(adjustments, ty, obligations) + }) } #[instrument(skip(self))] @@ -181,7 +182,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Coercing from `!` to any type is allowed: if a.is_never() { if self.coerce_never { - return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new()); + return success( + vec![Adjustment { kind: Adjust::NeverToAny, target: b }], + b, + PredicateObligations::new(), + ); } else { // Otherwise the only coercion we can do is unification. return self.unify(a, b); @@ -574,13 +579,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. let coerce_target = self.next_ty_var(self.cause.span); - let mut coercion = self.unify_and(coerce_target, target, |target| { - let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target }; + let mut coercion = self.unify_and( + coerce_target, + target, match reborrow { - None => vec![unsize], - Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone(), unsize], - } - })?; + None => vec![], + Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone()], + }, + Adjust::Pointer(PointerCoercion::Unsize), + )?; let mut selcx = traits::SelectionContext::new(self); @@ -803,7 +810,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // To complete the reborrow, we need to make sure we can unify the inner types, and if so we // add the adjustments. - self.unify_and(a, b, simple(Adjust::ReborrowPin(mut_b))) + self.unify_and(a, b, vec![], Adjust::ReborrowPin(mut_b)) } fn coerce_from_safe_fn( @@ -820,22 +827,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - self.unify_and(unsafe_a, b, |target| match adjustment { - Some(kind) => vec![ - Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }, - Adjustment { - kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - target, - }, - ], - None => simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer))(target), - }) + let adjustments = match adjustment { + Some(kind) => { + vec![Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }] + } + None => vec![], + }; + self.unify_and( + unsafe_a, + b, + adjustments, + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ) } else { let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); - self.unify_and(a, b, |target| match adjustment { - None => vec![], - Some(kind) => vec![Adjustment { kind, target }], - }) + match adjustment { + Some(adjust) => self.unify_and(a, b, vec![], adjust), + None => self.unify(a, b), + } }; // FIXME(#73154): This is a hack. Currently LUB can generate @@ -962,7 +971,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( pointer_ty, b, - simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety))), + vec![], + Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety)), ) } _ => self.unify(a, b), @@ -990,14 +1000,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // representation, we still register an Adjust::DerefRef so that // regionck knows that the region for `a` must be valid here. if is_ref { - self.unify_and(a_raw, b, |target| { - vec![ - Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }, - Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), target }, - ] - }) + self.unify_and( + a_raw, + b, + vec![Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], + Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), + ) } else if mt_a.mutbl != mutbl_b { - self.unify_and(a_raw, b, simple(Adjust::Pointer(PointerCoercion::MutToConstPointer))) + self.unify_and(a_raw, b, vec![], Adjust::Pointer(PointerCoercion::MutToConstPointer)) } else { self.unify(a_raw, b) } From 673012faf7085d426d6598b8e445ad8630921723 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Apr 2025 07:12:12 +0000 Subject: [PATCH 6/7] Some performance shenanigans --- compiler/rustc_hir_typeck/src/coercion.rs | 69 +++++++++++++---------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4f95d20251f2b..ec198c2529750 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -163,12 +163,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { &self, a: Ty<'tcx>, b: Ty<'tcx>, - mut adjustments: Vec>, + adjustments: impl IntoIterator>, final_adjustment: Adjust, ) -> CoerceResult<'tcx> { self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| { - adjustments.push(Adjustment { target: ty, kind: final_adjustment }); - success(adjustments, ty, obligations) + success( + adjustments + .into_iter() + .chain(std::iter::once(Adjustment { target: ty, kind: final_adjustment })) + .collect(), + ty, + obligations, + ) }) } @@ -579,15 +585,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. let coerce_target = self.next_ty_var(self.cause.span); - let mut coercion = self.unify_and( - coerce_target, - target, - match reborrow { - None => vec![], - Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone()], - }, - Adjust::Pointer(PointerCoercion::Unsize), - )?; + + let mut coercion = match reborrow { + None => { + self.unify_and(coerce_target, target, [], Adjust::Pointer(PointerCoercion::Unsize))? + } + Some((ref deref, ref autoref)) => self.unify_and( + coerce_target, + target, + [deref.clone(), autoref.clone()], + Adjust::Pointer(PointerCoercion::Unsize), + )?, + }; let mut selcx = traits::SelectionContext::new(self); @@ -810,7 +819,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // To complete the reborrow, we need to make sure we can unify the inner types, and if so we // add the adjustments. - self.unify_and(a, b, vec![], Adjust::ReborrowPin(mut_b)) + self.unify_and(a, b, [], Adjust::ReborrowPin(mut_b)) } fn coerce_from_safe_fn( @@ -827,22 +836,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - let adjustments = match adjustment { - Some(kind) => { - vec![Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }] - } - None => vec![], - }; - self.unify_and( - unsafe_a, - b, - adjustments, - Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - ) + match adjustment { + Some(kind) => self.unify_and( + unsafe_a, + b, + [Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }], + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ), + None => self.unify_and( + unsafe_a, + b, + [], + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ), + } } else { let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); match adjustment { - Some(adjust) => self.unify_and(a, b, vec![], adjust), + Some(adjust) => self.unify_and(a, b, [], adjust), None => self.unify(a, b), } }; @@ -971,7 +982,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( pointer_ty, b, - vec![], + [], Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety)), ) } @@ -1003,11 +1014,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( a_raw, b, - vec![Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], + [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), ) } else if mt_a.mutbl != mutbl_b { - self.unify_and(a_raw, b, vec![], Adjust::Pointer(PointerCoercion::MutToConstPointer)) + self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCoercion::MutToConstPointer)) } else { self.unify(a_raw, b) } From f80b12129ea8a58464a685abefd1f36819d3dd7b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Apr 2025 08:15:03 +0000 Subject: [PATCH 7/7] Avoid some more duplication --- compiler/rustc_hir_typeck/src/coercion.rs | 38 ++++++++--------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ec198c2529750..fd899425f62d2 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -586,17 +586,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // for the former and let type inference do the rest. let coerce_target = self.next_ty_var(self.cause.span); - let mut coercion = match reborrow { - None => { - self.unify_and(coerce_target, target, [], Adjust::Pointer(PointerCoercion::Unsize))? - } - Some((ref deref, ref autoref)) => self.unify_and( - coerce_target, - target, - [deref.clone(), autoref.clone()], - Adjust::Pointer(PointerCoercion::Unsize), - )?, - }; + let mut coercion = self.unify_and( + coerce_target, + target, + reborrow.into_iter().flat_map(|(deref, autoref)| [deref, autoref]), + Adjust::Pointer(PointerCoercion::Unsize), + )?; let mut selcx = traits::SelectionContext::new(self); @@ -836,20 +831,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - match adjustment { - Some(kind) => self.unify_and( - unsafe_a, - b, - [Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }], - Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - ), - None => self.unify_and( - unsafe_a, - b, - [], - Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - ), - } + self.unify_and( + unsafe_a, + b, + adjustment + .map(|kind| Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }), + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ) } else { let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); match adjustment {