Skip to content

Commit a5035f4

Browse files
committed
Auto merge of rust-lang#16749 - Veykril:on-demand-validation-err, r=Veykril
internal: Some method resolution cleanups
2 parents 1069f57 + c679482 commit a5035f4

File tree

10 files changed

+154
-150
lines changed

10 files changed

+154
-150
lines changed

Diff for: Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ anyhow = "1.0.75"
105105
arrayvec = "0.7.4"
106106
bitflags = "2.4.1"
107107
cargo_metadata = "0.18.1"
108+
chalk-solve = { version = "0.96.0", default-features = false }
109+
chalk-ir = "0.96.0"
110+
chalk-recursive = { version = "0.96.0", default-features = false }
111+
chalk-derive = "0.96.0"
108112
command-group = "2.0.1"
109113
crossbeam-channel = "0.5.8"
110114
dissimilar = "1.0.7"

Diff for: crates/hir-ty/Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ oorandom = "11.1.3"
2323
tracing.workspace = true
2424
rustc-hash.workspace = true
2525
scoped-tls = "1.0.0"
26-
chalk-solve = { version = "0.96.0", default-features = false }
27-
chalk-ir = "0.96.0"
28-
chalk-recursive = { version = "0.96.0", default-features = false }
29-
chalk-derive = "0.96.0"
26+
chalk-solve.workspace = true
27+
chalk-ir.workspace = true
28+
chalk-recursive.workspace = true
29+
chalk-derive.workspace = true
3030
la-arena.workspace = true
3131
once_cell = "1.17.0"
3232
triomphe.workspace = true

Diff for: crates/hir-ty/src/autoderef.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,23 @@ pub(crate) fn autoderef_step(
113113
ty: Ty,
114114
explicit: bool,
115115
) -> Option<(AutoderefKind, Ty)> {
116-
if let Some(derefed) = builtin_deref(table, &ty, explicit) {
116+
if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
117117
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
118118
} else {
119119
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
120120
}
121121
}
122122

