Skip to content

Commit d5c3c24

Browse files
committedFeb 13, 2025
Auto merge of #136824 - lcnr:yeet, r=<try>
solver cycles are coinductive once they have one coinductive step Implements the new cycle semantics in the new solver, dealing with the fallout from rust-lang/trait-system-refactor-initiative#10. I am currently also changing inductive cycles back to an error instead of ambiguity outside of coherence to deal with rust-lang/trait-system-refactor-initiative#114. This should allow nalgebra to compile without affecting anything on stable. Whether a cycle results in ambiguity or success should not matter for coherence, as it only checks for errors. The first commit has been extensively fuzzed via https://github.com/lcnr/search_graph_fuzz. TODO: - [ ] fix issues from https://hackmd.io/JsblAvk4R5y30niSNQVYeA - [ ] add ui tests - [ ] explain this approach and why we believe it to be correct r? `@compiler-errors` `@nikomatsakis`
2 parents cfe9ffc + 68f2802 commit d5c3c24

File tree

51 files changed

+911
-835
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+911
-835
lines changed
 

‎compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

+23-28
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use derive_where::derive_where;
66
use rustc_type_ir::fold::TypeFoldable;
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::lang_items::TraitSolverLangItem;
9-
use rustc_type_ir::solve::inspect;
109
use rustc_type_ir::visit::TypeVisitableExt as _;
1110
use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate};
1211
use tracing::{debug, instrument};
@@ -292,25 +291,6 @@ where
292291
let Ok(normalized_self_ty) =
293292
self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
294293
else {
295-
// FIXME: We register a fake candidate when normalization fails so that
296-
// we can point at the reason for *why*. I'm tempted to say that this
297-
// is the wrong way to do this, though.
298-
let result =
299-
self.probe(|&result| inspect::ProbeKind::RigidAlias { result }).enter(|this| {
300-
let normalized_ty = this.next_ty_infer();
301-
let alias_relate_goal = Goal::new(
302-
this.cx(),
303-
goal.param_env,
304-
ty::PredicateKind::AliasRelate(
305-
goal.predicate.self_ty().into(),
306-
normalized_ty.into(),
307-
ty::AliasRelationDirection::Equate,
308-
),
309-
);
310-
this.add_goal(GoalSource::AliasWellFormed, alias_relate_goal);
311-
this.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
312-
});
313-
assert_eq!(result, Err(NoSolution));
314294
return vec![];
315295
};
316296

@@ -789,11 +769,12 @@ where
789769
/// treat the alias as rigid.
790770
///
791771
/// See trait-system-refactor-initiative#124 for more details.
792-
#[instrument(level = "debug", skip(self), ret)]
772+
#[instrument(level = "debug", skip(self, inject_normalize_to_rigid_candidate), ret)]
793773
pub(super) fn merge_candidates(
794774
&mut self,
795775
proven_via: Option<TraitGoalProvenVia>,
796776
candidates: Vec<Candidate<I>>,
777+
inject_normalize_to_rigid_candidate: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
797778
) -> QueryResult<I> {
798779
let Some(proven_via) = proven_via else {
799780
// We don't care about overflow. If proving the trait goal overflowed, then
@@ -810,13 +791,27 @@ where
810791
// FIXME(const_trait_impl): should this behavior also be used by
811792
// constness checking. Doing so is *at least theoretically* breaking,
812793
// see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754
813-
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => candidates
814-
.iter()
815-
.filter(|c| {
816-
matches!(c.source, CandidateSource::AliasBound | CandidateSource::ParamEnv(_))
817-
})
818-
.map(|c| c.result)
819-
.collect(),
794+
TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => {
795+
let mut candidates_from_env: Vec<_> = candidates
796+
.iter()
797+
.filter(|c| {
798+
matches!(
799+
c.source,
800+
CandidateSource::AliasBound | CandidateSource::ParamEnv(_)
801+
)
802+
})
803+
.map(|c| c.result)
804+
.collect();
805+
806+
// If the trait goal has been proven by using the environment, we want to treat
807+
// aliases as rigid if there are no applicable projection bounds in the environment.
808+
if candidates_from_env.is_empty() {
809+
if let Ok(response) = inject_normalize_to_rigid_candidate(self) {
810+
candidates_from_env.push(response);
811+
}
812+
}
813+
candidates_from_env
814+
}
820815
TraitGoalProvenVia::Misc => candidates.iter().map(|c| c.result).collect(),
821816
};
822817

‎compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,27 @@ where
154154
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
155155

156156
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
157+
// Resolve inference variables here to improve the debug output :)
158+
let impl_trait_ref = ecx.resolve_vars_if_possible(impl_trait_ref);
159+
157160
let where_clause_bounds = cx
158161
.predicates_of(impl_def_id)
159162
.iter_instantiated(cx, impl_args)
160163
.map(|pred| goal.with(cx, pred));
161164
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
162165

166+
// When using an impl, we have to check that its super trait bounds are actually satisfied.
167+
// This is necessary as otherwise the impl `impl<T: Magic> Magic for T` would allow us to
168+
// incorrectly assume all super traits of `Magic`.
169+
for clause in elaborate::elaborate(
170+
cx,
171+
cx.explicit_super_predicates_of(impl_trait_ref.def_id)
172+
.iter_instantiated(cx, impl_trait_ref.args)
173+
.map(|(pred, _)| pred),
174+
) {
175+
ecx.add_goal(GoalSource::Misc, goal.with(cx, clause));
176+
}
177+
163178
// For this impl to be `const`, we need to check its `~const` bounds too.
164179
let const_conditions = cx
165180
.const_conditions(impl_def_id)
@@ -398,6 +413,6 @@ where
398413
goal.with(ecx.cx(), goal.predicate.trait_ref);
399414
ecx.compute_trait_goal(trait_goal)
400415
})?;
401-
self.merge_candidates(proven_via, candidates)
416+
self.merge_candidates(proven_via, candidates, |_ecx| Err(NoSolution))
402417
}
403418
}

0 commit comments

Comments
 (0)