Skip to content

Commit 3fe6ff7

Browse files
committed
Auto merge of rust-lang#16085 - Austaras:master, r=Veykril
fix: try obligation of `IndexMut` when infer Closes rust-lang#15842. This issue arises because `K` is ambiguous if only inferred from `Index` trait, but is unique if inferred from `IndexMut`, but r-a doesn't use this info.
2 parents 4f94ebb + 1b7968a commit 3fe6ff7

File tree

8 files changed

+74
-12
lines changed

8 files changed

+74
-12
lines changed

crates/hir-def/src/body/lower.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ impl ExprCollector<'_> {
622622
ast::Expr::IndexExpr(e) => {
623623
let base = self.collect_expr_opt(e.base());
624624
let index = self.collect_expr_opt(e.index());
625-
self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
625+
let is_assignee_expr = self.is_lowering_assignee_expr;
626+
self.alloc_expr(Expr::Index { base, index, is_assignee_expr }, syntax_ptr)
626627
}
627628
ast::Expr::RangeExpr(e) => {
628629
let lhs = e.start().map(|lhs| self.collect_expr(lhs));

crates/hir-def/src/body/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ impl Printer<'_> {
376376
w!(self, ") ");
377377
}
378378
}
379-
Expr::Index { base, index } => {
379+
Expr::Index { base, index, is_assignee_expr: _ } => {
380380
self.print_expr(*base);
381381
w!(self, "[");
382382
self.print_expr(*index);

crates/hir-def/src/hir.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ pub enum Expr {
265265
Index {
266266
base: ExprId,
267267
index: ExprId,
268+
is_assignee_expr: bool,
268269
},
269270
Closure {
270271
args: Box<[PatId]>,
@@ -432,7 +433,7 @@ impl Expr {
432433
f(rhs);
433434
}
434435
}
435-
Expr::Index { base, index } => {
436+
Expr::Index { base, index, .. } => {
436437
f(*base);
437438
f(*index);
438439
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ impl InferenceContext<'_> {
598598
self.consume_expr(expr);
599599
}
600600
}
601-
Expr::Index { base, index } => {
601+
Expr::Index { base, index, is_assignee_expr: _ } => {
602602
self.select_from_expr(*base);
603603
self.consume_expr(*index);
604604
}

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

+19-6
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ impl InferenceContext<'_> {
744744
(RangeOp::Inclusive, _, None) => self.err_ty(),
745745
}
746746
}
747-
Expr::Index { base, index } => {
747+
Expr::Index { base, index, is_assignee_expr } => {
748748
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
749749
let index_ty = self.infer_expr(*index, &Expectation::none());
750750

@@ -772,11 +772,24 @@ impl InferenceContext<'_> {
772772
.build();
773773
self.write_method_resolution(tgt_expr, func, substs);
774774
}
775-
self.resolve_associated_type_with_params(
776-
self_ty,
777-
self.resolve_ops_index_output(),
778-
&[index_ty.cast(Interner)],
779-
)
775+
let assoc = self.resolve_ops_index_output();
776+
let res = self.resolve_associated_type_with_params(
777+
self_ty.clone(),
778+
assoc,
779+
&[index_ty.clone().cast(Interner)],
780+
);
781+
782+
if *is_assignee_expr {
783+
if let Some(index_trait) = self.resolve_lang_trait(LangItem::IndexMut) {
784+
let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
785+
.push(self_ty)
786+
.fill(|_| index_ty.clone().cast(Interner))
787+
.build();
788+
self.push_obligation(trait_ref.cast(Interner));
789+
}
790+
}
791+
792+
res
780793
} else {
781794
self.err_ty()
782795
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl InferenceContext<'_> {
9696
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
9797
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
9898
}
99-
&Expr::Index { base, index } => {
99+
&Expr::Index { base, index, is_assignee_expr: _ } => {
100100
if mutability == Mutability::Mut {
101101
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
102102
if let Some(index_trait) = self

crates/hir-ty/src/mir/lower/as_place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl MirLowerCtx<'_> {
218218
self.push_field_projection(&mut r, expr_id)?;
219219
Ok(Some((r, current)))
220220
}
221-
Expr::Index { base, index } => {
221+
Expr::Index { base, index, is_assignee_expr: _ } => {
222222
let base_ty = self.expr_ty_after_adjustments(*base);
223223
let index_ty = self.expr_ty_after_adjustments(*index);
224224
if index_ty != TyBuilder::usize()

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

+47
Original file line numberDiff line numberDiff line change
@@ -4506,3 +4506,50 @@ fn ttt() {
45064506
"#,
45074507
);
45084508
}
4509+
4510+
#[test]
4511+
fn infer_borrow() {
4512+
check_types(
4513+
r#"
4514+
//- minicore: index
4515+
pub struct SomeMap<K>;
4516+
4517+
pub trait Borrow<Borrowed: ?Sized> {
4518+
fn borrow(&self) -> &Borrowed;
4519+
}
4520+
4521+
impl<T: ?Sized> Borrow<T> for T {
4522+
fn borrow(&self) -> &T {
4523+
self
4524+
}
4525+
}
4526+
4527+
impl<T: ?Sized> Borrow<T> for &T {
4528+
fn borrow(&self) -> &T {
4529+
&**self
4530+
}
4531+
}
4532+
4533+
impl<K, KB: Borrow<K>> core::ops::Index<KB> for SomeMap<K> {
4534+
type Output = ();
4535+
4536+
fn index(&self, _: KB) -> &() {
4537+
&()
4538+
}
4539+
}
4540+
4541+
impl<K> core::ops::IndexMut<K> for SomeMap<K> {
4542+
fn index_mut(&mut self, _: K) -> &mut () {
4543+
&mut ()
4544+
}
4545+
}
4546+
4547+
fn foo() {
4548+
let mut map = SomeMap;
4549+
map["a"] = ();
4550+
map;
4551+
//^^^ SomeMap<&str>
4552+
}
4553+
"#,
4554+
);
4555+
}

0 commit comments

Comments
 (0)