Skip to content

Commit f76c8f7

Browse files
authored
Rollup merge of rust-lang#124759 - compiler-errors:impl-args, r=lcnr
Record impl args in the proof tree in new solver Rather than rematching them during select. Also use `ImplSource::Param` instead of `ImplSource::Builtin` for alias-bound candidates, so we don't ICE in `Instance::resolve`. r? lcnr
2 parents 3111015 + e347239 commit f76c8f7

File tree

8 files changed

+111
-65
lines changed

8 files changed

+111
-65
lines changed

compiler/rustc_middle/src/traits/solve/inspect.rs

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ pub enum ProbeStep<'tcx> {
123123
/// used whenever there are multiple candidates to prove the
124124
/// current goalby .
125125
NestedProbe(Probe<'tcx>),
126+
/// A trait goal was satisfied by an impl candidate.
127+
RecordImplArgs { impl_args: CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> },
126128
/// A call to `EvalCtxt::evaluate_added_goals_make_canonical_response` with
127129
/// `Certainty` was made. This is the certainty passed in, so it's not unified
128130
/// with the certainty of the `try_evaluate_added_goals` that is done within;

compiler/rustc_middle/src/traits/solve/inspect/format.rs

+3
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
136136
ProbeStep::MakeCanonicalResponse { shallow_certainty } => {
137137
writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")?
138138
}
139+
ProbeStep::RecordImplArgs { impl_args } => {
140+
writeln!(this.f, "RECORDED IMPL ARGS: {impl_args:?}")?
141+
}
139142
}
140143
}
141144
Ok(())

compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
587587

588588
Ok(unchanged_certainty)
589589
}
590+
591+
/// Record impl args in the proof tree for later access by `InspectCandidate`.
592+
pub(crate) fn record_impl_args(&mut self, impl_args: ty::GenericArgsRef<'tcx>) {
593+
self.inspect.record_impl_args(self.infcx, self.max_input_universe, impl_args)
594+
}
590595
}
591596

592597
impl<'tcx> EvalCtxt<'_, 'tcx> {

compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs

+21-59
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use std::ops::ControlFlow;
22

3-
use rustc_hir::def_id::DefId;
4-
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
3+
use rustc_infer::infer::InferCtxt;
54
use rustc_infer::traits::solve::inspect::ProbeKind;
65
use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal};
76
use rustc_infer::traits::{
87
BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause,
9-
PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult,
8+
PolyTraitObligation, Selection, SelectionError, SelectionResult,
109
};
1110
use rustc_macros::extension;
1211
use rustc_span::Span;
@@ -141,32 +140,32 @@ fn to_selection<'tcx>(
141140
return None;
142141
}
143142

144-
let make_nested = || {
145-
cand.instantiate_nested_goals(span)
146-
.into_iter()
147-
.map(|nested| {
148-
Obligation::new(
149-
nested.infcx().tcx,
150-
ObligationCause::dummy_with_span(span),
151-
nested.goal().param_env,
152-
nested.goal().predicate,
153-
)
154-
})
155-
.collect()
156-
};
143+
let (nested, impl_args) = cand.instantiate_nested_goals_and_opt_impl_args(span);
144+
let nested = nested
145+
.into_iter()
146+
.map(|nested| {
147+
Obligation::new(
148+
nested.infcx().tcx,
149+
ObligationCause::dummy_with_span(span),
150+
nested.goal().param_env,
151+
nested.goal().predicate,
152+
)
153+
})
154+
.collect();
157155

