Skip to content

Commit 587ab93

Browse files
committed
Cleanup term search related changes
1 parent 7b49309 commit 587ab93

File tree

26 files changed

+590
-515
lines changed

26 files changed

+590
-515
lines changed

crates/hir-def/src/attr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ impl AttrsWithOwner {
382382
AttrDefId::GenericParamId(it) => match it {
383383
GenericParamId::ConstParamId(it) => {
384384
let src = it.parent().child_source(db);
385+
// FIXME: We should be never getting `None` here.
385386
match src.value.get(it.local_id()) {
386387
Some(val) => RawAttrs::from_attrs_owner(
387388
db.upcast(),
@@ -393,6 +394,7 @@ impl AttrsWithOwner {
393394
}
394395
GenericParamId::TypeParamId(it) => {
395396
let src = it.parent().child_source(db);
397+
// FIXME: We should be never getting `None` here.
396398
match src.value.get(it.local_id()) {
397399
Some(val) => RawAttrs::from_attrs_owner(
398400
db.upcast(),
@@ -404,6 +406,7 @@ impl AttrsWithOwner {
404406
}
405407
GenericParamId::LifetimeParamId(it) => {
406408
let src = it.parent.child_source(db);
409+
// FIXME: We should be never getting `None` here.
407410
match src.value.get(it.local_id) {
408411
Some(val) => RawAttrs::from_attrs_owner(
409412
db.upcast(),

crates/hir-ty/src/infer/unify.rs

Lines changed: 41 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
7474
}
7575
}
7676

77+
/// Check if types unify.
78+
///
79+
/// Note that we consider placeholder types to unify with everything.
80+
/// This means that there may be some unresolved goals that actually set bounds for the placeholder
81+
/// type for the types to unify. For example `Option<T>` and `Option<U>` unify although there is
82+
/// unresolved goal `T = U`.
7783
pub fn could_unify(
7884
db: &dyn HirDatabase,
7985
env: Arc<TraitEnvironment>,
@@ -82,30 +88,25 @@ pub fn could_unify(
8288
unify(db, env, tys).is_some()
8389
}
8490

91+
/// Check if types unify eagerly making sure there are no unresolved goals.
92+
///
93+
/// This means that placeholder types are not considered to unify if there are any bounds set on
94+
/// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U`
8595
pub fn could_unify_deeply(
8696
db: &dyn HirDatabase,
8797
env: Arc<TraitEnvironment>,
8898
tys: &Canonical<(Ty, Ty)>,
8999
) -> bool {
90100
let mut table = InferenceTable::new(db, env);
91-
let vars = Substitution::from_iter(
92-
Interner,
93-
tys.binders.iter(Interner).map(|it| match &it.kind {
94-
chalk_ir::VariableKind::Ty(_) => {
95-
GenericArgData::Ty(table.new_type_var()).intern(Interner)
96-
}
97-
chalk_ir::VariableKind::Lifetime => {
98-
GenericArgData::Ty(table.new_type_var()).intern(Interner)
99-
} // FIXME: maybe wrong?
100-
chalk_ir::VariableKind::Const(ty) => {
101-
GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner)
102-
}
103-
}),
104-
);
101+
let vars = make_substitutions(tys, &mut table);
105102
let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
106103
let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
107104
let ty1_with_vars = table.normalize_associated_types_in(ty1_with_vars);
108105
let ty2_with_vars = table.normalize_associated_types_in(ty2_with_vars);
106+
table.resolve_obligations_as_possible();
107+
table.propagate_diverging_flag();
108+
let ty1_with_vars = table.resolve_completely(ty1_with_vars);
109+
let ty2_with_vars = table.resolve_completely(ty2_with_vars);
109110
table.unify_deeply(&ty1_with_vars, &ty2_with_vars)
110111
}
111112

@@ -115,15 +116,7 @@ pub(crate) fn unify(
115116
tys: &Canonical<(Ty, Ty)>,
116117
) -> Option<Substitution> {
117118
let mut table = InferenceTable::new(db, env);
118-
let vars = Substitution::from_iter(
119-
Interner,
120-
tys.binders.iter(Interner).map(|it| match &it.kind {
121-
chalk_ir::VariableKind::Ty(_) => table.new_type_var().cast(Interner),
122-
// FIXME: maybe wrong?
123-
chalk_ir::VariableKind::Lifetime => table.new_type_var().cast(Interner),
124-
chalk_ir::VariableKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
125-
}),
126-
);
119+
let vars = make_substitutions(tys, &mut table);
127120
let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
128121
let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
129122
if !table.unify(&ty1_with_vars, &ty2_with_vars) {
@@ -152,6 +145,21 @@ pub(crate) fn unify(
152145
))
153146
}
154147

148+
fn make_substitutions(
149+
tys: &chalk_ir::Canonical<(chalk_ir::Ty<Interner>, chalk_ir::Ty<Interner>)>,
150+
table: &mut InferenceTable<'_>,
151+
) -> chalk_ir::Substitution<Interner> {
152+
Substitution::from_iter(
153+
Interner,
154+
tys.binders.iter(Interner).map(|it| match &it.kind {
155+
chalk_ir::VariableKind::Ty(_) => table.new_type_var().cast(Interner),
156+
// FIXME: maybe wrong?
157+
chalk_ir::VariableKind::Lifetime => table.new_type_var().cast(Interner),
158+
chalk_ir::VariableKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
159+
}),
160+
)
161+
}
162+
155163
bitflags::bitflags! {
156164
#[derive(Default, Clone, Copy)]
157165
pub(crate) struct TypeVariableFlags: u8 {
@@ -458,15 +466,15 @@ impl<'a> InferenceTable<'a> {
458466
true
459467
}
460468

461-
/// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
469+
/// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled
462470
pub(crate) fn unify_deeply<T: ?Sized + Zip<Interner>>(&mut self, ty1: &T, ty2: &T) -> bool {
463471
let result = match self.try_unify(ty1, ty2) {
464472
Ok(r) => r,
465473
Err(_) => return false,
466474
};
467475
result.goals.iter().all(|goal| {
468476
let canonicalized = self.canonicalize(goal.clone());
469-
self.try_fulfill_obligation(&canonicalized)
477+
self.try_resolve_obligation(&canonicalized).is_some()
470478
})
471479
}
472480

@@ -540,7 +548,8 @@ impl<'a> InferenceTable<'a> {
540548

541549
fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
542550
let canonicalized = self.canonicalize(goal);
543-
if !self.try_resolve_obligation(&canonicalized) {
551+
let solution = self.try_resolve_obligation(&canonicalized);
552+
if matches!(solution, Some(Solution::Ambig(_))) {
544553
self.pending_obligations.push(canonicalized);
545554
}
546555
}
@@ -666,70 +675,35 @@ impl<'a> InferenceTable<'a> {
666675
fn try_resolve_obligation(
667676
&mut self,
668677
canonicalized: &Canonicalized<InEnvironment<Goal>>,
669-
) -> bool {
678+
) -> Option<chalk_solve::Solution<Interner>> {
670679
let solution = self.db.trait_solve(
671680
self.trait_env.krate,
672681
self.trait_env.block,
673682
canonicalized.value.clone(),
674683
);
675684

676-
match solution {
685+
match &solution {
677686
Some(Solution::Unique(canonical_subst)) => {
678687
canonicalized.apply_solution(
679688
self,
680689
Canonical {
681-
binders: canonical_subst.binders,
690+
binders: canonical_subst.binders.clone(),
682691
// FIXME: handle constraints
683-
value: canonical_subst.value.subst,
692+
value: canonical_subst.value.subst.clone(),
684693
},
685694
);
686-
true
687695
}
688696
Some(Solution::Ambig(Guidance::Definite(substs))) => {
689-
canonicalized.apply_solution(self, substs);
690-
false
697+
canonicalized.apply_solution(self, substs.clone());
691698
}
692699
Some(_) => {
693700
// FIXME use this when trying to resolve everything at the end
694-
false
695701
}
696702
None => {
697703
// FIXME obligation cannot be fulfilled => diagnostic
698-
true
699-
}
700-
}
701-
}
702-
703-
fn try_fulfill_obligation(
704-
&mut self,
705-
canonicalized: &Canonicalized<InEnvironment<Goal>>,
706-
) -> bool {
707-
let solution = self.db.trait_solve(
708-
self.trait_env.krate,
709-
self.trait_env.block,
710-
canonicalized.value.clone(),
711-
);
712-
713-
// FIXME: Does just returning `solution.is_some()` work?
714-
match solution {
715-
Some(Solution::Unique(canonical_subst)) => {
716-
canonicalized.apply_solution(
717-
self,
718-
Canonical {
719-
binders: canonical_subst.binders,
720-
// FIXME: handle constraints
721-
value: canonical_subst.value.subst,
722-
},
723-
);
724-
true
725-
}
726-
Some(Solution::Ambig(Guidance::Definite(substs))) => {
727-
canonicalized.apply_solution(self, substs);
728-
true
729704
}
730-
Some(_) => true,
731-
None => false,
732705
}
706+
solution
733707
}
734708

735709
pub(crate) fn callable_sig(

crates/hir-ty/src/mir/borrowck.rs

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use stdx::never;
1212
use triomphe::Arc;
1313

1414
use crate::{
15-
db::HirDatabase, mir::Operand, utils::ClosureSubst, ClosureId, Interner, Ty, TyExt, TypeFlags,
15+
db::HirDatabase, mir::Operand, utils::ClosureSubst, ClosureId, Interner, Substitution, Ty,
16+
TyExt, TypeFlags,
1617
};
1718

1819
use super::{
@@ -102,6 +103,18 @@ pub fn borrowck_query(
102103
Ok(res.into())
103104
}
104105

106+
fn make_fetch_closure_field(
107+
db: &dyn HirDatabase,
108+
) -> impl FnOnce(ClosureId, &Substitution, usize) -> Ty + '_ {
109+
|c: ClosureId, subst: &Substitution, f: usize| {
110+
let (def, _) = db.lookup_intern_closure(c.into());
111+
let infer = db.infer(def);
112+
let (captures, _) = infer.closure_info(&c);
113+
let parent_subst = ClosureSubst(subst).parent_subst();
114+
captures.get(f).expect("broken closure field").ty.clone().substitute(Interner, parent_subst)
115+
}
116+
}
117+
105118
fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef> {
106119
let mut result = vec![];
107120
let mut for_operand = |op: &Operand, span: MirSpan| match op {
@@ -115,18 +128,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
115128
ty = proj.projected_ty(
116129
ty,
117130
db,
118-
|c, subst, f| {
119-
let (def, _) = db.lookup_intern_closure(c.into());
120-
let infer = db.infer(def);
121-
let (captures, _) = infer.closure_info(&c);
122-
let parent_subst = ClosureSubst(subst).parent_subst();
123-
captures
124-
.get(f)
125-
.expect("broken closure field")
126-
.ty
127-
.clone()
128-
.substitute(Interner, parent_subst)
129-
},
131+
make_fetch_closure_field(db),
130132
body.owner.module(db.upcast()).krate(),
131133
);
132134
}
@@ -213,18 +215,7 @@ fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec<PartiallyMoved>
213215
ty = proj.projected_ty(
214216
ty,
215217
db,
216-
|c, subst, f| {
217-
let (def, _) = db.lookup_intern_closure(c.into());
218-
let infer = db.infer(def);
219-
let (captures, _) = infer.closure_info(&c);
220-
let parent_subst = ClosureSubst(subst).parent_subst();
221-
captures
222-
.get(f)
223-
.expect("broken closure field")
224-
.ty
225-
.clone()
226-
.substitute(Interner, parent_subst)
227-
},
218+
make_fetch_closure_field(db),
228219
body.owner.module(db.upcast()).krate(),
229220
);
230221
}
@@ -306,23 +297,17 @@ fn borrow_regions(db: &dyn HirDatabase, body: &MirBody) -> Vec<BorrowRegion> {
306297
for (_, block) in body.basic_blocks.iter() {
307298
db.unwind_if_cancelled();
308299
for statement in &block.statements {
309-
match &statement.kind {
310-
StatementKind::Assign(_, r) => match r {
311-
Rvalue::Ref(kind, p) => {
312-
borrows
313-
.entry(p.local)
314-
.and_modify(|it: &mut BorrowRegion| {
315-
it.places.push(statement.span);
316-
})
317-
.or_insert_with(|| BorrowRegion {
318-
local: p.local,
319-
kind: *kind,
320-
places: vec![statement.span],
321-
});
322-
}
323-
_ => (),
324-
},
325-
_ => (),
300+
if let StatementKind::Assign(_, Rvalue::Ref(kind, p)) = &statement.kind {
301+
borrows
302+
.entry(p.local)
303+
.and_modify(|it: &mut BorrowRegion| {
304+
it.places.push(statement.span);
305+
})
306+
.or_insert_with(|| BorrowRegion {
307+
local: p.local,
308+
kind: *kind,
309+
places: vec![statement.span],
310+
});
326311
}
327312
}
328313
match &block.terminator {
@@ -376,18 +361,7 @@ fn place_case(db: &dyn HirDatabase, body: &MirBody, lvalue: &Place) -> Projectio
376361
ty = proj.projected_ty(
377362
ty,
378363
db,
379-
|c, subst, f| {
380-
let (def, _) = db.lookup_intern_closure(c.into());
381-
let infer = db.infer(def);
382-
let (captures, _) = infer.closure_info(&c);
383-
let parent_subst = ClosureSubst(subst).parent_subst();
384-
captures
385-
.get(f)
386-
.expect("broken closure field")
387-
.ty
388-
.clone()
389-
.substitute(Interner, parent_subst)
390-
},
364+
make_fetch_closure_field(db),
391365
body.owner.module(db.upcast()).krate(),
392366
);
393367
}

0 commit comments

Comments
 (0)