Skip to content

Commit d21f888

Browse files
committed
Remove some unnecessary cloning in method_resolution
1 parent 593156a commit d21f888

File tree

8 files changed

+76
-78
lines changed

8 files changed

+76
-78
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
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"

crates/hir-ty/Cargo.toml

Lines changed: 4 additions & 4 deletions
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

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

Lines changed: 1 addition & 1 deletion
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

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ impl InferenceContext<'_> {
774774
let receiver_adjustments = method_resolution::resolve_indexing_op(
775775
self.db,
776776
self.table.trait_env.clone(),
777-
canonicalized.value,
777+
canonicalized,
778778
index_trait,
779779
);
780780
let (self_ty, mut adj) = receiver_adjustments
@@ -1559,7 +1559,7 @@ impl InferenceContext<'_> {
15591559
let canonicalized_receiver = self.canonicalize(receiver_ty.clone());
15601560
let resolved = method_resolution::lookup_method(
15611561
self.db,
1562-
&canonicalized_receiver.value,
1562+
&canonicalized_receiver,
15631563
self.table.trait_env.clone(),
15641564
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),
15651565
VisibleFromModule::Filter(self.resolver.module()),
@@ -1608,7 +1608,7 @@ impl InferenceContext<'_> {
16081608

16091609
let resolved = method_resolution::lookup_method(
16101610
self.db,
1611-
&canonicalized_receiver.value,
1611+
&canonicalized_receiver,
16121612
self.table.trait_env.clone(),
16131613
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),
16141614
VisibleFromModule::Filter(self.resolver.module()),
@@ -1641,7 +1641,7 @@ impl InferenceContext<'_> {
16411641
};
16421642

16431643
let assoc_func_with_same_name = method_resolution::iterate_method_candidates(
1644-
&canonicalized_receiver.value,
1644+
&canonicalized_receiver,
16451645
self.db,
16461646
self.table.trait_env.clone(),
16471647
self.get_traits_in_scope().as_ref().left_or_else(|&it| it),

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

Lines changed: 1 addition & 1 deletion
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),

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

Lines changed: 21 additions & 21 deletions
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
}
@@ -307,12 +304,9 @@ impl<'a> InferenceTable<'a> {
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
@@ -541,7 +545,7 @@ impl<'a> InferenceTable<'a> {
541545
Err(_) => return false,
542546
};
543547
result.goals.iter().all(|goal| {
544-
let canonicalized = self.canonicalize(goal.clone());
548+
let canonicalized = self.canonicalize_with_free_vars(goal.clone());
545549
self.try_resolve_obligation(&canonicalized).is_some()
546550
})
547551
}
@@ -602,7 +606,7 @@ impl<'a> InferenceTable<'a> {
602606
let in_env = InEnvironment::new(&self.trait_env.env, goal);
603607
let canonicalized = self.canonicalize(in_env);
604608

605-
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value)
609+
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized)
606610
}
607611

