Skip to content

Commit d667549

Browse files
Normalize if knowable
1 parent 999877c commit d667549

File tree

2 files changed

+86
-14
lines changed

2 files changed

+86
-14
lines changed

Diff for: compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+42-14
Original file line numberDiff line numberDiff line change
@@ -889,20 +889,48 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
889889
SolverMode::Normal => return,
890890
SolverMode::Coherence => {
891891
let trait_ref = goal.predicate.trait_ref(self.tcx());
892-
match coherence::trait_ref_is_knowable(self.tcx(), trait_ref) {
893-
Ok(()) => {}
894-
Err(_) => match self
895-
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
896-
{
897-
Ok(result) => candidates.push(Candidate {
898-
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity),
899-
result,
900-
}),
901-
// FIXME: This will be reachable at some point if we're in
902-
// `assemble_candidates_after_normalizing_self_ty` and we get a
903-
// universe error. We'll deal with it at this point.
904-
Err(NoSolution) => bug!("coherence candidate resulted in NoSolution"),
905-
},
892+
// will assemble in `assemble_candidates_after_normalizing_self_ty`
893+
if matches!(trait_ref.self_ty().kind(), ty::Alias(..)) {
894+
return;
895+
}
896+
let result = self.probe_candidate("unknowable candidate").enter(|ecx| {
897+
let mut args = trait_ref.args.to_vec();
898+
for arg in args.iter_mut().skip(1) {
899+
let Some(ty) = arg.as_type() else {
900+
continue;
901+
};
902+
let Some(normalized_ty) = ecx.normalize_non_self_ty(ty, goal.param_env)?
903+
else {
904+
return Ok(ecx
905+
.evaluate_added_goals_and_make_canonical_response(
906+
Certainty::AMBIGUOUS,
907+
)
908+
.unwrap());
909+
};
910+
*arg = normalized_ty.into();
911+
}
912+
match coherence::trait_ref_is_knowable(ecx.tcx(), trait_ref) {
913+
Ok(()) => Err(NoSolution),
914+
Err(_) => {
915+
match ecx.evaluate_added_goals_and_make_canonical_response(
916+
Certainty::AMBIGUOUS,
917+
) {
918+
Ok(result) => Ok(result),
919+
// FIXME: This will be reachable at some point if we're in
920+
// `assemble_candidates_after_normalizing_self_ty` and we get a
921+
// universe error. We'll deal with it at this point.
922+
Err(NoSolution) => {
923+
bug!("coherence candidate resulted in NoSolution")
924+
}
925+
}
926+
}
927+
}
928+
});
929+
if let Ok(result) = result {
930+
candidates.push(Candidate {
931+
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity),
932+
result,
933+
});
906934
}
907935
}
908936
}

Diff for: compiler/rustc_trait_selection/src/solve/trait_goals.rs

+44
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
22
33
use super::assembly::{self, structural_traits};
4+
use super::search_graph::OverflowHandler;
45
use super::{EvalCtxt, SolverMode};
56
use rustc_hir::def_id::DefId;
67
use rustc_hir::{LangItem, Movability};
@@ -750,4 +751,47 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
750751
let candidates = self.assemble_and_evaluate_candidates(goal);
751752
self.merge_candidates(candidates)
752753
}
754+
755+
/// Normalize a non-self type when it is structually matched on when solving
756+
/// a built-in goal. This is handled already through `assemble_candidates_after_normalizing_self_ty`
757+
/// for the self type, but for other goals, additional normalization of other
758+
/// arguments may be needed to completely implement the semantics of the trait.
759+
///
760+
/// This is required when structurally matching on any trait argument that is
761+
/// not the self type.
762+
pub(super) fn normalize_non_self_ty(
763+
&mut self,
764+
mut ty: Ty<'tcx>,
765+
param_env: ty::ParamEnv<'tcx>,
766+
) -> Result<Option<Ty<'tcx>>, NoSolution> {
767+
if !matches!(ty.kind(), ty::Alias(..)) {
768+
return Ok(Some(ty));
769+
}
770+
771+
self.repeat_while_none(
772+
|_| Ok(None),
773+
|ecx| {
774+
let ty::Alias(_, projection_ty) = *ty.kind() else {
775+
return Some(Ok(Some(ty)));
776+
};
777+
778+
let normalized_ty = ecx.next_ty_infer();
779+
let normalizes_to_goal = Goal::new(
780+
ecx.tcx(),
781+
param_env,
782+
ty::Binder::dummy(ty::ProjectionPredicate {
783+
projection_ty,
784+
term: normalized_ty.into(),
785+
}),
786+
);
787+
ecx.add_goal(normalizes_to_goal);
788+
if let Err(err) = ecx.try_evaluate_added_goals() {
789+
return Some(Err(err));
790+
}
791+
792+
ty = ecx.resolve_vars_if_possible(normalized_ty);
793+
None
794+
},
795+
)
796+
}
753797
}

0 commit comments

Comments
 (0)