mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
Auto merge of #16085 - Austaras:master, r=Veykril
fix: try obligation of `IndexMut` when infer Closes #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.
This commit is contained in:
commit
3fe6ff74cf
8 changed files with 74 additions and 12 deletions
|
@ -598,7 +598,7 @@ impl InferenceContext<'_> {
|
|||
self.consume_expr(expr);
|
||||
}
|
||||
}
|
||||
Expr::Index { base, index } => {
|
||||
Expr::Index { base, index, is_assignee_expr: _ } => {
|
||||
self.select_from_expr(*base);
|
||||
self.consume_expr(*index);
|
||||
}
|
||||
|
|
|
@ -744,7 +744,7 @@ impl InferenceContext<'_> {
|
|||
(RangeOp::Inclusive, _, None) => self.err_ty(),
|
||||
}
|
||||
}
|
||||
Expr::Index { base, index } => {
|
||||
Expr::Index { base, index, is_assignee_expr } => {
|
||||
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
|
||||
let index_ty = self.infer_expr(*index, &Expectation::none());
|
||||
|
||||
|
@ -772,11 +772,24 @@ impl InferenceContext<'_> {
|
|||
.build();
|
||||
self.write_method_resolution(tgt_expr, func, substs);
|
||||
}
|
||||
self.resolve_associated_type_with_params(
|
||||
self_ty,
|
||||
self.resolve_ops_index_output(),
|
||||
&[index_ty.cast(Interner)],
|
||||
)
|
||||
let assoc = self.resolve_ops_index_output();
|
||||
let res = self.resolve_associated_type_with_params(
|
||||
self_ty.clone(),
|
||||
assoc,
|
||||
&[index_ty.clone().cast(Interner)],
|
||||
);
|
||||
|
||||
if *is_assignee_expr {
|
||||
if let Some(index_trait) = self.resolve_lang_trait(LangItem::IndexMut) {
|
||||
let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
|
||||
.push(self_ty)
|
||||
.fill(|_| index_ty.clone().cast(Interner))
|
||||
.build();
|
||||
self.push_obligation(trait_ref.cast(Interner));
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
} else {
|
||||
self.err_ty()
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ impl InferenceContext<'_> {
|
|||
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
|
||||
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
|
||||
}
|
||||
&Expr::Index { base, index } => {
|
||||
&Expr::Index { base, index, is_assignee_expr: _ } => {
|
||||
if mutability == Mutability::Mut {
|
||||
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
|
||||
if let Some(index_trait) = self
|
||||
|
|
|
@ -218,7 +218,7 @@ impl MirLowerCtx<'_> {
|
|||
self.push_field_projection(&mut r, expr_id)?;
|
||||
Ok(Some((r, current)))
|
||||
}
|
||||
Expr::Index { base, index } => {
|
||||
Expr::Index { base, index, is_assignee_expr: _ } => {
|
||||
let base_ty = self.expr_ty_after_adjustments(*base);
|
||||
let index_ty = self.expr_ty_after_adjustments(*index);
|
||||
if index_ty != TyBuilder::usize()
|
||||
|
|
|
@ -4506,3 +4506,50 @@ fn ttt() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_borrow() {
|
||||
check_types(
|
||||
r#"
|
||||
//- minicore: index
|
||||
pub struct SomeMap<K>;
|
||||
|
||||
pub trait Borrow<Borrowed: ?Sized> {
|
||||
fn borrow(&self) -> &Borrowed;
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Borrow<T> for T {
|
||||
fn borrow(&self) -> &T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Borrow<T> for &T {
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, KB: Borrow<K>> core::ops::Index<KB> for SomeMap<K> {
|
||||
type Output = ();
|
||||
|
||||
fn index(&self, _: KB) -> &() {
|
||||
&()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> core::ops::IndexMut<K> for SomeMap<K> {
|
||||
fn index_mut(&mut self, _: K) -> &mut () {
|
||||
&mut ()
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let mut map = SomeMap;
|
||||
map["a"] = ();
|
||||
map;
|
||||
//^^^ SomeMap<&str>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue