mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 14:03:35 +00:00
fix: try obligation of IndexMut
when infer
This commit is contained in:
parent
3ab1666370
commit
1b7968a2cb
8 changed files with 74 additions and 12 deletions
|
@ -622,7 +622,8 @@ impl ExprCollector<'_> {
|
||||||
ast::Expr::IndexExpr(e) => {
|
ast::Expr::IndexExpr(e) => {
|
||||||
let base = self.collect_expr_opt(e.base());
|
let base = self.collect_expr_opt(e.base());
|
||||||
let index = self.collect_expr_opt(e.index());
|
let index = self.collect_expr_opt(e.index());
|
||||||
self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
|
let is_assignee_expr = self.is_lowering_assignee_expr;
|
||||||
|
self.alloc_expr(Expr::Index { base, index, is_assignee_expr }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::Expr::RangeExpr(e) => {
|
ast::Expr::RangeExpr(e) => {
|
||||||
let lhs = e.start().map(|lhs| self.collect_expr(lhs));
|
let lhs = e.start().map(|lhs| self.collect_expr(lhs));
|
||||||
|
|
|
@ -376,7 +376,7 @@ impl Printer<'_> {
|
||||||
w!(self, ") ");
|
w!(self, ") ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Index { base, index } => {
|
Expr::Index { base, index, is_assignee_expr: _ } => {
|
||||||
self.print_expr(*base);
|
self.print_expr(*base);
|
||||||
w!(self, "[");
|
w!(self, "[");
|
||||||
self.print_expr(*index);
|
self.print_expr(*index);
|
||||||
|
|
|
@ -265,6 +265,7 @@ pub enum Expr {
|
||||||
Index {
|
Index {
|
||||||
base: ExprId,
|
base: ExprId,
|
||||||
index: ExprId,
|
index: ExprId,
|
||||||
|
is_assignee_expr: bool,
|
||||||
},
|
},
|
||||||
Closure {
|
Closure {
|
||||||
args: Box<[PatId]>,
|
args: Box<[PatId]>,
|
||||||
|
@ -432,7 +433,7 @@ impl Expr {
|
||||||
f(rhs);
|
f(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Index { base, index } => {
|
Expr::Index { base, index, .. } => {
|
||||||
f(*base);
|
f(*base);
|
||||||
f(*index);
|
f(*index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -598,7 +598,7 @@ impl InferenceContext<'_> {
|
||||||
self.consume_expr(expr);
|
self.consume_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Index { base, index } => {
|
Expr::Index { base, index, is_assignee_expr: _ } => {
|
||||||
self.select_from_expr(*base);
|
self.select_from_expr(*base);
|
||||||
self.consume_expr(*index);
|
self.consume_expr(*index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -744,7 +744,7 @@ impl InferenceContext<'_> {
|
||||||
(RangeOp::Inclusive, _, None) => self.err_ty(),
|
(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 base_ty = self.infer_expr_inner(*base, &Expectation::none());
|
||||||
let index_ty = self.infer_expr(*index, &Expectation::none());
|
let index_ty = self.infer_expr(*index, &Expectation::none());
|
||||||
|
|
||||||
|
@ -772,11 +772,24 @@ impl InferenceContext<'_> {
|
||||||
.build();
|
.build();
|
||||||
self.write_method_resolution(tgt_expr, func, substs);
|
self.write_method_resolution(tgt_expr, func, substs);
|
||||||
}
|
}
|
||||||
self.resolve_associated_type_with_params(
|
let assoc = self.resolve_ops_index_output();
|
||||||
self_ty,
|
let res = self.resolve_associated_type_with_params(
|
||||||
self.resolve_ops_index_output(),
|
self_ty.clone(),
|
||||||
&[index_ty.cast(Interner)],
|
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 {
|
} else {
|
||||||
self.err_ty()
|
self.err_ty()
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl InferenceContext<'_> {
|
||||||
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
|
Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => {
|
||||||
self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread))
|
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 mutability == Mutability::Mut {
|
||||||
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
|
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
|
||||||
if let Some(index_trait) = self
|
if let Some(index_trait) = self
|
||||||
|
|
|
@ -218,7 +218,7 @@ impl MirLowerCtx<'_> {
|
||||||
self.push_field_projection(&mut r, expr_id)?;
|
self.push_field_projection(&mut r, expr_id)?;
|
||||||
Ok(Some((r, current)))
|
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 base_ty = self.expr_ty_after_adjustments(*base);
|
||||||
let index_ty = self.expr_ty_after_adjustments(*index);
|
let index_ty = self.expr_ty_after_adjustments(*index);
|
||||||
if index_ty != TyBuilder::usize()
|
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…
Reference in a new issue