Skip to content

Commit a8433d4

Browse files
committed
Move unsafe semantics methods into SemanticsImpl and reference them in Semantics
1 parent e63a16a commit a8433d4

File tree

1 file changed

+83
-71
lines changed

1 file changed

+83
-71
lines changed

crates/ra_hir/src/semantics.rs

Lines changed: 83 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -278,83 +278,15 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
278278
}
279279

280280
pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool {
281-
method_call_expr
282-
.expr()
283-
.and_then(|expr| {
284-
let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr {
285-
field_expr
286-
} else {
287-
return None;
288-
};
289-
let ty = self.type_of_expr(&field_expr.expr()?)?;
290-
if !ty.is_packed(self.db) {
291-
return None;
292-
}
293-
294-
let func = self.resolve_method_call(&method_call_expr)?;
295-
let is_unsafe = func.has_self_param(self.db)
296-
&& matches!(func.params(self.db).first(), Some(TypeRef::Reference(..)));
297-
Some(is_unsafe)
298-
})
299-
.unwrap_or(false)
281+
self.imp.is_unsafe_method_call(method_call_expr)
300282
}
301283

302284
pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
303-
ref_expr
304-
.expr()
305-
.and_then(|expr| {
306-
let field_expr = match expr {
307-
ast::Expr::FieldExpr(field_expr) => field_expr,
308-
_ => return None,
309-
};
310-
let expr = field_expr.expr()?;
311-
self.type_of_expr(&expr)
312-
})
313-
// Binding a reference to a packed type is possibly unsafe.
314-
.map(|ty| ty.is_packed(self.db))
315-
.unwrap_or(false)
316-
317-
// FIXME This needs layout computation to be correct. It will highlight
318-
// more than it should with the current implementation.
285+
self.imp.is_unsafe_ref_expr(ref_expr)
319286
}
320287

321288
pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool {
322-
bind_pat
323-
.syntax()
324-
.parent()
325-
.and_then(|parent| {
326-
// `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or
327-
// `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`,
328-
// so this tries to lookup the `BindPat` anywhere along that structure to the
329-
// `RecordPat` so we can get the containing type.
330-
let record_pat = ast::RecordFieldPat::cast(parent.clone())
331-
.and_then(|record_pat| record_pat.syntax().parent())
332-
.or_else(|| Some(parent.clone()))
333-
.and_then(|parent| {
334-
ast::RecordFieldPatList::cast(parent)?
335-
.syntax()
336-
.parent()
337-
.and_then(ast::RecordPat::cast)
338-
});
339-
340-
// If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
341-
// this is initialized from a `FieldExpr`.
342-
if let Some(record_pat) = record_pat {
343-
self.type_of_pat(&ast::Pat::RecordPat(record_pat))
344-
} else if let Some(let_stmt) = ast::LetStmt::cast(parent) {
345-
let field_expr = match let_stmt.initializer()? {
346-
ast::Expr::FieldExpr(field_expr) => field_expr,
347-
_ => return None,
348-
};
349-
350-
self.type_of_expr(&field_expr.expr()?)
351-
} else {
352-
None
353-
}
354-
})
355-
// Binding a reference to a packed type is possibly unsafe.
356-
.map(|ty| ty.is_packed(self.db))
357-
.unwrap_or(false)
289+
self.imp.is_unsafe_bind_pat(bind_pat)
358290
}
359291
}
360292

@@ -640,6 +572,86 @@ impl<'db> SemanticsImpl<'db> {
640572
});
641573
InFile::new(file_id, node)
642574
}
575+
576+
pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool {
577+
method_call_expr
578+
.expr()
579+
.and_then(|expr| {
580+
let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr {
581+
field_expr
582+
} else {
583+
return None;
584+
};
585+
let ty = self.type_of_expr(&field_expr.expr()?)?;
586+
if !ty.is_packed(self.db) {
587+
return None;
588+
}
589+
590+
let func = self.resolve_method_call(&method_call_expr).map(Function::from)?;
591+
let is_unsafe = func.has_self_param(self.db)
592+
&& matches!(func.params(self.db).first(), Some(TypeRef::Reference(..)));
593+
Some(is_unsafe)
594+
})
595+
.unwrap_or(false)
596+
}
597+
598+
pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
599+
ref_expr
600+
.expr()
601+
.and_then(|expr| {
602+
let field_expr = match expr {
603+
ast::Expr::FieldExpr(field_expr) => field_expr,
604+
_ => return None,
605+
};
606+
let expr = field_expr.expr()?;
607+
self.type_of_expr(&expr)
608+
})
609+
// Binding a reference to a packed type is possibly unsafe.
610+
.map(|ty| ty.is_packed(self.db))
611+
.unwrap_or(false)
612+
613+
// FIXME This needs layout computation to be correct. It will highlight
614+
// more than it should with the current implementation.
615+
}
616+
617+
pub fn is_unsafe_bind_pat(&self, bind_pat: &ast::BindPat) -> bool {
618+
bind_pat
619+
.syntax()
620+
.parent()
621+
.and_then(|parent| {
622+
// `BindPat` can live under `RecordPat` directly under `RecordFieldPat` or
623+
// `RecordFieldPatList`. `RecordFieldPat` also lives under `RecordFieldPatList`,
624+
// so this tries to lookup the `BindPat` anywhere along that structure to the
625+
// `RecordPat` so we can get the containing type.
626+
let record_pat = ast::RecordFieldPat::cast(parent.clone())
627+
.and_then(|record_pat| record_pat.syntax().parent())
628+
.or_else(|| Some(parent.clone()))
629+
.and_then(|parent| {
630+
ast::RecordFieldPatList::cast(parent)?
631+
.syntax()
632+
.parent()
633+
.and_then(ast::RecordPat::cast)
634+
});
635+
636+
// If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
637+
// this is initialized from a `FieldExpr`.
638+
if let Some(record_pat) = record_pat {
639+
self.type_of_pat(&ast::Pat::RecordPat(record_pat))
640+
} else if let Some(let_stmt) = ast::LetStmt::cast(parent) {
641+
let field_expr = match let_stmt.initializer()? {
642+
ast::Expr::FieldExpr(field_expr) => field_expr,
643+
_ => return None,
644+
};
645+
646+
self.type_of_expr(&field_expr.expr()?)
647+
} else {
648+
None
649+
}
650+
})
651+
// Binding a reference to a packed type is possibly unsafe.
652+
.map(|ty| ty.is_packed(self.db))
653+
.unwrap_or(false)
654+
}
643655
}
644656

645657
pub trait ToDef: AstNode + Clone {

0 commit comments

Comments
 (0)