Skip to content

Commit 58003af

Browse files
committed
Implement offset_of in hir-def and hir-ty
1 parent 9b8eb80 commit 58003af

File tree

15 files changed

+78
-109
lines changed

15 files changed

+78
-109
lines changed

crates/hir-def/src/body/lower.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
hir::{
3232
dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy,
3333
ClosureKind, Expr, ExprId, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability,
34-
Pat, PatId, RecordFieldPat, RecordLitField, Statement,
34+
OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
3535
},
3636
item_scope::BuiltinShadowMode,
3737
lang_item::LangItem,
@@ -649,7 +649,11 @@ impl ExprCollector<'_> {
649649
}
650650
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
651651
ast::Expr::AsmExpr(_) => self.missing_expr(),
652-
ast::Expr::OffsetOfExpr(_) => self.missing_expr(),
652+
ast::Expr::OffsetOfExpr(e) => {
653+
let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
654+
let fields = e.fields().map(|it| it.as_name()).collect();
655+
self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
656+
}
653657
ast::Expr::FormatArgsExpr(_) => self.missing_expr(),
654658
})
655659
}

crates/hir-def/src/body/pretty.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::fmt::{self, Write};
44

55
use hir_expand::db::ExpandDatabase;
6+
use itertools::Itertools;
67
use syntax::ast::HasName;
78

89
use crate::{
@@ -154,6 +155,15 @@ impl Printer<'_> {
154155
match expr {
155156
Expr::Missing => w!(self, "�"),
156157
Expr::Underscore => w!(self, "_"),
158+
Expr::OffsetOf(offset_of) => {
159+
w!(self, "builtin#offset_of!(");
160+
self.print_type_ref(&offset_of.container);
161+
w!(
162+
self,
163+
", {})",
164+
offset_of.fields.iter().format_with(".", |field, f| f(&field.display(self.db)))
165+
);
166+
}
157167
Expr::Path(path) => self.print_path(path),
158168
Expr::If { condition, then_branch, else_branch } => {
159169
w!(self, "if ");

crates/hir-def/src/hir.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,13 @@ pub enum Expr {
281281
Array(Array),
282282
Literal(Literal),
283283
Underscore,
284+
OffsetOf(OffsetOf),
285+
}
286+
287+
#[derive(Debug, Clone, PartialEq, Eq)]
288+
pub struct OffsetOf {
289+
pub container: Interned<TypeRef>,
290+
pub fields: Box<[Name]>,
284291
}
285292

286293
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -341,7 +348,7 @@ impl Expr {
341348
pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
342349
match self {
343350
Expr::Missing => {}
344-
Expr::Path(_) => {}
351+
Expr::Path(_) | Expr::OffsetOf(_) => {}
345352
Expr::If { condition, then_branch, else_branch } => {
346353
f(*condition);
347354
f(*then_branch);

crates/hir-ty/src/infer/closure.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ impl InferenceContext<'_> {
452452

453453
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
454454
match &self.body[tgt_expr] {
455+
Expr::OffsetOf(_) => (),
455456
Expr::If { condition, then_branch, else_branch } => {
456457
self.consume_expr(*condition);
457458
self.consume_expr(*then_branch);

crates/hir-ty/src/infer/expr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,7 @@ impl InferenceContext<'_> {
843843
});
844844
expected
845845
}
846+
Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
846847
};
847848
// use a new type variable if we got unknown here
848849
let ty = self.insert_type_vars_shallow(ty);

crates/hir-ty/src/infer/mutability.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl InferenceContext<'_> {
3535
fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutability) {
3636
match &self.body[tgt_expr] {
3737
Expr::Missing => (),
38+
Expr::OffsetOf(_) => (),
3839
&Expr::If { condition, then_branch, else_branch } => {
3940
self.infer_mut_expr(condition, Mutability::Not);
4041
self.infer_mut_expr(then_branch, Mutability::Not);

crates/hir-ty/src/mir/lower.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
370370
mut current: BasicBlockId,
371371
) -> Result<Option<BasicBlockId>> {
372372
match &self.body.exprs[expr_id] {
373+
Expr::OffsetOf(_) => not_supported!("builtin#offset_of"),
373374
Expr::Missing => {
374375
if let DefWithBodyId::FunctionId(f) = self.owner {
375376
let assoc = f.lookup(self.db.upcast());

crates/hir-ty/src/tests/simple.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,3 +3649,15 @@ fn main() {
36493649
"#,
36503650
);
36513651
}
3652+
3653+
#[test]
3654+
fn offset_of() {
3655+
check_types(
3656+
r#"
3657+
fn main() {
3658+
builtin#offset_of((,), 0);
3659+
// ^^^^^^^^^^^^^^^^^^^^^^^^^ usize
3660+
}
3661+
"#,
3662+
);
3663+
}

crates/parser/src/grammar/expressions/atom.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,24 +220,39 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
220220
// fn foo() {
221221
// builtin#asm(0);
222222
// builtin#format_args(0);
223-
// builtin#builtin(0);
223+
// builtin#offset_of(Foo, bar.baz.0);
224224
// }
225225
fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
226226
let m = p.start();
227227
p.bump_remap(T![builtin]);
228228
p.bump(T![#]);
229229
if p.at_contextual_kw(T![offset_of]) {
230+
p.bump_remap(T![offset_of]);
230231
p.expect(T!['(']);
231232
type_(p);
232-
p.bump(T![,]);
233+
p.expect(T![,]);
234+
while !p.at(EOF) && !p.at(T![')']) {
235+
if p.at(IDENT) || p.at(INT_NUMBER) {
236+
name_ref_or_index(p);
237+
// } else if p.at(FLOAT_NUMBER) {
238+
// FIXME: needs float hack
239+
} else {
240+
p.err_and_bump("expected field name or number");
241+
}
242+
if !p.at(T![')']) {
243+
p.expect(T![.]);
244+
}
245+
}
233246
p.expect(T![')']);
234247
Some(m.complete(p, OFFSET_OF_EXPR))
235248
} else if p.at_contextual_kw(T![format_args]) {
249+
p.bump_remap(T![format_args]);
236250
p.expect(T!['(']);
237251
expr(p);
238252
p.expect(T![')']);
239253
Some(m.complete(p, FORMAT_ARGS_EXPR))
240254
} else if p.at_contextual_kw(T![asm]) {
255+
p.bump_remap(T![asm]);
241256
p.expect(T!['(']);
242257
expr(p);
243258
p.expect(T![')']);

crates/parser/test_data/parser/inline/ok/0132_box_expr.rast

Lines changed: 0 additions & 90 deletions
This file was deleted.

0 commit comments

Comments
 (0)