158156
Some(match cand.kind() {
159157
ProbeKind::TraitCandidate { source, result: _ } => match source {
160158
CandidateSource::Impl(impl_def_id) => {
161159
// FIXME: Remove this in favor of storing this in the tree
162160
// For impl candidates, we do the rematch manually to compute the args.
163-
ImplSource::UserDefined(rematch_impl(cand.goal(), impl_def_id, span))
164-
}
165-
CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, make_nested()),
166-
CandidateSource::ParamEnv(_) => ImplSource::Param(make_nested()),
167-
CandidateSource::AliasBound => {
168-
ImplSource::Builtin(BuiltinImplSource::Misc, make_nested())
161+
ImplSource::UserDefined(ImplSourceUserDefinedData {
162+
impl_def_id,
163+
args: impl_args.expect("expected recorded impl args for impl candidate"),
164+
nested,
165+
})
169166
}
167+
CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, nested),
168+
CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => ImplSource::Param(nested),
170169
CandidateSource::CoherenceUnknowable => {
171170
span_bug!(span, "didn't expect to select an unknowable candidate")
172171
}
@@ -181,40 +180,3 @@ fn to_selection<'tcx>(
181180
}
182181
})
183182
}
184-
185-
fn rematch_impl<'tcx>(
186-
goal: &inspect::InspectGoal<'_, 'tcx>,
187-
impl_def_id: DefId,
188-
span: Span,
189-
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
190-
let infcx = goal.infcx();
191-
let goal_trait_ref = infcx
192-
.enter_forall_and_leak_universe(goal.goal().predicate.to_opt_poly_trait_pred().unwrap())
193-
.trait_ref;
194-
195-
let args = infcx.fresh_args_for_item(span, impl_def_id);
196-
let impl_trait_ref =
197-
infcx.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(infcx.tcx, args);
198-
199-
let InferOk { value: (), obligations: mut nested } = infcx
200-
.at(&ObligationCause::dummy_with_span(span), goal.goal().param_env)
201-
.eq(DefineOpaqueTypes::Yes, goal_trait_ref, impl_trait_ref)
202-
.expect("rematching impl failed");
203-
204-
// FIXME(-Znext-solver=coinductive): We need to add supertraits here eventually.
205-
206-
nested.extend(
207-
infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, args).into_iter().map(
208-
|(clause, _)| {
209-
Obligation::new(
210-
infcx.tcx,
211-
ObligationCause::dummy_with_span(span),
212-
goal.goal().param_env,
213-
clause,
214-
)
215-
},
216-
),
217-
);
218-
219-
ImplSourceUserDefinedData { impl_def_id, nested, args }
220-
}

compiler/rustc_trait_selection/src/solve/inspect/analyse.rs

+37-5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub struct InspectCandidate<'a, 'tcx> {
9393
kind: inspect::ProbeKind<'tcx>,
9494
nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
9595
final_state: inspect::CanonicalState<'tcx, ()>,
96+
impl_args: Option<inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>>>,
9697
result: QueryResult<'tcx>,
9798
shallow_certainty: Certainty,
9899
}
@@ -135,7 +136,20 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
135136

136137
/// Instantiate the nested goals for the candidate without rolling back their
137138
/// inference constraints. This function modifies the state of the `infcx`.
139+
///
140+
/// See [`Self::instantiate_nested_goals_and_opt_impl_args`] if you need the impl args too.
138141
pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
142+
self.instantiate_nested_goals_and_opt_impl_args(span).0
143+
}
144+
145+
/// Instantiate the nested goals for the candidate without rolling back their
146+
/// inference constraints, and optionally the args of an impl if this candidate
147+
/// came from a `CandidateSource::Impl`. This function modifies the state of the
148+
/// `infcx`.
149+
pub fn instantiate_nested_goals_and_opt_impl_args(
150+
&self,
151+
span: Span,
152+
) -> (Vec<InspectGoal<'a, 'tcx>>, Option<ty::GenericArgsRef<'tcx>>) {
139153
let infcx = self.goal.infcx;
140154
let param_env = self.goal.goal.param_env;
141155
let mut orig_values = self.goal.orig_values.to_vec();
@@ -164,14 +178,25 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
164178
self.final_state,
165179
);
166180

181+
let impl_args = self.impl_args.map(|impl_args| {
182+
canonical::instantiate_canonical_state(
183+
infcx,
184+
span,
185+
param_env,
186+
&mut orig_values,
187+
impl_args,
188+
)
189+
.fold_with(&mut EagerResolver::new(infcx))
190+
});
191+
167192
if let Some(term_hack) = self.goal.normalizes_to_term_hack {
168193
// FIXME: We ignore the expected term of `NormalizesTo` goals
169194
// when computing the result of its candidates. This is
170195
// scuffed.
171196
let _ = term_hack.constrain(infcx, span, param_env);
172197
}
173198

