Skip to content

Commit 7cd9505

Browse files
committed
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.
2 parents da19b9d + 170ccbf commit 7cd9505

File tree

3 files changed

+30
-35
lines changed

3 files changed

+30
-35
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,14 @@ fn compare_method_predicate_entailment<'tcx>(
356356
}
357357

358358
if !(impl_sig, trait_sig).references_error() {
359-
ocx.register_obligation(traits::Obligation::new(
360-
infcx.tcx,
361-
cause,
362-
param_env,
363-
ty::ClauseKind::WellFormed(
364-
Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig)).into(),
365-
),
366-
));
359+
for ty in unnormalized_impl_sig.inputs_and_output {
360+
ocx.register_obligation(traits::Obligation::new(
361+
infcx.tcx,
362+
cause.clone(),
363+
param_env,
364+
ty::ClauseKind::WellFormed(ty.into()),
365+
));
366+
}
367367
}
368368

369369
// Check that all obligations are satisfied by the implementation's

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
142142

143143
let (method_sig, method_predicates) =
144144
self.normalize(self.span, (method_sig, method_predicates));
145-
let method_sig = ty::Binder::dummy(method_sig);
146145

147146
// Make sure nobody calls `drop()` explicitly.
148147
self.check_for_illegal_method_calls(pick);
@@ -154,20 +153,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
154153
// We won't add these if we encountered an illegal sized bound, so that we can use
155154
// a custom error in that case.
156155
if illegal_sized_bound.is_none() {
157-
self.add_obligations(
158-
Ty::new_fn_ptr(self.tcx, method_sig),
159-
all_args,
160-
method_predicates,
161-
pick.item.def_id,
162-
);
156+
self.add_obligations(method_sig, all_args, method_predicates, pick.item.def_id);
163157
}
164158

165159
// Create the final `MethodCallee`.
166-
let callee = MethodCallee {
167-
def_id: pick.item.def_id,
168-
args: all_args,
169-
sig: method_sig.skip_binder(),
170-
};
160+
let callee = MethodCallee { def_id: pick.item.def_id, args: all_args, sig: method_sig };
171161
ConfirmResult { callee, illegal_sized_bound }
172162
}
173163

@@ -601,14 +591,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
601591

602592
fn add_obligations(
603593
&mut self,
604-
fty: Ty<'tcx>,
594+
sig: ty::FnSig<'tcx>,
605595
all_args: GenericArgsRef<'tcx>,
606596
method_predicates: ty::InstantiatedPredicates<'tcx>,
607597
def_id: DefId,
608598
) {
609599
debug!(
610-
"add_obligations: fty={:?} all_args={:?} method_predicates={:?} def_id={:?}",
611-
fty, all_args, method_predicates, def_id
600+
"add_obligations: sig={:?} all_args={:?} method_predicates={:?} def_id={:?}",
601+
sig, all_args, method_predicates, def_id
612602
);
613603

614604
// FIXME: could replace with the following, but we already calculated `method_predicates`,
@@ -637,7 +627,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
637627
// the function type must also be well-formed (this is not
638628
// implied by the args being well-formed because of inherent
639629
// impls and late-bound regions - see issue #28609).
640-
self.register_wf_obligation(fty.into(), self.span, ObligationCauseCode::WellFormed(None));
630+
for ty in sig.inputs_and_output {
631+
self.register_wf_obligation(
632+
ty.into(),
633+
self.span,
634+
ObligationCauseCode::WellFormed(None),
635+
);
636+
}
641637
}
642638

643639
///////////////////////////////////////////////////////////////////////////

compiler/rustc_hir_typeck/src/method/mod.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -428,19 +428,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
428428
));
429429

430430
// Also add an obligation for the method type being well-formed.
431-
let method_ty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(fn_sig));
432431
debug!(
433-
"lookup_method_in_trait: matched method method_ty={:?} obligation={:?}",
434-
method_ty, obligation
432+
"lookup_method_in_trait: matched method fn_sig={:?} obligation={:?}",
433+
fn_sig, obligation
435434
);
436-
obligations.push(traits::Obligation::new(
437-
tcx,
438-
obligation.cause,
439-
self.param_env,
440-
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
441-
method_ty.into(),
442-
))),
443-
));
435+
for ty in fn_sig.inputs_and_output {
436+
obligations.push(traits::Obligation::new(
437+
tcx,
438+
obligation.cause.clone(),
439+
self.param_env,
440+
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into()))),
441+
));
442+
}
444443

445444
let callee = MethodCallee { def_id, args, sig: fn_sig };
446445
debug!("callee = {:?}", callee);

0 commit comments

Comments
 (0)