Skip to content

Commit 90086de

Browse files
committed
feat(mir): add Path expression kind
1 parent 051c23b commit 90086de

3 files changed

Lines changed: 71 additions & 3 deletions

File tree

src/ir/hir.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ mod expression {
183183
Unreachable,
184184
Aggregate(Aggregate),
185185
Field(Field),
186+
Path(Path),
186187
}
187188

188189
#[derive(Clone, Debug)]
@@ -247,6 +248,18 @@ mod expression {
247248
pub field: usize,
248249
}
249250

251+
/// A qualified path to a trait with an item.
252+
///
253+
/// ```
254+
/// <Ty as TargetTrait>::item
255+
/// ```
256+
#[derive(Clone, Debug)]
257+
pub struct Path {
258+
pub ty: TypeId,
259+
pub target_trait: TraitId,
260+
pub item: TraitMethodId,
261+
}
262+
250263
enum_conversion! {
251264
[Expression]
252265
Assign: Assign,
@@ -260,6 +273,7 @@ mod expression {
260273
Variable: Variable,
261274
Aggregate: Aggregate,
262275
Field: Field,
276+
Path: Path,
263277
}
264278
}
265279

src/passes/hir_gen.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,34 @@ impl<'ctx, 'ast> HirGen<'ctx, 'ast> {
435435
},
436436
}
437437
.into(),
438-
ast::Expression::QualifiedPath(ast::QualifiedPath { .. }) => {
439-
todo!()
438+
ast::Expression::QualifiedPath(ast::QualifiedPath { ty, name, item }) => {
439+
let trait_name = self.ctx.scopes.resolve_global(*name);
440+
let (trait_id, target_trait) = self
441+
.hir
442+
.traits
443+
.iter_pairs()
444+
.find(|&(_, t)| t.name == trait_name)
445+
.expect("trait must exist");
446+
let item_binding = self.ctx.scopes.resolve(target_trait.method_scope, *item);
447+
let item = *target_trait
448+
.method_bindings
449+
.get(&item_binding)
450+
.expect("valid method on trait");
451+
452+
Path {
453+
ty: {
454+
let ty = self.lower_ast_type(*ty);
455+
match ctx.current_self() {
456+
Some(current_self) => ty.with_self(current_self),
457+
None => ty
458+
.without_self()
459+
.expect("`Self` cannot be used in this context"),
460+
}
461+
},
462+
target_trait: trait_id,
463+
item,
464+
}
465+
.into()
440466
}
441467
};
442468

src/passes/mir_gen.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::prelude::*;
1+
use crate::{ir::hir::TraitImplementationKey, prelude::*};
22

33
use mir::{UnaryOperation, *};
44
use thir::Thir;
@@ -596,6 +596,34 @@ impl<'ctx, 'hir, 'thir> MirGen<'ctx, 'hir, 'thir> {
596596
let place = self.mir.places.insert(lhs);
597597
Some(self.mir.operands.insert(Operand::Place(place)))
598598
}
599+
hir::Expression::Path(hir::Path {
600+
ty,
601+
target_trait,
602+
item,
603+
}) => {
604+
// Look up the trait implementation.
605+
let trait_implementation = &self.thir[&TraitImplementationKey {
606+
trait_id: *target_trait,
607+
ty: *ty,
608+
}];
609+
610+
// Look up the function ID corresponding with the method ID.
611+
let thir_function_id = trait_implementation.methods[*item];
612+
613+
// Map from THIR function to MIR function.
614+
let (function_id, _) = self
615+
.function_ids
616+
.iter_pairs()
617+
.find(|(_, id)| **id == thir_function_id)
618+
.expect("function to exist");
619+
620+
// Insert constant resolving to the function.
621+
Some(
622+
self.mir
623+
.operands
624+
.insert(Operand::Constant(Constant::Function(function_id))),
625+
)
626+
}
599627
}
600628
}
601629

0 commit comments

Comments
 (0)