From 263f9a7f231a474dd56d02adbcd7c57d079e88fd Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 3 Jun 2020 23:38:25 -0400 Subject: Add tracking of packed repr, use it to highlight unsafe refs Taking a reference to a misaligned field on a packed struct is an unsafe operation. Highlight that behavior. Currently, the misaligned part isn't tracked, so this highlight is a bit too aggressive. --- crates/ra_hir/src/code_model.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 44456e49e..6f9c56d29 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -4,6 +4,7 @@ use std::{iter, sync::Arc}; use arrayvec::ArrayVec; use either::Either; use hir_def::{ + adt::ReprKind, adt::StructKind, adt::VariantData, builtin_type::BuiltinType, @@ -431,6 +432,10 @@ impl Struct { Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) } + pub fn is_packed(self, db: &dyn HirDatabase) -> bool { + matches!(db.struct_data(self.id).repr, Some(ReprKind::Packed)) + } + fn variant_data(self, db: &dyn HirDatabase) -> Arc { db.struct_data(self.id).variant_data.clone() } @@ -1253,6 +1258,19 @@ impl Type { ) } + pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { + let adt_id = match self.ty.value { + Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id, + _ => return false, + }; + + let adt = adt_id.into(); + match adt { + Adt::Struct(s) => s.is_packed(db), + _ => false, + } + } + pub fn is_raw_ptr(&self) -> bool { matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) } -- cgit v1.2.3 From fd30134cf84b134259fe8140e513b152e37f3f88 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Mon, 15 Jun 2020 07:19:45 -0400 Subject: Remove token tree from ReprKind::Other variant, expose ReprKind higher, remove debug println. --- crates/ra_hir/src/code_model.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 6f9c56d29..0007d7fa8 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -432,8 +432,8 @@ impl Struct { Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) } - pub fn is_packed(self, db: &dyn HirDatabase) -> bool { - matches!(db.struct_data(self.id).repr, Some(ReprKind::Packed)) + pub fn repr(self, db: &dyn HirDatabase) -> Option { + db.struct_data(self.id).repr.clone() } fn variant_data(self, db: &dyn HirDatabase) -> Arc { @@ -1266,7 +1266,7 @@ impl Type { let adt = adt_id.into(); match adt { - Adt::Struct(s) => s.is_packed(db), + Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)), _ => false, } } -- cgit v1.2.3 From d5f11e530dbf6edbdd0ca32d6cd5fafe634c8c4a Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sat, 27 Jun 2020 17:11:43 -0400 Subject: Unsafe borrow of packed fields: account for borrow through ref binding, auto ref function calls --- crates/ra_hir/src/code_model.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 0007d7fa8..a880fa671 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,6 +11,7 @@ use hir_def::{ docs::Documentation, expr::{BindingAnnotation, Pat, PatId}, import_map, + item_tree::SelfParam, per_ns::PerNs, resolver::{HasResolver, Resolver}, src::HasSource as _, @@ -670,8 +671,8 @@ impl Function { db.function_data(self.id).name.clone() } - pub fn has_self_param(self, db: &dyn HirDatabase) -> bool { - db.function_data(self.id).has_self_param + pub fn self_param(self, db: &dyn HirDatabase) -> Option { + db.function_data(self.id).self_param } pub fn params(self, db: &dyn HirDatabase) -> Vec { -- cgit v1.2.3 From c5cc24cb312c70159e63315ea49769b575e8cb65 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sun, 28 Jun 2020 16:04:00 -0400 Subject: Revert function structs back to using bool to track self param, use first param for self information in syntax highlighting instead --- crates/ra_hir/src/code_model.rs | 5 ++--- crates/ra_hir/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a880fa671..0007d7fa8 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,7 +11,6 @@ use hir_def::{ docs::Documentation, expr::{BindingAnnotation, Pat, PatId}, import_map, - item_tree::SelfParam, per_ns::PerNs, resolver::{HasResolver, Resolver}, src::HasSource as _, @@ -671,8 +670,8 @@ impl Function { db.function_data(self.id).name.clone() } - pub fn self_param(self, db: &dyn HirDatabase) -> Option { - db.function_data(self.id).self_param + pub fn has_self_param(self, db: &dyn HirDatabase) -> bool { + db.function_data(self.id).has_self_param } pub fn params(self, db: &dyn HirDatabase) -> Vec { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 31f3241c9..34b02c536 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -49,7 +49,7 @@ pub use hir_def::{ docs::Documentation, nameres::ModuleSource, path::{ModPath, Path, PathKind}, - type_ref::Mutability, + type_ref::{Mutability, TypeRef}, }; pub use hir_expand::{ hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, -- cgit v1.2.3 From 08182aa9fad4021e60cdc80ee0a578929507e115 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Sun, 19 Jul 2020 11:45:46 -0400 Subject: Move unsafe packed ref logic to Semantics, use `Attrs::by_key` to simplify repr attr lookup --- crates/ra_hir/src/semantics.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index e392130ab..1072b3971 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -279,6 +279,47 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { pub fn assert_contains_node(&self, node: &SyntaxNode) { self.imp.assert_contains_node(node) } + + pub fn is_unsafe_pat(&self, pat: &ast::Pat) -> bool { + let ty = (|| { + let parent = match pat { + ast::Pat::BindPat(bind_pat) => bind_pat.syntax().parent()?, + _ => return None, + }; + + // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or + // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`, + // so this tries to lookup the `BindPat` anywhere along that structure to the + // `RecordPat` so we can get the containing type. + let record_pat = ast::RecordFieldPat::cast(parent.clone()) + .and_then(|record_pat| record_pat.syntax().parent()) + .or_else(|| Some(parent.clone())) + .and_then(|parent| { + ast::RecordFieldPatList::cast(parent)? + .syntax() + .parent() + .and_then(ast::RecordPat::cast) + }); + + // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if + // this is initialized from a `FieldExpr`. + if let Some(record_pat) = record_pat { + self.type_of_pat(&ast::Pat::RecordPat(record_pat)) + } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { + let field_expr = match let_stmt.initializer()? { + ast::Expr::FieldExpr(field_expr) => field_expr, + _ => return None, + }; + + self.type_of_expr(&field_expr.expr()?) + } else { + None + } + })(); + + // Binding a reference to a packed type is possibly unsafe. + ty.map(|ty| ty.is_packed(self.db)).unwrap_or(false) + } } impl<'db> SemanticsImpl<'db> { -- cgit v1.2.3 From a6af0272f7bf129a3063cdd7096f685fc58438e6 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 23 Jul 2020 10:11:37 -0400 Subject: Move semantic logic into Semantics, fix missing tag for safe amp operator, using functional methods rather than clunky inline closure --- crates/ra_hir/src/semantics.rs | 110 ++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 35 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 1072b3971..f706a186e 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -25,7 +25,8 @@ use crate::{ semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, - Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, + Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef, + VariantDef, }; use resolver::TypeNs; @@ -280,45 +281,84 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.assert_contains_node(node) } - pub fn is_unsafe_pat(&self, pat: &ast::Pat) -> bool { - let ty = (|| { - let parent = match pat { - ast::Pat::BindPat(bind_pat) => bind_pat.syntax().parent()?, - _ => return None, - }; - - // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or - // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`, - // so this tries to lookup the `BindPat` anywhere along that structure to the - // `RecordPat` so we can get the containing type. - let record_pat = ast::RecordFieldPat::cast(parent.clone()) - .and_then(|record_pat| record_pat.syntax().parent()) - .or_else(|| Some(parent.clone())) - .and_then(|parent| { - ast::RecordFieldPatList::cast(parent)? - .syntax() - .parent() - .and_then(ast::RecordPat::cast) - }); - - // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if - // this is initialized from a `FieldExpr`. - if let Some(record_pat) = record_pat { - self.type_of_pat(&ast::Pat::RecordPat(record_pat)) - } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { - let field_expr = match let_stmt.initializer()? { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; + pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> Option<()> { + let expr = method_call_expr.expr()?; + let field_expr = + if let ast::Expr::FieldExpr(field_expr) = expr { field_expr } else { return None }; + let ty = self.type_of_expr(&field_expr.expr()?)?; + if !ty.is_packed(self.db) { + return None; + } - self.type_of_expr(&field_expr.expr()?) + let func = self.resolve_method_call(&method_call_expr)?; + if func.has_self_param(self.db) { + let params = func.params(self.db); + if matches!(params.into_iter().next(), Some(TypeRef::Reference(..))) { + Some(()) } else { None } - })(); + } else { + None + } + } - // Binding a reference to a packed type is possibly unsafe. - ty.map(|ty| ty.is_packed(self.db)).unwrap_or(false) + pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { + ref_expr + .expr() + .and_then(|expr| { + let field_expr = match expr { + ast::Expr::FieldExpr(field_expr) => field_expr, + _ => return None, + }; + let expr = field_expr.expr()?; + self.type_of_expr(&expr) + }) + // Binding a reference to a packed type is possibly unsafe. + .map(|ty| ty.is_packed(self.db)) + .unwrap_or(false) + + // FIXME This needs layout computation to be correct. It will highlight + // more than it should with the current implementation. + } + + pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool { + bind_pat + .syntax() + .parent() + .and_then(|parent| { + // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or + // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`, + // so this tries to lookup the `BindPat` anywhere along that structure to the + // `RecordPat` so we can get the containing type. + let record_pat = ast::RecordFieldPat::cast(parent.clone()) + .and_then(|record_pat| record_pat.syntax().parent()) + .or_else(|| Some(parent.clone())) + .and_then(|parent| { + ast::RecordFieldPatList::cast(parent)? + .syntax() + .parent() + .and_then(ast::RecordPat::cast) + }); + + // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if + // this is initialized from a `FieldExpr`. + if let Some(record_pat) = record_pat { + self.type_of_pat(&ast::Pat::RecordPat(record_pat)) + } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { + let field_expr = match let_stmt.initializer()? { + ast::Expr::FieldExpr(field_expr) => field_expr, + _ => return None, + }; + + self.type_of_expr(&field_expr.expr()?) + } else { + None + } + }) + // Binding a reference to a packed type is possibly unsafe. + .map(|ty| ty.is_packed(self.db)) + .unwrap_or(false) } } -- cgit v1.2.3 From 39fdd41df4052cef5da4876067ae28615012476b Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 23 Jul 2020 18:31:28 -0400 Subject: Return bool from is_unsafe_method_call and cleanup usages --- crates/ra_hir/src/semantics.rs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index f706a186e..9697c7082 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -281,26 +281,26 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.assert_contains_node(node) } - pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> Option<()> { - let expr = method_call_expr.expr()?; - let field_expr = - if let ast::Expr::FieldExpr(field_expr) = expr { field_expr } else { return None }; - let ty = self.type_of_expr(&field_expr.expr()?)?; - if !ty.is_packed(self.db) { - return None; - } + pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { + method_call_expr + .expr() + .and_then(|expr| { + let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { + field_expr + } else { + return None; + }; + let ty = self.type_of_expr(&field_expr.expr()?)?; + if !ty.is_packed(self.db) { + return None; + } - let func = self.resolve_method_call(&method_call_expr)?; - if func.has_self_param(self.db) { - let params = func.params(self.db); - if matches!(params.into_iter().next(), Some(TypeRef::Reference(..))) { - Some(()) - } else { - None - } - } else { - None - } + let func = self.resolve_method_call(&method_call_expr)?; + let is_unsafe = func.has_self_param(self.db) + && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..))); + Some(is_unsafe) + }) + .unwrap_or(false) } pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { -- cgit v1.2.3 From 61dff939f909e0c53bcd3be4c3e672c794022cde Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Thu, 30 Jul 2020 09:26:40 -0400 Subject: Move unsafe semantics methods into `SemanticsImpl` and reference them in `Semantics` --- crates/ra_hir/src/semantics.rs | 154 ++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 71 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 9697c7082..758d00409 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -282,83 +282,15 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { } pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { - method_call_expr - .expr() - .and_then(|expr| { - let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { - field_expr - } else { - return None; - }; - let ty = self.type_of_expr(&field_expr.expr()?)?; - if !ty.is_packed(self.db) { - return None; - } - - let func = self.resolve_method_call(&method_call_expr)?; - let is_unsafe = func.has_self_param(self.db) - && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..))); - Some(is_unsafe) - }) - .unwrap_or(false) + self.imp.is_unsafe_method_call(method_call_expr) } pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { - ref_expr - .expr() - .and_then(|expr| { - let field_expr = match expr { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - let expr = field_expr.expr()?; - self.type_of_expr(&expr) - }) - // Binding a reference to a packed type is possibly unsafe. - .map(|ty| ty.is_packed(self.db)) - .unwrap_or(false) - - // FIXME This needs layout computation to be correct. It will highlight - // more than it should with the current implementation. + self.imp.is_unsafe_ref_expr(ref_expr) } pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool { - bind_pat - .syntax() - .parent() - .and_then(|parent| { - // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or - // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`, - // so this tries to lookup the `BindPat` anywhere along that structure to the - // `RecordPat` so we can get the containing type. - let record_pat = ast::RecordFieldPat::cast(parent.clone()) - .and_then(|record_pat| record_pat.syntax().parent()) - .or_else(|| Some(parent.clone())) - .and_then(|parent| { - ast::RecordFieldPatList::cast(parent)? - .syntax() - .parent() - .and_then(ast::RecordPat::cast) - }); - - // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if - // this is initialized from a `FieldExpr`. - if let Some(record_pat) = record_pat { - self.type_of_pat(&ast::Pat::RecordPat(record_pat)) - } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { - let field_expr = match let_stmt.initializer()? { - ast::Expr::FieldExpr(field_expr) => field_expr, - _ => return None, - }; - - self.type_of_expr(&field_expr.expr()?) - } else { - None - } - }) - // Binding a reference to a packed type is possibly unsafe. - .map(|ty| ty.is_packed(self.db)) - .unwrap_or(false) + self.imp.is_unsafe_bind_pat(bind_pat) } } @@ -655,6 +587,86 @@ impl<'db> SemanticsImpl<'db> { }); InFile::new(file_id, node) } + + pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { + method_call_expr + .expr() + .and_then(|expr| { + let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr { + field_expr + } else { + return None; + }; + let ty = self.type_of_expr(&field_expr.expr()?)?; + if !ty.is_packed(self.db) { + return None; + } + + let func = self.resolve_method_call(&method_call_expr).map(Function::from)?; + let is_unsafe = func.has_self_param(self.db) + && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..))); + Some(is_unsafe) + }) + .unwrap_or(false) + } + + pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool { + ref_expr + .expr() + .and_then(|expr| { + let field_expr = match expr { + ast::Expr::FieldExpr(field_expr) => field_expr, + _ => return None, + }; + let expr = field_expr.expr()?; + self.type_of_expr(&expr) + }) + // Binding a reference to a packed type is possibly unsafe. + .map(|ty| ty.is_packed(self.db)) + .unwrap_or(false) + + // FIXME This needs layout computation to be correct. It will highlight + // more than it should with the current implementation. + } + + pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool { + bind_pat + .syntax() + .parent() + .and_then(|parent| { + // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or + // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`, + // so this tries to lookup the `BindPat` anywhere along that structure to the + // `RecordPat` so we can get the containing type. + let record_pat = ast::RecordFieldPat::cast(parent.clone()) + .and_then(|record_pat| record_pat.syntax().parent()) + .or_else(|| Some(parent.clone())) + .and_then(|parent| { + ast::RecordFieldPatList::cast(parent)? + .syntax() + .parent() + .and_then(ast::RecordPat::cast) + }); + + // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if + // this is initialized from a `FieldExpr`. + if let Some(record_pat) = record_pat { + self.type_of_pat(&ast::Pat::RecordPat(record_pat)) + } else if let Some(let_stmt) = ast::LetStmt::cast(parent) { + let field_expr = match let_stmt.initializer()? { + ast::Expr::FieldExpr(field_expr) => field_expr, + _ => return None, + }; + + self.type_of_expr(&field_expr.expr()?) + } else { + None + } + }) + // Binding a reference to a packed type is possibly unsafe. + .map(|ty| ty.is_packed(self.db)) + .unwrap_or(false) + } } pub trait ToDef: AstNode + Clone { -- cgit v1.2.3 From 2199d0cda9c745ecb460dd987b8da982d02bc130 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Fri, 7 Aug 2020 10:40:09 -0400 Subject: Fix type names broken by rebase, redo expected test because of rebase --- crates/ra_hir/src/semantics.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 758d00409..872f5fa4c 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs @@ -289,8 +289,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.is_unsafe_ref_expr(ref_expr) } - pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool { - self.imp.is_unsafe_bind_pat(bind_pat) + pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { + self.imp.is_unsafe_ident_pat(ident_pat) } } @@ -629,20 +629,24 @@ impl<'db> SemanticsImpl<'db> { // more than it should with the current implementation. } - pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool { - bind_pat + pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool { + if !ident_pat.ref_token().is_some() { + return false; + } + + ident_pat .syntax() .parent() .and_then(|parent| { - // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or - // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`, - // so this tries to lookup the `BindPat` anywhere along that structure to the + // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or + // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`, + // so this tries to lookup the `IdentPat` anywhere along that structure to the // `RecordPat` so we can get the containing type. - let record_pat = ast::RecordFieldPat::cast(parent.clone()) + let record_pat = ast::RecordPatField::cast(parent.clone()) .and_then(|record_pat| record_pat.syntax().parent()) .or_else(|| Some(parent.clone())) .and_then(|parent| { - ast::RecordFieldPatList::cast(parent)? + ast::RecordPatFieldList::cast(parent)? .syntax() .parent() .and_then(ast::RecordPat::cast) -- cgit v1.2.3