diff options
author | Paul Daniel Faria <[email protected]> | 2020-07-19 16:45:46 +0100 |
---|---|---|
committer | Paul Daniel Faria <[email protected]> | 2020-08-10 13:44:54 +0100 |
commit | 08182aa9fad4021e60cdc80ee0a578929507e115 (patch) | |
tree | 3056a7d87fd90356da335f3650a8438ce2a03761 /crates/ra_hir/src | |
parent | c5cc24cb312c70159e63315ea49769b575e8cb65 (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.rs | 41 |
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 | ||
284 | impl<'db> SemanticsImpl<'db> { | 325 | impl<'db> SemanticsImpl<'db> { |