608612
pub(crate) fn register_obligation(&mut self, goal: Goal) {
@@ -611,7 +615,7 @@ impl<'a> InferenceTable<'a> {
611615
}
612616

613617
fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
614-
let canonicalized = self.canonicalize(goal);
618+
let canonicalized = self.canonicalize_with_free_vars(goal);
615619
let solution = self.try_resolve_obligation(&canonicalized);
616620
if matches!(solution, Some(Solution::Ambig(_))) {
617621
self.pending_obligations.push(canonicalized);
@@ -824,11 +828,7 @@ impl<'a> InferenceTable<'a> {
824828
environment: trait_env.clone(),
825829
};
826830
let canonical = self.canonicalize(obligation.clone());
827-
if self
828-
.db
829-
.trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
830-
.is_some()
831-
{
831+
if self.db.trait_solve(krate, self.trait_env.block, canonical.cast(Interner)).is_some() {
832832
self.register_obligation(obligation.goal);
833833
let return_ty = self.normalize_projection_ty(projection);
834834
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
@@ -841,7 +841,7 @@ impl<'a> InferenceTable<'a> {
841841
let canonical = self.canonicalize(obligation.clone());
842842
if self
843843
.db
844-
.trait_solve(krate, self.trait_env.block, canonical.value.cast(Interner))
844+
.trait_solve(krate, self.trait_env.block, canonical.cast(Interner))
845845
.is_some()
846846
{
847847
return Some((fn_x, arg_tys, return_ty));

crates/hir-ty/src/method_resolution.rs

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ pub fn iterate_method_candidates_dyn(
973973
deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
974974
iterate_method_candidates_with_autoref(
975975
&mut table,
976-
&receiver_ty,
976+
receiver_ty,
977977
adj,
978978
traits_in_scope,
979979
visible_from_module,
@@ -1000,7 +1000,7 @@ pub fn iterate_method_candidates_dyn(
10001000
#[tracing::instrument(skip_all, fields(name = ?name))]
10011001
fn iterate_method_candidates_with_autoref(
10021002
table: &mut InferenceTable<'_>,
1003-
receiver_ty: &Canonical<Ty>,
1003+
receiver_ty: Canonical<Ty>,
10041004
first_adjustment: ReceiverAdjustments,
10051005
traits_in_scope: &FxHashSet<TraitId>,
10061006
visible_from_module: VisibleFromModule,
@@ -1031,32 +1031,29 @@ fn iterate_method_candidates_with_autoref(
10311031
maybe_reborrowed.autoderefs += 1;
10321032
}
10331033

1034-
iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?;
1034+
iterate_method_candidates_by_receiver(receiver_ty.clone(), maybe_reborrowed)?;
10351035

10361036
let refed = Canonical {
10371037
value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())
10381038
.intern(Interner),
10391039
binders: receiver_ty.binders.clone(),
10401040
};
10411041

1042-
iterate_method_candidates_by_receiver(&refed, first_adjustment.with_autoref(Mutability::Not))?;
1042+
iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?;
10431043

10441044
let ref_muted = Canonical {
10451045
value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone())
10461046
.intern(Interner),
10471047
binders: receiver_ty.binders.clone(),
10481048
};
10491049

1050-
iterate_method_candidates_by_receiver(
1051-
&ref_muted,
1052-
first_adjustment.with_autoref(Mutability::Mut),
1053-
)
1050+
iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
10541051
}
10551052

10561053
#[tracing::instrument(skip_all, fields(name = ?name))]
10571054
fn iterate_method_candidates_by_receiver(
10581055
table: &mut InferenceTable<'_>,
1059-
receiver_ty: &Canonical<Ty>,
1056+
receiver_ty: Canonical<Ty>,
10601057
receiver_adjustments: ReceiverAdjustments,
10611058
traits_in_scope: &FxHashSet<TraitId>,
10621059
visible_from_module: VisibleFromModule,
@@ -1143,9 +1140,9 @@ fn iterate_trait_method_candidates(
11431140
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
11441141
) -> ControlFlow<()> {
11451142
let db = table.db;
1146-
let env = table.trait_env.clone();
11471143

1148-
let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
1144+
let canonical_self_ty = table.canonicalize(self_ty.clone());
1145+
let TraitEnvironment { krate, block, .. } = *table.trait_env;
11491146

11501147
'traits: for &t in traits_in_scope {
11511148
let data = db.trait_data(t);
@@ -1160,7 +1157,7 @@ fn iterate_trait_method_candidates(
11601157
{
11611158
// FIXME: this should really be using the edition of the method name's span, in case it
11621159
// comes from a macro
1163-
if db.crate_graph()[env.krate].edition < Edition::Edition2021 {
1160+
if db.crate_graph()[krate].edition < Edition::Edition2021 {
11641161
continue;
11651162
}
11661163
}
@@ -1179,8 +1176,8 @@ fn iterate_trait_method_candidates(
11791176
IsValidCandidate::No => continue,
11801177
};
11811178
if !known_implemented {
1182-
let goal = generic_implements_goal(db, env.clone(), t, &canonical_self_ty);
1183-
if db.trait_solve(env.krate, env.block, goal.cast(Interner)).is_none() {
1179+
let goal = generic_implements_goal(db, &table.trait_env, t, &canonical_self_ty);
1180+
if db.trait_solve(krate, block, goal.cast(Interner)).is_none() {
11841181
continue 'traits;
11851182
}
11861183
}
@@ -1361,7 +1358,7 @@ pub(crate) fn resolve_indexing_op(
13611358
let ty = table.instantiate_canonical(ty);
13621359
let deref_chain = autoderef_method_receiver(&mut table, ty);
13631360
for (ty, adj) in deref_chain {
1364-
let goal = generic_implements_goal(db, table.trait_env.clone(), index_trait, &ty);
1361+
let goal = generic_implements_goal(db, &table.trait_env, index_trait, &ty);
13651362
if db
13661363
.trait_solve(table.trait_env.krate, table.trait_env.block, goal.cast(Interner))
13671364
.is_some()
@@ -1544,7 +1541,7 @@ fn is_valid_impl_fn_candidate(
15441541

15451542
for goal in goals.clone() {
15461543
let in_env = InEnvironment::new(&table.trait_env.env, goal);
1547-
let canonicalized = table.canonicalize(in_env);
1544+
let canonicalized = table.canonicalize_with_free_vars(in_env);
15481545
let solution = table.db.trait_solve(
15491546
table.trait_env.krate,
15501547
table.trait_env.block,
@@ -1582,10 +1579,10 @@ fn is_valid_impl_fn_candidate(
15821579
pub fn implements_trait(
15831580
ty: &Canonical<Ty>,
15841581
db: &dyn HirDatabase,
1585-
env: Arc<TraitEnvironment>,
1582+
env: &TraitEnvironment,
15861583
trait_: TraitId,
15871584
) -> bool {
1588-
let goal = generic_implements_goal(db, env.clone(), trait_, ty);
1585+
let goal = generic_implements_goal(db, env, trait_, ty);
15891586
let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
15901587

15911588
solution.is_some()
@@ -1594,10 +1591,10 @@ pub fn implements_trait(
15941591
pub fn implements_trait_unique(
15951592
ty: &Canonical<Ty>,
15961593
db: &dyn HirDatabase,
1597-
env: Arc<TraitEnvironment>,
1594+
env: &TraitEnvironment,
15981595
trait_: TraitId,
15991596
) -> bool {
1600-
let goal = generic_implements_goal(db, env.clone(), trait_, ty);
1597+
let goal = generic_implements_goal(db, env, trait_, ty);
16011598
let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
16021599

16031600
matches!(solution, Some(crate::Solution::Unique(_)))
@@ -1608,32 +1605,34 @@ pub fn implements_trait_unique(
16081605
#[tracing::instrument(skip_all)]
16091606
fn generic_implements_goal(
16101607
db: &dyn HirDatabase,
1611-
env: Arc<TraitEnvironment>,
1608+
env: &TraitEnvironment,
16121609
trait_: TraitId,
16131610
self_ty: &Canonical<Ty>,
16141611
) -> Canonical<InEnvironment<super::DomainGoal>> {
1615-
let mut kinds = self_ty.binders.interned().to_vec();
1612+
let binders = self_ty.binders.interned();
16161613
let trait_ref = TyBuilder::trait_ref(db, trait_)
16171614
.push(self_ty.value.clone())
1618-
.fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
1615+
.fill_with_bound_vars(DebruijnIndex::INNERMOST, binders.len())
16191616
.build();
1620-
kinds.extend(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
1621-
let vk = match it.data(Interner) {
1622-
chalk_ir::GenericArgData::Ty(_) => {
1623-
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
1624-
}
1625-
chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
1626-
chalk_ir::GenericArgData::Const(c) => {
1627-
chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
1628-
}
1629-
};
1630-
chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
1631-
}));
1617+
1618+
let kinds =
1619+
binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
1620+
let vk = match it.data(Interner) {
1621+
chalk_ir::GenericArgData::Ty(_) => {
1622+
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
1623+
}
1624+
chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
1625+
chalk_ir::GenericArgData::Const(c) => {
1626+
chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
1627+
}
1628+
};
1629+
chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
1630+
}));
1631+
let binders = CanonicalVarKinds::from_iter(Interner, kinds);
1632+
16321633
let obligation = trait_ref.cast(Interner);
1633-
Canonical {
1634-
binders: CanonicalVarKinds::from_iter(Interner, kinds),
1635-
value: InEnvironment::new(&env.env, obligation),
1636-
}
1634+
let value = InEnvironment::new(&env.env, obligation);
1635+
Canonical { binders, value }
16371636
}
16381637

16391638
fn autoderef_method_receiver(
@@ -1644,7 +1643,7 @@ fn autoderef_method_receiver(
16441643
let mut autoderef = autoderef::Autoderef::new(table, ty, false);
16451644
while let Some((ty, derefs)) = autoderef.next() {
16461645
deref_chain.push((
1647-
autoderef.table.canonicalize(ty).value,
1646+
autoderef.table.canonicalize(ty),
16481647
ReceiverAdjustments { autoref: None, autoderefs: derefs, unsize_array: false },
16491648
));
16501649
}

0 commit comments

Comments
 (0)