Skip to content

Commit 6428273

Browse files
committed
Always reborrow mutable reference receiver in methods
1 parent ea22d24 commit 6428273

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed

crates/hir-ty/src/method_resolution.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,6 @@ pub(crate) fn iterate_method_candidates<T>(
610610
name,
611611
mode,
612612
&mut |adj, item, visible| {
613-
assert!(slot.is_none());
614613
if let Some(it) = callback(adj, item, visible) {
615614
slot = Some(it);
616615
return ControlFlow::Break(());
@@ -894,6 +893,7 @@ pub fn iterate_method_candidates_dyn(
894893
let mut table = InferenceTable::new(db, env.clone());
895894
let ty = table.instantiate_canonical(ty.clone());
896895
let deref_chain = autoderef_method_receiver(&mut table, ty);
896+
let mut is_reborrowing = false;
897897

898898
let result = deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
899899
iterate_method_candidates_with_autoref(
@@ -904,6 +904,7 @@ pub fn iterate_method_candidates_dyn(
904904
traits_in_scope,
905905
visible_from_module,
906906
name,
907+
&mut is_reborrowing,
907908
callback,
908909
)
909910
});
@@ -932,6 +933,7 @@ fn iterate_method_candidates_with_autoref(
932933
traits_in_scope: &FxHashSet<TraitId>,
933934
visible_from_module: VisibleFromModule,
934935
name: Option<&Name>,
936+
is_reborrowing: &mut bool,
935937
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
936938
) -> ControlFlow<()> {
937939
if receiver_ty.value.is_general_var(Interner, &receiver_ty.binders) {
@@ -952,7 +954,21 @@ fn iterate_method_candidates_with_autoref(
952954
)
953955
};
954956

955-
iterate_method_candidates_by_receiver(receiver_ty, first_adjustment.clone())?;
957+
// If `is_reborrowing` is true, it means that there is a reborrow in progress, so we should
958+
// directly go to the autoref step.
959+
if !*is_reborrowing {
960+
let without_autoref =
961+
iterate_method_candidates_by_receiver(receiver_ty, first_adjustment.clone());
962+
if without_autoref.is_break()
963+
&& matches!(receiver_ty.value.kind(Interner), TyKind::Ref(_, _, _))
964+
{
965+
// if `&&T` and `&T` are both applicable, we should prefer `&*&&T` to `&*&T`, so this
966+
// flag exists
967+
*is_reborrowing = true;
968+
return ControlFlow::Continue(());
969+
}
970+
without_autoref?;
971+
}
956972

957973
let refed = Canonical {
958974
value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())

crates/hir-ty/src/tests/method_resolution.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,24 @@ mod bar_test {
388388
);
389389
}
390390

391+
#[test]
392+
fn infer_trait_method_multiple_mutable_reference() {
393+
check_types(
394+
r#"
395+
trait Trait {
396+
fn method(&mut self) -> i32 { 5 }
397+
}
398+
struct S;
399+
impl Trait for &mut &mut S {}
400+
fn test() {
401+
let s = &mut &mut &mut S;
402+
s.method();
403+
//^^^^^^^^^^ i32
404+
}
405+
"#,
406+
);
407+
}
408+
391409
#[test]
392410
fn infer_trait_method_generic_1() {
393411
// the trait implementation is intentionally incomplete -- it shouldn't matter
@@ -1722,7 +1740,7 @@ fn test() {
17221740
Foo.foo();
17231741
//^^^ adjustments: Borrow(Ref(Not))
17241742
(&Foo).foo();
1725-
// ^^^^ adjustments: ,
1743+
// ^^^^ adjustments: Deref(None), Borrow(Ref(Not))
17261744
}
17271745
"#,
17281746
);

crates/ide/src/inlay_hints/adjustment.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,17 @@ fn main() {
315315
(&Struct).consume();
316316
//^^^^^^^*
317317
(&Struct).by_ref();
318+
//^^^^^^^&
319+
//^^^^^^^*
318320
319321
(&mut Struct).consume();
320322
//^^^^^^^^^^^*
321323
(&mut Struct).by_ref();
322324
//^^^^^^^^^^^&
323325
//^^^^^^^^^^^*
324326
(&mut Struct).by_ref_mut();
327+
//^^^^^^^^^^^&mut $
328+
//^^^^^^^^^^^*
325329
326330
// Check that block-like expressions don't duplicate hints
327331
let _: &mut [u32] = (&mut []);
@@ -414,6 +418,10 @@ fn main() {
414418
//^^^^^^^)
415419
//^^^^^^^.*
416420
(&Struct).by_ref();
421+
//^^^^^^^(
422+
//^^^^^^^)
423+
//^^^^^^^.*
424+
//^^^^^^^.&
417425
418426
(&mut Struct).consume();
419427
//^^^^^^^^^^^(
@@ -425,6 +433,10 @@ fn main() {
425433
//^^^^^^^^^^^.*
426434
//^^^^^^^^^^^.&
427435
(&mut Struct).by_ref_mut();
436+
//^^^^^^^^^^^(
437+
//^^^^^^^^^^^)
438+
//^^^^^^^^^^^.*
439+
//^^^^^^^^^^^.&mut
428440
429441
// Check that block-like expressions don't duplicate hints
430442
let _: &mut [u32] = (&mut []);

0 commit comments

Comments
 (0)