aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorPaul Daniel Faria <[email protected]>2020-07-19 16:45:46 +0100
committerPaul Daniel Faria <[email protected]>2020-08-10 13:44:54 +0100
commit08182aa9fad4021e60cdc80ee0a578929507e115 (patch)
tree3056a7d87fd90356da335f3650a8438ce2a03761 /crates/ra_hir/src
parentc5cc24cb312c70159e63315ea49769b575e8cb65 (diff)
Move unsafe packed ref logic to Semantics, use `Attrs::by_key` to simplify repr attr lookup
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/semantics.rs41
1 files changed, 41 insertions, 0 deletions
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> {
279 pub fn assert_contains_node(&self, node: &SyntaxNode) { 279 pub fn assert_contains_node(&self, node: &SyntaxNode) {
280 self.imp.assert_contains_node(node) 280 self.imp.assert_contains_node(node)
281 } 281 }
282
283 pub fn is_unsafe_pat(&self, pat: &ast::Pat) -> bool {
284 let ty = (|| {
285 let parent = match pat {
286 ast::Pat::BindPat(bind_pat) => bind_pat.syntax().parent()?,
287 _ => return None,
288 };
289
290 // `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or
291 // `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`,
292 // so this tries to lookup the `BindPat` anywhere along that structure to the
293 // `RecordPat` so we can get the containing type.
294 let record_pat = ast::RecordFieldPat::cast(parent.clone())
295 .and_then(|record_pat| record_pat.syntax().parent())
296 .or_else(|| Some(parent.clone()))
297 .and_then(|parent| {
298 ast::RecordFieldPatList::cast(parent)?
299 .syntax()
300 .parent()
301 .and_then(ast::RecordPat::cast)
302 });
303
304 // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
305 // this is initialized from a `FieldExpr`.
306 if let Some(record_pat) = record_pat {
307 self.type_of_pat(&ast::Pat::RecordPat(record_pat))
308 } else if let Some(let_stmt) = ast::LetStmt::cast(parent) {
309 let field_expr = match let_stmt.initializer()? {
310 ast::Expr::FieldExpr(field_expr) => field_expr,
311 _ => return None,
312 };
313
314 self.type_of_expr(&field_expr.expr()?)
315 } else {
316 None
317 }
318 })();
319
320 // Binding a reference to a packed type is possibly unsafe.
321 ty.map(|ty| ty.is_packed(self.db)).unwrap_or(false)
322 }
282} 323}
283 324
284impl<'db> SemanticsImpl<'db> { 325impl<'db> SemanticsImpl<'db> {