Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure/analysis.rs')
-rw-r--r--crates/hir-ty/src/infer/closure/analysis.rs60
1 files changed, 18 insertions, 42 deletions
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs
index 763b145812..944b3594ba 100644
--- a/crates/hir-ty/src/infer/closure/analysis.rs
+++ b/crates/hir-ty/src/infer/closure/analysis.rs
@@ -11,11 +11,8 @@ use hir_def::{
Statement, UnaryOp,
},
item_tree::FieldsShape,
- lang_item::LangItem,
resolver::ValueNs,
};
-use hir_expand::name::Name;
-use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::inherent::{IntoKind, SliceLike, Ty as _};
@@ -351,10 +348,12 @@ impl<'db> InferenceContext<'_, 'db> {
return Some(place);
}
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
- if matches!(
- self.expr_ty_after_adjustments(*expr).kind(),
- TyKind::Ref(..) | TyKind::RawPtr(..)
- ) {
+ let is_builtin_deref = match self.expr_ty(*expr).kind() {
+ TyKind::Ref(..) | TyKind::RawPtr(..) => true,
+ TyKind::Adt(adt_def, _) if adt_def.is_box() => true,
+ _ => false,
+ };
+ if is_builtin_deref {
let mut place = self.place_of_expr(*expr)?;
self.current_capture_span_stack.push(MirSpan::ExprId(tgt_expr));
place.projections.push(ProjectionElem::Deref);
@@ -609,28 +608,19 @@ impl<'db> InferenceContext<'_, 'db> {
}
Expr::Field { expr, name: _ } => self.select_from_expr(*expr),
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
- if matches!(
- self.expr_ty_after_adjustments(*expr).kind(),
- TyKind::Ref(..) | TyKind::RawPtr(..)
- ) {
- self.select_from_expr(*expr);
- } else if let Some((f, _)) = self.result.method_resolution(tgt_expr) {
- let mutability = 'b: {
- if let Some(deref_trait) =
- self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
- && let Some(deref_fn) = deref_trait
- .trait_items(self.db)
- .method_by_name(&Name::new_symbol_root(sym::deref_mut))
- {
- break 'b deref_fn == f;
+ if self.result.method_resolution(tgt_expr).is_some() {
+ // Overloaded deref.
+ match self.expr_ty_after_adjustments(*expr).kind() {
+ TyKind::Ref(_, _, mutability) => {
+ let place = self.place_of_expr(*expr);
+ match mutability {
+ Mutability::Mut => self.mutate_expr(*expr, place),
+ Mutability::Not => self.ref_expr(*expr, place),
+ }
}
- false
- };
- let place = self.place_of_expr(*expr);
- if mutability {
- self.mutate_expr(*expr, place);
- } else {
- self.ref_expr(*expr, place);
+ // FIXME: Is this correct wrt. raw pointer derefs?
+ TyKind::RawPtr(..) => self.select_from_expr(*expr),
+ _ => never!("deref adjustments should include taking a mutable reference"),
}
} else {
self.select_from_expr(*expr);
@@ -806,20 +796,6 @@ impl<'db> InferenceContext<'_, 'db> {
self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
}
- fn expr_ty(&self, expr: ExprId) -> Ty<'db> {
- self.result[expr]
- }
-
- fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> {
- let mut ty = None;
- if let Some(it) = self.result.expr_adjustments.get(&e)
- && let Some(it) = it.last()
- {
- ty = Some(it.target);
- }
- ty.unwrap_or_else(|| self.expr_ty(e))
- }
-
fn is_upvar(&self, place: &HirPlace<'db>) -> bool {
if let Some(c) = self.current_closure {
let InternedClosure(_, root) = self.db.lookup_intern_closure(c);