123123
pub(crate) fn builtin_deref<'ty>(
124-
table: &mut InferenceTable<'_>,
124+
db: &dyn HirDatabase,
125125
ty: &'ty Ty,
126126
explicit: bool,
127127
) -> Option<&'ty Ty> {
128128
match ty.kind(Interner) {
129129
TyKind::Ref(.., ty) => Some(ty),
130130
TyKind::Raw(.., ty) if explicit => Some(ty),
131131
&TyKind::Adt(chalk_ir::AdtId(adt), ref substs) => {
132-
if crate::lang_items::is_box(table.db, adt) {
132+
if crate::lang_items::is_box(db, adt) {
133133
substs.at(Interner, 0).ty(Interner)
134134
} else {
135135
None

Diff for: crates/hir-ty/src/infer/coerce.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ impl InferenceTable<'_> {
647647
let goal: InEnvironment<DomainGoal> =
648648
InEnvironment::new(&self.trait_env.env, coerce_unsized_tref.cast(Interner));
649649

650-
let canonicalized = self.canonicalize(goal);
650+
let canonicalized = self.canonicalize_with_free_vars(goal);
651651

652652
// FIXME: rustc's coerce_unsized is more specialized -- it only tries to
653653
// solve `CoerceUnsized` and `Unsize` goals at this point and leaves the

Diff for: crates/hir-ty/src/infer/expr.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -312,15 +312,13 @@ impl InferenceContext<'_> {
312312
Expr::Call { callee, args, .. } => {
313313
let callee_ty = self.infer_expr(*callee, &Expectation::none());
314314
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
315-
let (res, derefed_callee) = 'b: {
316-
// manual loop to be able to access `derefs.table`
317-
while let Some((callee_deref_ty, _)) = derefs.next() {
318-
let res = derefs.table.callable_sig(&callee_deref_ty, args.len());
319-
if res.is_some() {
320-
break 'b (res, callee_deref_ty);
321-
}
315+
let (res, derefed_callee) = loop {
316+
let Some((callee_deref_ty, _)) = derefs.next() else {
317+
break (None, callee_ty.clone());
318+
};
319+
if let Some(res) = derefs.table.callable_sig(&callee_deref_ty, args.len()) {
320+
break (Some(res), callee_deref_ty);
322321
}
323-
(None, callee_ty.clone())
324322
};
325323
// if the function is unresolved, we use is_varargs=true to
326324
// suppress the arg count diagnostic here
@@ -657,7 +655,7 @@ impl InferenceContext<'_> {
657655
);
658656
}
659657
}
660-
if let Some(derefed) = builtin_deref(&mut self.table, &inner_ty, true) {
658+
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
661659
self.resolve_ty_shallow(derefed)
662660
} else {
663661
deref_by_trait(&mut self.table, inner_ty)
@@ -774,7 +772,7 @@ impl InferenceContext<'_> {
774772
let receiver_adjustments = method_resolution::resolve_indexing_op(
775773
self.db,
776774
self.table.trait_env.clone(),
777-
canonicalized.value,
775+
canonicalized,
778776
index_trait,
779777
);
780778
let (self_ty, mut adj) = receiver_adjustments
@@ -1559,7 +1557,7 @@ impl InferenceContext<'_> {
15591557
let canonicalized_receiver = self.canonicalize(receiver_ty.clone());
15601558
let resolved = method_resolution::lookup_method(
15611559
self.db,
1562-
&canonicalized_receiver.value,
1560+
&canonicalized_receiver,
15631561
self.table.trait_env.clone(),
15641562
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),
15651563
VisibleFromModule::Filter(self.resolver.module()),
@@ -1608,7 +1606,7 @@ impl InferenceContext<'_> {
16081606

16091607
let resolved = method_resolution::lookup_method(
16101608
self.db,
1611-
&canonicalized_receiver.value,
1609+
&canonicalized_receiver,
16121610
self.table.trait_env.clone(),
16131611
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),
16141612
VisibleFromModule::Filter(self.resolver.module()),
@@ -1641,7 +1639,7 @@ impl InferenceContext<'_> {
16411639
};
16421640

16431641
let assoc_func_with_same_name = method_resolution::iterate_method_candidates(
1644-
&canonicalized_receiver.value,
1642+
&canonicalized_receiver,
16451643
self.db,
16461644
self.table.trait_env.clone(),
16471645
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),

Diff for: crates/hir-ty/src/infer/path.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ impl InferenceContext<'_> {
321321

322322
let mut not_visible = None;
323323
let res = method_resolution::iterate_method_candidates(
324-
&canonical_ty.value,
324+
&canonical_ty,
325325
self.db,
326326
self.table.trait_env.clone(),
327327
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),

Diff for: crates/hir-ty/src/infer/unify.rs

+36-39
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,9 @@ use crate::{
2323
};
2424

2525
impl InferenceContext<'_> {
26-
pub(super) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
27-
&mut self,
28-
t: T,
29-
) -> Canonicalized<T>
26+
pub(super) fn canonicalize<T>(&mut self, t: T) -> Canonical<T>
3027
where
31-
T: HasInterner<Interner = Interner>,
28+
T: TypeFoldable<Interner> + HasInterner<Interner = Interner>,
3229
{
3330
self.table.canonicalize(t)
3431
}
@@ -128,14 +125,14 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
128125
}),
129126
);
130127
for (i, v) in solution.value.iter(Interner).enumerate() {
131-
let var = self.free_vars[i].clone();
128+
let var = &self.free_vars[i];
132129
if let Some(ty) = v.ty(Interner) {
133130
// eagerly replace projections in the type; we may be getting types
134131
// e.g. from where clauses where this hasn't happened yet
135132
let ty = ctx.normalize_associated_types_in(new_vars.apply(ty.clone(), Interner));
136133
ctx.unify(var.assert_ty_ref(Interner), &ty);
137134
} else {
138-
let _ = ctx.try_unify(&var, &new_vars.apply(v.clone(), Interner));
135+
let _ = ctx.try_unify(var, &new_vars.apply(v.clone(), Interner));
139136
}
140137
}
141138
}
@@ -243,7 +240,7 @@ pub(crate) struct InferenceTable<'a> {
243240
pub(crate) db: &'a dyn HirDatabase,
244241
pub(crate) trait_env: Arc<TraitEnvironment>,
245242
var_unification_table: ChalkInferenceTable,
246-
type_variable_table: Vec<TypeVariableFlags>,
243+
type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
247244
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
248245
/// Double buffer used in [`Self::resolve_obligations_as_possible`] to cut down on
249246
/// temporary allocations.
@@ -252,8 +249,8 @@ pub(crate) struct InferenceTable<'a> {
252249

253250
pub(crate) struct InferenceTableSnapshot {
254251
var_table_snapshot: chalk_solve::infer::InferenceSnapshot<Interner>,
252+
type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
255253
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
256-
type_variable_table_snapshot: Vec<TypeVariableFlags>,
257254
}
258255

259256
impl<'a> InferenceTable<'a> {
@@ -262,7 +259,7 @@ impl<'a> InferenceTable<'a> {
262259
db,
263260
trait_env,
264261
var_unification_table: ChalkInferenceTable::new(),
265-
type_variable_table: Vec::new(),
262+
type_variable_table: SmallVec::new(),
266263
pending_obligations: Vec::new(),
267264
resolve_obligations_buffer: Vec::new(),
268265
}
@@ -292,27 +289,24 @@ impl<'a> InferenceTable<'a> {
292289
}
293290

294291
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
292+
let is_diverging = self
293+
.type_variable_table
294+
.get(iv.index() as usize)
295+
.map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING));
296+
if is_diverging {
297+
return TyKind::Never.intern(Interner);
298+
}
295299
match kind {
296-
_ if self
297-
.type_variable_table
298-
.get(iv.index() as usize)
299-
.map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING)) =>
300-
{
301-
TyKind::Never
302-
}
303300
TyVariableKind::General => TyKind::Error,
304301
TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
305302
TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
306303
}
307304
.intern(Interner)
308305
}
309306