174-
instantiated_goals
199+
let goals = instantiated_goals
175200
.into_iter()
176201
.map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
177202
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
@@ -208,7 +233,9 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
208233
source,
209234
),
210235
})
211-
.collect()
236+
.collect();
237+
238+
(goals, impl_args)
212239
}
213240

214241
/// Visit all nested goals of this candidate, rolling back
@@ -245,9 +272,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
245272
probe: &inspect::Probe<'tcx>,
246273
) {
247274
let mut shallow_certainty = None;
275+
let mut impl_args = None;
248276
for step in &probe.steps {
249-
match step {
250-
&inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
277+
match *step {
278+
inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
251279
inspect::ProbeStep::NestedProbe(ref probe) => {
252280
// Nested probes have to prove goals added in their parent
253281
// but do not leak them, so we truncate the added goals
@@ -257,7 +285,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
257285
nested_goals.truncate(num_goals);
258286
}
259287
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
260-
assert_eq!(shallow_certainty.replace(*c), None);
288+
assert_eq!(shallow_certainty.replace(c), None);
289+
}
290+
inspect::ProbeStep::RecordImplArgs { impl_args: i } => {
291+
assert_eq!(impl_args.replace(i), None);
261292
}
262293
inspect::ProbeStep::EvaluateGoals(_) => (),
263294
}
@@ -284,6 +315,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
284315
final_state: probe.final_state,
285316
result,
286317
shallow_certainty,
318+
impl_args,
287319
});
288320
}
289321
}

compiler/rustc_trait_selection/src/solve/inspect/build.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ enum WipProbeStep<'tcx> {
242242
EvaluateGoals(WipAddedGoalsEvaluation<'tcx>),
243243
NestedProbe(WipProbe<'tcx>),
244244
MakeCanonicalResponse { shallow_certainty: Certainty },
245+
RecordImplArgs { impl_args: inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> },
245246
}
246247

247248
impl<'tcx> WipProbeStep<'tcx> {
@@ -250,6 +251,9 @@ impl<'tcx> WipProbeStep<'tcx> {
250251
WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal),
251252
WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()),
252253
WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()),
254+
WipProbeStep::RecordImplArgs { impl_args } => {
255+
inspect::ProbeStep::RecordImplArgs { impl_args }
256+
}
253257
WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
254258
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
255259
}
@@ -534,6 +538,30 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
534538
}
535539
}
536540

541+
pub(crate) fn record_impl_args(
542+
&mut self,
543+
infcx: &InferCtxt<'tcx>,
544+
max_input_universe: ty::UniverseIndex,
545+
impl_args: ty::GenericArgsRef<'tcx>,
546+
) {
547+
match self.as_mut() {
548+
Some(DebugSolver::GoalEvaluationStep(state)) => {
549+
let impl_args = canonical::make_canonical_state(
550+
infcx,
551+
&state.var_values,
552+
max_input_universe,
553+
impl_args,
554+
);
555+
state
556+
.current_evaluation_scope()
557+
.steps
558+
.push(WipProbeStep::RecordImplArgs { impl_args });
559+
}
560+
None => {}
561+
_ => bug!(),
562+
}
563+
}
564+
537565
pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
538566
match self.as_mut() {
539567
Some(DebugSolver::GoalEvaluationStep(state)) => {
@@ -543,7 +571,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
543571
.push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
544572
}
545573
None => {}
546-
_ => {}
574+
_ => bug!(),
547575
}
548576
}
549577

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
7575

7676
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
7777
let impl_args = ecx.fresh_args_for_item(impl_def_id);
78+
ecx.record_impl_args(impl_args);
7879
let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args);
7980

8081
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ check-pass
2+
//@ compile-flags: -Znext-solver
3+
4+
pub(crate) fn y() -> impl FnMut() {
5+
|| {}
6+
}
7+
8+
pub(crate) fn x(a: (), b: ()) {
9+
let x = ();
10+
y()()
11+
}
12+
13+
fn main() {}

0 commit comments

Comments
 (0)