33//! Places represent storage locations in the MIR, including local variables and complex paths
44//! through data structures. Projections allow accessing nested data within structured types.
55
6- use core:: { alloc:: Allocator , fmt} ;
6+ use alloc:: { alloc:: Global , collections:: VecDeque } ;
7+ use core:: {
8+ alloc:: Allocator ,
9+ fmt,
10+ hash:: { Hash , Hasher } ,
11+ } ;
712
813use hashql_core:: { id, intern:: Interned , symbol:: Symbol , r#type:: TypeId } ;
914
@@ -210,6 +215,7 @@ pub enum DefUse {
210215/// For a place like `local_0.field_1.field_2`:
211216/// - At projection 0: `PlaceRef { local: local_0, projections: [] }`
212217/// - At projection 1: `PlaceRef { local: local_0, projections: [field_1] }`
218+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
213219pub struct PlaceRef < ' proj , ' heap > {
214220 /// The root local variable that this place reference starts from.
215221 pub local : Local ,
@@ -221,6 +227,52 @@ pub struct PlaceRef<'proj, 'heap> {
221227 pub projections : & ' proj [ Projection < ' heap > ] ,
222228}
223229
230+ impl < ' heap > PlaceRef < ' _ , ' heap > {
231+ /// Interns the borrowed projection slice and returns an owned [`Place`].
232+ ///
233+ /// Converts this borrowed reference into an interned place suitable for storage in MIR.
234+ pub fn intern ( & self , interner : & Interner < ' heap > ) -> Place < ' heap > {
235+ Place {
236+ local : self . local ,
237+ projections : interner. projections . intern_slice ( self . projections ) ,
238+ }
239+ }
240+ }
241+
242+ /// An intermediate place representation used during dependency resolution.
243+ ///
244+ /// Represents a partially-resolved place where the projection sequence may still grow
245+ /// as resolution traverses through the dependency graph. Convert to [`Place`] via
246+ /// [`PlaceRef::intern`] once resolution completes.
247+ #[ derive( Debug , Clone ) ]
248+ pub struct PlaceMut < ' heap , A : Allocator = Global > {
249+ /// The current root local after partial resolution.
250+ pub local : Local ,
251+
252+ /// Accumulated projections that could not yet be resolved.
253+ ///
254+ /// During resolution, projections are prepended from edge targets and appended
255+ /// from the original place being resolved.
256+ pub projections : VecDeque < Projection < ' heap > , A > ,
257+ }
258+
259+ impl < A : Allocator > PartialEq for PlaceMut < ' _ , A > {
260+ fn eq ( & self , other : & Self ) -> bool {
261+ let Self { local, projections } = self ;
262+
263+ * local == other. local && * projections == other. projections
264+ }
265+ }
266+
267+ impl < A : Allocator > Eq for PlaceMut < ' _ , A > { }
268+
269+ impl < A : Allocator > Hash for PlaceMut < ' _ , A > {
270+ fn hash < H : Hasher > ( & self , state : & mut H ) {
271+ self . local . hash ( state) ;
272+ self . projections . hash ( state) ;
273+ }
274+ }
275+
224276/// A storage location that can be read from or written to in the MIR.
225277///
226278/// A [`Place`] represents a path to a storage location, starting from a [`Local`] variable and
@@ -331,6 +383,15 @@ impl<'heap> Place<'heap> {
331383 . last ( )
332384 . map_or_else ( || decl[ self . local ] . r#type , |projection| projection. r#type )
333385 }
386+
387+ /// Returns a borrowed reference to this place.
388+ #[ must_use]
389+ pub const fn as_ref ( & self ) -> PlaceRef < ' heap , ' heap > {
390+ PlaceRef {
391+ local : self . local ,
392+ projections : self . projections . 0 ,
393+ }
394+ }
334395}
335396
336397/// A single projection step that navigates into structured data, carrying its result type.
0 commit comments