310-
pub(crate) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
311-
&mut self,
312-
t: T,
313-
) -> Canonicalized<T>
307+
pub(crate) fn canonicalize_with_free_vars<T>(&mut self, t: T) -> Canonicalized<T>
314308
where
315-
T: HasInterner<Interner = Interner>,
309+
T: TypeFoldable<Interner> + HasInterner<Interner = Interner>,
316310
{
317311
// try to resolve obligations before canonicalizing, since this might
318312
// result in new knowledge about variables
@@ -326,6 +320,16 @@ impl<'a> InferenceTable<'a> {
326320
Canonicalized { value: result.quantified, free_vars }
327321
}
328322

323+
pub(crate) fn canonicalize<T>(&mut self, t: T) -> Canonical<T>
324+
where
325+
T: TypeFoldable<Interner> + HasInterner<Interner = Interner>,
326+
{
327+
// try to resolve obligations before canonicalizing, since this might
328+
// result in new knowledge about variables
329+
self.resolve_obligations_as_possible();
330+
self.var_unification_table.canonicalize(Interner, t).quantified
331+
}
332+
329333
/// Recurses through the given type, normalizing associated types mentioned
330334
/// in it by replacing them by type variables and registering obligations to
331335
/// resolve later. This should be done once for every type we get from some
@@ -434,6 +438,7 @@ impl<'a> InferenceTable<'a> {
434438
where
435439
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
436440
{
441+
// TODO check this vec here
437442
self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback)
438443
}
439444

@@ -541,7 +546,7 @@ impl<'a> InferenceTable<'a> {
541546
Err(_) => return false,
542547
};
543548
result.goals.iter().all(|goal| {
544-
let canonicalized = self.canonicalize(goal.clone());
549+
let canonicalized = self.canonicalize_with_free_vars(goal.clone());
545550
self.try_resolve_obligation(&canonicalized).is_some()
546551
})
547552
}
@@ -575,19 +580,15 @@ impl<'a> InferenceTable<'a> {
575580

576581
pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot {
577582
let var_table_snapshot = self.var_unification_table.snapshot();
578-
let type_variable_table_snapshot = self.type_variable_table.clone();
583+
let type_variable_table = self.type_variable_table.clone();
579584
let pending_obligations = self.pending_obligations.clone();
580-
InferenceTableSnapshot {
581-
var_table_snapshot,
582-
pending_obligations,
583-
type_variable_table_snapshot,
584-
}
585+
InferenceTableSnapshot { var_table_snapshot, pending_obligations, type_variable_table }
585586
}
586587

587588
#[tracing::instrument(skip_all)]
588589
pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot) {
589590
self.var_unification_table.rollback_to(snapshot.var_table_snapshot);
590-
self.type_variable_table = snapshot.type_variable_table_snapshot;
591+
self.type_variable_table = snapshot.type_variable_table;
591592
self.pending_obligations = snapshot.pending_obligations;
592593
}
593594

@@ -606,7 +607,7 @@ impl<'a> InferenceTable<'a> {
606607
let in_env = InEnvironment::new(&self.trait_env.env, goal);
607608
let canonicalized = self.canonicalize(in_env);
608609

609-
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value)
610+
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized)
610611
}
611612

612613
pub(crate) fn register_obligation(&mut self, goal: Goal) {
@@ -615,7 +616,7 @@ impl<'a> InferenceTable<'a> {
615616
}
616617

617618
fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
618-
let canonicalized = self.canonicalize(goal);
619+
let canonicalized = self.canonicalize_with_free_vars(goal);
619620
let solution = self.try_resolve_obligation(&canonicalized);
620621
if matches!(solution, Some(Solution::Ambig(_))) {
621622
self.pending_obligations.push(canonicalized);
@@ -798,7 +799,7 @@ impl<'a> InferenceTable<'a> {
798799
let trait_data = self.db.trait_data(fn_once_trait);
799800
let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
800801

801-
let mut arg_tys = vec![];
802+
let mut arg_tys = Vec::with_capacity(num_args);
802803
let arg_ty = TyBuilder::tuple(num_args)
803804
.fill(|it| {
804805
let arg = match it {
@@ -828,11 +829,7 @@ impl<'a> InferenceTable<'a> {
828829
environment: trait_env.clone(),
829830
};
830831
let canonical = self.canonicalize(obligation.clone());
831-
if self
832-
.db
833-
.trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
834-
.is_some()
835-
{
832+
if self.db.trait_solve(krate, self.trait_env.block, canonical.cast(Interner)).is_some() {
836833
self.register_obligation(obligation.goal);
837834
let return_ty = self.normalize_projection_ty(projection);
838835
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
@@ -845,7 +842,7 @@ impl<'a> InferenceTable<'a> {
845842
let canonical = self.canonicalize(obligation.clone());
846843
if self
847844
.db
848-
.trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
845+
.trait_solve(krate, self.trait_env.block, canonical.cast(Interner))
849846
.is_some()
850847
{
851848
return Some((fn_x, arg_tys, return_ty));

0 commit comments

Comments
 (0)