Skip to content

Commit 9dcd6e5

Browse files
committed
Auto merge of rust-lang#122385 - lcnr:analyze-obligations-for-infer, r=<try>
`obligations_for_self_ty`: use `ProofTreeVisitor` for nested goals As always, dealing with proof trees continues to be a hacked together mess. After this PR and rust-lang#124380 the only remaining blocker for core is rust-lang/trait-system-refactor-initiative#90. There is also a `ProofTreeVisitor` issue causing an ICE when compiling `alloc` which I will handle in a separate PR. This issue likely affects coherence diagnostics more generally. The core idea is to extend the proof tree visitor to support visiting nested candidates without using a `probe`. We then simply recurse into nested candidates if they are the only potentially applicable candidate for a given goal and check whether the self type matches the expected one. For that to work, we need to improve `CanonicalState` to also handle unconstrained inference variables created inside of the trait solver. This is done by extending the `var_values` of `CanoncalState` with each fresh inference variables. Furthermore, we also store the state of all inference variables at the end of each probe. When recursing into `InspectCandidates` we then unify the values of all these states. r? `@compiler-errors`
2 parents 3a36386 + 146f637 commit 9dcd6e5

25 files changed

+677
-350
lines changed

Diff for: compiler/rustc_hir_typeck/src/closure.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
342342
ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
343343
Ty::new_var(self.tcx, self.root_var(vid)),
344344
closure_kind,
345-
self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
345+
self.obligations_for_self_ty(vid)
346+
.into_iter()
347+
.map(|obl| (obl.predicate, obl.cause.span)),
346348
),
347349
ty::FnPtr(sig) => match closure_kind {
348350
hir::ClosureKind::Closure => {
@@ -889,7 +891,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
889891

890892
let output_ty = match *ret_ty.kind() {
891893
ty::Infer(ty::TyVar(ret_vid)) => {
892-
self.obligations_for_self_ty(ret_vid).find_map(|obligation| {
894+
self.obligations_for_self_ty(ret_vid).into_iter().find_map(|obligation| {
893895
get_future_output(obligation.predicate, obligation.cause.span)
894896
})?
895897
}

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+22-81
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use crate::errors::CtorIsPrivate;
33
use crate::method::{self, MethodCallee, SelfSource};
44
use crate::rvalue_scopes;
55
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
6-
use rustc_data_structures::captures::Captures;
76
use rustc_data_structures::fx::FxHashSet;
87
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey};
98
use rustc_hir as hir;
@@ -47,7 +46,7 @@ use std::slice;
4746
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4847
/// Produces warning on the given node, if the current point in the
4948
/// function is unreachable, and there hasn't been another warning.
50-
pub(in super::super) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
49+
pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
5150
// FIXME: Combine these two 'if' expressions into one once
5251
// let chains are implemented
5352
if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() {
@@ -87,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8786
// FIXME(-Znext-solver): A lot of the calls to this method should
8887
// probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead.
8988
#[instrument(skip(self), level = "debug", ret)]
90-
pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
89+
pub(crate) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
9190
// No Infer()? Nothing needs doing.
9291
if !ty.has_non_region_infer() {
9392
debug!("no inference var, nothing needs doing");
@@ -109,7 +108,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
109108
self.resolve_vars_if_possible(ty)
110109
}
111110

112-
pub(in super::super) fn record_deferred_call_resolution(
111+
pub(crate) fn record_deferred_call_resolution(
113112
&self,
114113
closure_def_id: LocalDefId,
115114
r: DeferredCallResolution<'tcx>,
@@ -118,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
118117
deferred_call_resolutions.entry(closure_def_id).or_default().push(r);
119118
}
120119

121-
pub(in super::super) fn remove_deferred_call_resolutions(
120+
pub(crate) fn remove_deferred_call_resolutions(
122121
&self,
123122
closure_def_id: LocalDefId,
124123
) -> Vec<DeferredCallResolution<'tcx>> {
@@ -172,7 +171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172171
}
173172

174173
#[instrument(level = "debug", skip(self))]
175-
pub(in super::super) fn write_resolution(
174+
pub(crate) fn write_resolution(
176175
&self,
177176
hir_id: HirId,
178177
r: Result<(DefKind, DefId), ErrorGuaranteed>,
@@ -336,7 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
336335
}
337336

338337
/// Instantiates and normalizes the bounds for a given item
339-
pub(in super::super) fn instantiate_bounds(
338+
pub(crate) fn instantiate_bounds(
340339
&self,
341340
span: Span,
342341
def_id: DefId,
@@ -349,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
349348
result
350349
}
351350

352-
pub(in super::super) fn normalize<T>(&self, span: Span, value: T) -> T
351+
pub(crate) fn normalize<T>(&self, span: Span, value: T) -> T
353352
where
354353
T: TypeFoldable<TyCtxt<'tcx>>,
355354
{
@@ -537,7 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
537536
self.normalize(span, field.ty(self.tcx, args))
538537
}
539538

540-
pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
539+
pub(crate) fn resolve_rvalue_scopes(&self, def_id: DefId) {
541540
let scope_tree = self.tcx.region_scope_tree(def_id);
542541
let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) };
543542
let mut typeck_results = self.typeck_results.borrow_mut();
@@ -553,7 +552,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
553552
/// We must not attempt to select obligations after this method has run, or risk query cycle
554553
/// ICE.
555554
#[instrument(level = "debug", skip(self))]
556-
pub(in super::super) fn resolve_coroutine_interiors(&self) {
555+
pub(crate) fn resolve_coroutine_interiors(&self) {
557556
// Try selecting all obligations that are not blocked on inference variables.
558557
// Once we start unifying coroutine witnesses, trying to select obligations on them will
559558
// trigger query cycle ICEs, as doing so requires MIR.
@@ -594,7 +593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
594593
}
595594

596595
#[instrument(skip(self), level = "debug")]
597-
pub(in super::super) fn report_ambiguity_errors(&self) {
596+
pub(crate) fn report_ambiguity_errors(&self) {
598597
let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors(self);
599598

600599
if !errors.is_empty() {
@@ -609,7 +608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
609608
}
610609

611610
/// Select as many obligations as we can at present.
612-
pub(in super::super) fn select_obligations_where_possible(
611+
pub(crate) fn select_obligations_where_possible(
613612
&self,
614613
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
615614
) {
@@ -625,7 +624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
625624
/// returns a type of `&T`, but the actual type we assign to the
626625
/// *expression* is `T`. So this function just peels off the return
627626
/// type by one layer to yield `T`.
628-
pub(in super::super) fn make_overloaded_place_return_type(
627+
pub(crate) fn make_overloaded_place_return_type(
629628
&self,
630629
method: MethodCallee<'tcx>,
631630
) -> ty::TypeAndMut<'tcx> {
@@ -636,67 +635,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
636635
ret_ty.builtin_deref(true).unwrap()
637636
}
638637

639-
#[instrument(skip(self), level = "debug")]
640-
fn self_type_matches_expected_vid(&self, self_ty: Ty<'tcx>, expected_vid: ty::TyVid) -> bool {
641-
let self_ty = self.shallow_resolve(self_ty);
642-
debug!(?self_ty);
643-
644-
match *self_ty.kind() {
645-
ty::Infer(ty::TyVar(found_vid)) => {
646-
let found_vid = self.root_var(found_vid);
647-
debug!("self_type_matches_expected_vid - found_vid={:?}", found_vid);
648-
expected_vid == found_vid
649-
}
650-
_ => false,
651-
}
652-
}
653-
654-
#[instrument(skip(self), level = "debug")]
655-
pub(in super::super) fn obligations_for_self_ty<'b>(
656-
&'b self,
657-
self_ty: ty::TyVid,
658-
) -> impl DoubleEndedIterator<Item = traits::PredicateObligation<'tcx>> + Captures<'tcx> + 'b
659-
{
660-
let ty_var_root = self.root_var(self_ty);
661-
trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations());
662-
663-
self.fulfillment_cx.borrow().pending_obligations().into_iter().filter_map(
664-
move |obligation| match &obligation.predicate.kind().skip_binder() {
665-
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data))
666-
if self.self_type_matches_expected_vid(
667-
data.projection_ty.self_ty(),
668-
ty_var_root,
669-
) =>
670-
{
671-
Some(obligation)
672-
}
673-
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data))
674-
if self.self_type_matches_expected_vid(data.self_ty(), ty_var_root) =>
675-
{
676-
Some(obligation)
677-
}
678-
679-
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
680-
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
681-
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
682-
| ty::PredicateKind::Subtype(..)
683-
| ty::PredicateKind::Coerce(..)
684-
| ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
685-
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
686-
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
687-
| ty::PredicateKind::ObjectSafe(..)
688-
| ty::PredicateKind::NormalizesTo(..)
689-
| ty::PredicateKind::AliasRelate(..)
690-
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
691-
| ty::PredicateKind::ConstEquate(..)
692-
| ty::PredicateKind::Ambiguous => None,
693-
},
694-
)
695-
}
696-
697-
pub(in super::super) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool {
638+
pub(crate) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool {
698639
let sized_did = self.tcx.lang_items().sized_trait();
699-
self.obligations_for_self_ty(self_ty).any(|obligation| {
640+
self.obligations_for_self_ty(self_ty).into_iter().any(|obligation| {
700641
match obligation.predicate.kind().skip_binder() {
701642
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
702643
Some(data.def_id()) == sized_did
@@ -706,15 +647,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
706647
})
707648
}
708649

709-
pub(in super::super) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
650+
pub(crate) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
710651
let ty_error = Ty::new_misc_error(self.tcx);
711652
vec![ty_error; len]
712653
}
713654

714655
/// Unifies the output type with the expected type early, for more coercions
715656
/// and forward type information on the input expressions.
716657
#[instrument(skip(self, call_span), level = "debug")]
717-
pub(in super::super) fn expected_inputs_for_expected_output(
658+
pub(crate) fn expected_inputs_for_expected_output(
718659
&self,
719660
call_span: Span,
720661
expected_ret: Expectation<'tcx>,
@@ -747,7 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
747688
expect_args
748689
}
749690

750-
pub(in super::super) fn resolve_lang_item_path(
691+
pub(crate) fn resolve_lang_item_path(
751692
&self,
752693
lang_item: hir::LangItem,
753694
span: Span,
@@ -926,7 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
926867
/// but we often want access to the parent function's signature.
927868
///
928869
/// Otherwise, return false.
929-
pub(in super::super) fn get_node_fn_decl(
870+
pub(crate) fn get_node_fn_decl(
930871
&self,
931872
node: Node<'tcx>,
932873
) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, Ident, bool)> {
@@ -1004,7 +945,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1004945
})
1005946
}
1006947

1007-
pub(in super::super) fn note_internal_mutation_in_method(
948+
pub(crate) fn note_internal_mutation_in_method(
1008949
&self,
1009950
err: &mut Diag<'_>,
1010951
expr: &hir::Expr<'_>,
@@ -1549,7 +1490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15491490
}
15501491
}
15511492

1552-
pub(in super::super) fn with_breakable_ctxt<F: FnOnce() -> R, R>(
1493+
pub(crate) fn with_breakable_ctxt<F: FnOnce() -> R, R>(
15531494
&self,
15541495
id: HirId,
15551496
ctxt: BreakableCtxt<'tcx>,
@@ -1575,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15751516

15761517
/// Instantiate a QueryResponse in a probe context, without a
15771518
/// good ObligationCause.
1578-
pub(in super::super) fn probe_instantiate_query_response(
1519+
pub(crate) fn probe_instantiate_query_response(
15791520
&self,
15801521
span: Span,
15811522
original_values: &OriginalQueryValues<'tcx>,
@@ -1590,7 +1531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15901531
}
15911532

15921533
/// Returns `true` if an expression is contained inside the LHS of an assignment expression.
1593-
pub(in super::super) fn expr_in_place(&self, mut expr_id: HirId) -> bool {
1534+
pub(crate) fn expr_in_place(&self, mut expr_id: HirId) -> bool {
15941535
let mut contained_in_place = false;
15951536

15961537
while let hir::Node::Expr(parent_expr) = self.tcx.parent_hir_node(expr_id) {

0 commit comments

Comments
 (0)