Skip to content

Commit 078c52f

Browse files
compiler-errorslcnr
authored andcommitted
Incompletely prefer opaque type bounds when self type bottoms out in infer
1 parent b51a3a5 commit 078c52f

File tree

2 files changed

+91
-3
lines changed
  • compiler/rustc_next_trait_solver/src/solve

2 files changed

+91
-3
lines changed

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

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use rustc_type_ir::lang_items::SolverTraitLangItem;
1111
use rustc_type_ir::search_graph::CandidateHeadUsages;
1212
use rustc_type_ir::solve::SizedTraitKind;
1313
use rustc_type_ir::{
14-
self as ty, Interner, TypeFlags, TypeFoldable, TypeSuperVisitable, TypeVisitable,
15-
TypeVisitableExt as _, TypeVisitor, TypingMode, Upcast as _, elaborate,
14+
self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
15+
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
16+
elaborate,
1617
};
1718
use tracing::{debug, instrument};
1819

@@ -399,12 +400,17 @@ where
399400

400401
if normalized_self_ty.is_ty_var() {
401402
debug!("self type has been normalized to infer");
402-
candidates.extend(self.forced_ambiguity(MaybeCause::Ambiguity));
403+
self.try_assemble_bounds_via_registered_opaque(
404+
goal,
405+
normalized_self_ty,
406+
&mut candidates,
407+
);
403408
return (candidates, failed_candidate_info);
404409
}
405410

406411
let goal: Goal<I, G> = goal
407412
.with(self.cx(), goal.predicate.with_replaced_self_ty(self.cx(), normalized_self_ty));
413+
408414
// Vars that show up in the rest of the goal substs may have been constrained by
409415
// normalizing the self type as well, since type variables are not uniquified.
410416
let goal = self.resolve_vars_if_possible(goal);
@@ -943,6 +949,61 @@ where
943949
}
944950
}
945951

952+
/// If the self type is the hidden type of an opaque, try to assemble
953+
/// candidates for it by consider its item bounds. This is used to
954+
/// incompletely guide type inference when handling non-defining uses
955+
/// in the defining scope.
956+
fn try_assemble_bounds_via_registered_opaque<G: GoalKind<D>>(
957+
&mut self,
958+
goal: Goal<I, G>,
959+
self_ty: I::Ty,
960+
candidates: &mut Vec<Candidate<I>>,
961+
) {
962+
for alias_ty in self.find_sup_as_registered_opaque(self_ty) {
963+
for item_bound in self
964+
.cx()
965+
.item_self_bounds(alias_ty.def_id)
966+
.iter_instantiated(self.cx(), alias_ty.args)
967+
{
968+
// TODO: comment
969+
let assumption =
970+
item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty });
971+
candidates.extend(G::probe_and_match_goal_against_assumption(
972+
self,
973+
CandidateSource::AliasBound,
974+
goal,
975+
assumption,
976+
|ecx| {
977+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
978+
},
979+
));
980+
}
981+
982+
struct ReplaceOpaque<I: Interner> {
983+
cx: I,
984+
alias_ty: ty::AliasTy<I>,
985+
self_ty: I::Ty,
986+
}
987+
impl<I: Interner> TypeFolder<I> for ReplaceOpaque<I> {
988+
fn cx(&self) -> I {
989+
self.cx
990+
}
991+
fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
992+
if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() {
993+
if alias_ty == self.alias_ty {
994+
return self.self_ty;
995+
}
996+
}
997+
ty.super_fold_with(self)
998+
}
999+
}
1000+
}
1001+
1002+
if candidates.is_empty() {
1003+
candidates.extend(self.forced_ambiguity(MaybeCause::Ambiguity));
1004+
}
1005+
}
1006+
9461007
/// Assemble and merge candidates for goals which are related to an underlying trait
9471008
/// goal. Right now, this is normalizes-to and host effect goals.
9481009
///

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,33 @@ where
11631163
) -> bool {
11641164
may_use_unstable_feature(&**self.delegate, param_env, symbol)
11651165
}
1166+
1167+
pub(crate) fn find_sup_as_registered_opaque(
1168+
&self,
1169+
self_ty: I::Ty,
1170+
) -> impl Iterator<Item = ty::AliasTy<I>> + use<'a, D, I> {
1171+
let delegate = self.delegate;
1172+
delegate
1173+
.clone_opaque_types_lookup_table()
1174+
.into_iter()
1175+
.chain(delegate.clone_duplicate_opaque_types())
1176+
.filter_map(move |(key, hidden_ty)| {
1177+
if let ty::Infer(ty::TyVar(self_vid)) = self_ty.kind() {
1178+
if let ty::Infer(ty::TyVar(hidden_vid)) = hidden_ty.kind() {
1179+
if delegate.sub_unification_table_root_var(self_vid)
1180+
== delegate.sub_unification_table_root_var(hidden_vid)
1181+
{
1182+
return Some(ty::AliasTy::new_from_args(
1183+
delegate.cx(),
1184+
key.def_id.into(),
1185+
key.args,
1186+
));
1187+
}
1188+
}
1189+
}
1190+
None
1191+
})
1192+
}
11661193
}
11671194

11681195
/// Eagerly replace aliases with inference variables, emitting `AliasRelate`

0 commit comments

Comments
 (0)