diff options
| author | bors <bors@rust-lang.org> | 2025-08-03 09:29:54 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-08-03 09:29:54 +0000 |
| commit | 7cd950546b4ce68843b4cbdb1ab3a43776202d3a (patch) | |
| tree | 0103f5ef96f3696cb4e9dbb71409b8f1ea27aa77 | |
| parent | da19b9d24c4ed900b91b45ec7f7795ec43613b1e (diff) | |
| parent | 170ccbf434112f25f596898b1117942b4bafbd22 (diff) | |
| download | rust-7cd950546b4ce68843b4cbdb1ab3a43776202d3a.tar.gz rust-7cd950546b4ce68843b4cbdb1ab3a43776202d3a.zip | |
Auto merge of #144704 - compiler-errors:explode-wf, r=lcnr
expand WF obligations when checking method calls Don't wrap a bunch of signatures in `FnPtr` then check their WF; instead, check the WFness of each input/output separately. This is useful for the new trait solver, since because we stall on root obligations we end up needing to repeatedly recompute the WFness of possibly very large function signature types if it ends up bottoming out in ambiguity. This may also give us more chances to hit the WF fast path for certain types like built-ins. Finally, this just seems conceptually correct to do. There's nothing conceptually that suggests that wrapping the function signature in an fn pointer makes sense at all to do; I'm guessing that it was just convenient so that we didn't have to register WF obligations in a loop, but it doesn't affect the readability of this code at all.
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/compare_impl_item.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/confirm.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/method/mod.rs | 21 |
3 files changed, 30 insertions, 35 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 37aaa63d0e5..6767e5ed88d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -356,14 +356,14 @@ fn compare_method_predicate_entailment<'tcx>( } if !(impl_sig, trait_sig).references_error() { - ocx.register_obligation(traits::Obligation::new( - infcx.tcx, - cause, - param_env, - ty::ClauseKind::WellFormed( - Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig)).into(), - ), - )); + for ty in unnormalized_impl_sig.inputs_and_output { + ocx.register_obligation(traits::Obligation::new( + infcx.tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(ty.into()), + )); + } } // Check that all obligations are satisfied by the implementation's diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 8d9f7eaf177..79996ff482e 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -142,7 +142,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let (method_sig, method_predicates) = self.normalize(self.span, (method_sig, method_predicates)); - let method_sig = ty::Binder::dummy(method_sig); // Make sure nobody calls `drop()` explicitly. self.check_for_illegal_method_calls(pick); @@ -154,20 +153,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. if illegal_sized_bound.is_none() { - self.add_obligations( - Ty::new_fn_ptr(self.tcx, method_sig), - all_args, - method_predicates, - pick.item.def_id, - ); + self.add_obligations(method_sig, all_args, method_predicates, pick.item.def_id); } // Create the final `MethodCallee`. - let callee = MethodCallee { - def_id: pick.item.def_id, - args: all_args, - sig: method_sig.skip_binder(), - }; + let callee = MethodCallee { def_id: pick.item.def_id, args: all_args, sig: method_sig }; ConfirmResult { callee, illegal_sized_bound } } @@ -601,14 +591,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn add_obligations( &mut self, - fty: Ty<'tcx>, + sig: ty::FnSig<'tcx>, all_args: GenericArgsRef<'tcx>, method_predicates: ty::InstantiatedPredicates<'tcx>, def_id: DefId, ) { debug!( - "add_obligations: fty={:?} all_args={:?} method_predicates={:?} def_id={:?}", - fty, all_args, method_predicates, def_id + "add_obligations: sig={:?} all_args={:?} method_predicates={:?} def_id={:?}", + sig, all_args, method_predicates, def_id ); // FIXME: could replace with the following, but we already calculated `method_predicates`, @@ -637,7 +627,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // the function type must also be well-formed (this is not // implied by the args being well-formed because of inherent // impls and late-bound regions - see issue #28609). - self.register_wf_obligation(fty.into(), self.span, ObligationCauseCode::WellFormed(None)); + for ty in sig.inputs_and_output { + self.register_wf_obligation( + ty.into(), + self.span, + ObligationCauseCode::WellFormed(None), + ); + } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 316468b0a5d..e37ea031672 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -428,19 +428,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); // Also add an obligation for the method type being well-formed. - let method_ty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(fn_sig)); debug!( - "lookup_method_in_trait: matched method method_ty={:?} obligation={:?}", - method_ty, obligation + "lookup_method_in_trait: matched method fn_sig={:?} obligation={:?}", + fn_sig, obligation ); - obligations.push(traits::Obligation::new( - tcx, - obligation.cause, - self.param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - method_ty.into(), - ))), - )); + for ty in fn_sig.inputs_and_output { + obligations.push(traits::Obligation::new( + tcx, + obligation.cause.clone(), + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into()))), + )); + } let callee = MethodCallee { def_id, args, sig: fn_sig }; debug!("callee = {:?}", callee); |
