### Example Searches Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.ExprId_search= Provides examples of search queries that can be used within the Solar Sema environment for finding types, functions, and patterns. ```APIDOC ## Example Searches ### Description This section provides common search patterns and examples for using the search functionality within the Solar Sema project. These examples demonstrate how to query for specific types, function signatures, and generic patterns. ### Method Not Applicable (Search examples) ### Endpoint Not Applicable (Search examples) ### Parameters None ### Request Example ```text Example searches: * std::vec * u32 -> bool * Option, (T -> U) -> Option ``` ### Response No direct response, as these are examples of search queries. ``` -------------------------------- ### Example Search Queries Source: https://docs.rs/solar-sema/latest/solar_sema/builtins/enum.Builtin_search= Demonstrates common search query patterns. These examples illustrate how to search for standard library components, type signatures, and generic type transformations. ```plaintext * std::vec * u32 -> bool * Option, (T -> U) -> Option ``` -------------------------------- ### Rust Example Searches: Common Type and Pattern Queries Source: https://docs.rs/solar-sema/latest/solar_sema/eval/enum.EvalErrorKind_search= Provides example searches demonstrating common query patterns for Rust types and functionalities. These examples cover standard library collections like `std::vec`, primitive type conversions like `u32 -> bool`, and functional transformations on optional types such as `Option, (T -> U) -> Option`. ```rust std::vec ``` ```rust u32 -> bool ``` ```rust Option, (T -> U) -> Option ``` -------------------------------- ### Closure-Based Object Allocation Example in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=std%3A%3Avec Shows how to use `alloc_with` with a closure to allocate and initialize an object in `bumpalo::Bump`. The example allocates a string literal created by the closure and verifies its content. ```rust let bump = bumpalo::Bump::new(); let x = bump.alloc_with(|| "hello"); assert_eq!(*x, "hello"); ``` -------------------------------- ### Direct Object Allocation Example in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=std%3A%3Avec Illustrates the basic usage of the `alloc` method for `bumpalo::Bump`. A string literal is allocated, and the example asserts that the returned reference points to the correct value. ```rust let bump = bumpalo::Bump::new(); let x = bump.alloc("hello"); assert_eq!(*x, "hello"); ``` -------------------------------- ### Rust: Bump Allocator Allocation Limit Example Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to set and query the allocation limit of a Bump arena, including examples of when allocations might fail due to the limit. ```rust let bump = bumpalo::Bump::with_capacity(0); assert_eq!(bump.allocation_limit(), None); bump.set_allocation_limit(Some(6)); assert_eq!(bump.allocation_limit(), Some(6)); bump.set_allocation_limit(None); assert_eq!(bump.allocation_limit(), None); bump.set_allocation_limit(Some(0)); assert!(bump.try_alloc(5).is_err()); ``` -------------------------------- ### Example: Compiling a Solidity File - Rust Source: https://docs.rs/solar-sema/latest/solar_sema/struct.Compiler Demonstrates a full workflow of using the `Compiler` struct in Rust. This example shows how to initialize a session, create a compiler, parse a Solidity file, load its contents, perform AST lowering, and inspect the resulting High-Level Intermediate Representation (HIR). It also includes error handling for diagnostics. ```rust use solar::{ interface::{Session, diagnostics::EmittedDiagnostics}, sema::Compiler, }; use std::{ops::ControlFlow, path::Path}; #[test] fn main() -> Result<(), EmittedDiagnostics> { let paths = [Path::new("src/AnotherCounter.sol")]; let sess = Session::builder().with_buffer_emitter(solar::interface::ColorChoice::Auto).build(); let mut compiler = Compiler::new(sess); let _ = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { let mut parsing_context = compiler.parse(); parsing_context.load_files(paths)?; parsing_context.parse(); Ok(()) }); let contracts = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { let ControlFlow::Continue(()) = compiler.lower_asts()? else { return Ok(vec![]); }; let gcx = compiler.gcx(); let contracts = gcx.hir.contracts().map(|c| c.name.to_string()).collect::>(); Ok(contracts) }); if let Ok(mut contracts) = contracts { contracts.sort(); assert_eq!(contracts, ["AnotherCounter".to_string(), "Counter".to_string()]); } compiler.sess().emitted_errors().unwrap() } ``` -------------------------------- ### Fallible Initialization Allocation Example in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=std%3A%3Avec Demonstrates `alloc_try_with` for allocating an object that might fail during initialization. The example shows a successful allocation where the closure returns `Ok`, and asserts the content of the allocated string. ```rust let bump = bumpalo::Bump::new(); let x = bump.alloc_try_with(|| Ok("hello"))?; assert_eq!(*x, "hello"); ``` -------------------------------- ### Rust: Example Usage of ParsingContext Source: https://docs.rs/solar-sema/latest/src/solar_sema/parse.rs Demonstrates how to use the `ParsingContext` within a compiler workflow. The example shows creating a compiler, entering a mutable context, initializing a parser, setting options like disabling import resolution, loading source code from stdin, and initiating the parsing process. ```rust /// Builder for parsing sources into a [`Compiler`](crate::Compiler). /// /// Created from [`CompilerRef::parse`](crate::CompilerRef::parse). /// /// # Examples /// /// ``` /// # let mut compiler = solar_sema::Compiler::new(solar_interface::Session::builder().with_stderr_emitter().build()); /// compiler.enter_mut(|compiler| { /// let mut pcx = compiler.parse(); /// pcx.set_resolve_imports(false); /// pcx.load_stdin(); /// pcx.parse(); /// }); /// ``` ``` -------------------------------- ### Example Usage of ParsingContext in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/struct.ParsingContext_search= Demonstrates how to use the ParsingContext to control parsing behavior. This example shows creating a parsing context, disabling import resolution, loading standard input, and then performing the parse operation. ```rust compiler.enter_mut(|compiler| { let mut pcx = compiler.parse(); pcx.set_resolve_imports(false); pcx.load_stdin(); pcx.parse(); }); ``` -------------------------------- ### Rust: Compiler Struct Definition and Usage Example Source: https://docs.rs/solar-sema/latest/solar_sema/struct.Compiler_search=std%3A%3Avec Defines the main Compiler struct for the solar-sema compiler and provides a comprehensive example of its usage in Rust. This includes initializing the compiler, parsing Solidity files, lowering ASTs, and inspecting the resulting High-Level Intermediate Representation (HIR). The example demonstrates the use of `enter_mut` for operations requiring mutable access and `enter` for subsequent read-only operations, highlighting error handling and context management. ```rust pub struct Compiler(/* private fields */); #[test] fn main() -> Result<(), EmittedDiagnostics> { let paths = [Path::new("src/AnotherCounter.sol")]; // Create a new session with a buffer emitter. // This is required to capture the emitted diagnostics and to return them at the end. let sess = Session::builder().with_buffer_emitter(solar::interface::ColorChoice::Auto).build(); // Create a new compiler. let mut compiler = Compiler::new(sess); // Enter the context and parse the file. // Counter will be parsed, even if not explicitly provided, since it is a dependency. let _ = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { // Parse the files. let mut parsing_context = compiler.parse(); parsing_context.load_files(paths)?; parsing_context.parse(); Ok(()) }); // Do some other stuff, store the compiler in a struct... // Enter the context again and lower the ASTs to inspect the HIR. let contracts = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { // Perform AST lowering to populate the HIR. let ControlFlow::Continue(()) = compiler.lower_asts()? else { // Can't continue because HIR was not populated, // possibly because it was requested in `Session` with `stop_after`. return Ok(vec![]); }; // Inspect the HIR. let gcx = compiler.gcx(); let contracts = gcx.hir.contracts().map(|c| c.name.to_string()).collect::>(); Ok(contracts) }); if let Ok(mut contracts) = contracts { // No order is guaranteed. contracts.sort(); assert_eq!(contracts, ["AnotherCounter".to_string(), "Counter".to_string()]); } // `compiler` can be entered again to perform analysis, type checking, etc, without needing // mutable access, since `gcx` is the main context that is passed by immutable reference. // Return the emitted diagnostics as a `Result<(), _>`. // If any errors were emitted, this returns `Err(_)`, otherwise `Ok(())`. // Note that this discards warnings and other non-error diagnostics. compiler.sess().emitted_errors().unwrap() } ``` -------------------------------- ### Bump Allocator Allocation Limit Example in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=std%3A%3Avec Demonstrates how to set and retrieve the allocation limit for a `bumpalo::Bump` instance. The example shows setting the limit to `None` and to a specific byte value, and verifies the behavior with `allocation_limit()` and `set_allocation_limit()`. ```rust let bump = bumpalo::Bump::with_capacity(0); assert_eq!(bump.allocation_limit(), None); bump.set_allocation_limit(Some(6)); assert_eq!(bump.allocation_limit(), Some(6)); bump.set_allocation_limit(None); assert_eq!(bump.allocation_limit(), None); ``` -------------------------------- ### Fallible Closure-Based Object Allocation Example in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=std%3A%3Avec Illustrates the use of `try_alloc_with` with a closure for allocating objects in `bumpalo::Bump`. The example demonstrates a successful allocation of a string literal and asserts the `Ok` result. ```rust let bump = bumpalo::Bump::new(); let x = bump.try_alloc_with(|| "hello"); assert_eq!(x, Ok(&mut "hello")); ``` -------------------------------- ### Solidity Getter Function Generation Example Source: https://docs.rs/solar-sema/latest/src/solar_sema/ast_lowering/resolve.rs_search=u32+-%3E+bool This example demonstrates how Solidity getter functions are generated for state variables, including mappings and structs. It shows the mapping from a storage variable to its corresponding getter function signature and body. ```solidity mapping(string k => bool[] v) public map; // Generates: function map(string calldata k, uint256 index1) public view returns(bool) { return map[k][index1]; } ``` Special case for when the return type is a struct. Note that `mapping` fields are skipped: ```solidity struct Struct { uint256 field1; mapping(uint256 => bool) field2; bool field3; } mapping(string k => Struct[] v) public mapWithStruct; // Generates: function mapWithStruct(string calldata k, uint256 index1) public view returns(uint256 field1, bool field3) { Struct storage tmp = map[k][index1]; return (tmp.field1, tmp.field3); } ``` ``` -------------------------------- ### iter() - Get Slice Iterator Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Block_search=u32+-%3E+bool Returns an iterator over the elements of the slice, yielding items from start to end. ```APIDOC ## pub fn iter(&self) -> Iter<'_, T> ### Description Returns an iterator that yields references to the elements of the slice in order, from the first element to the last. ### Method `iter` ### Endpoint N/A (Method on a slice object) ### Parameters N/A ### Request Example ```rust let x = &[1, 2, 4]; let mut iterator = x.iter(); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), Some(&4)); assert_eq!(iterator.next(), None); ``` ### Response #### Success Response - `Iter<'_, T>`: An iterator yielding references (`&T`) to the slice elements. ``` -------------------------------- ### Rust Compiler Example: Parsing and Lowering Files Source: https://docs.rs/solar-sema/latest/solar_sema/struct.Compiler_search= Demonstrates how to use the `Compiler` struct to parse and lower Solidity files. This example shows initializing the compiler with a session, loading files, parsing them, and then lowering the Abstract Syntax Trees (ASTs) to High-Level Intermediate Representation (HIR). It also includes error handling and verification of contract names. ```rust use solar:: interface::{Session, diagnostics::EmittedDiagnostics}, sema::Compiler; use std::{ops::ControlFlow, path::Path}; #[test] fn main() -> Result<(), EmittedDiagnostics> { let paths = [Path::new("src/AnotherCounter.sol")]; // Create a new session with a buffer emitter. // This is required to capture the emitted diagnostics and to return them at the end. let sess = Session::builder().with_buffer_emitter(solar::interface::ColorChoice::Auto).build(); // Create a new compiler. let mut compiler = Compiler::new(sess); // Enter the context and parse the file. // Counter will be parsed, even if not explicitly provided, since it is a dependency. let _ = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { // Parse the files. let mut parsing_context = compiler.parse(); parsing_context.load_files(paths)?; parsing_context.parse(); Ok(()) }); // Do some other stuff, store the compiler in a struct... // Enter the context again and lower the ASTs to inspect the HIR. let contracts = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { // Perform AST lowering to populate the HIR. let ControlFlow::Continue(()) = compiler.lower_asts()? else { // Can't continue because HIR was not populated, // possibly because it was requested in `Session` with `stop_after`. return Ok(vec![]); }; // Inspect the HIR. let gcx = compiler.gcx(); let contracts = gcx.hir.contracts().map(|c| c.name.to_string()).collect::>(); Ok(contracts) }); if let Ok(mut contracts) = contracts { // No order is guaranteed. contracts.sort(); assert_eq!(contracts, ["AnotherCounter".to_string(), "Counter".to_string()]); } // `compiler` can be entered again to perform analysis, type checking, etc, without needing // mutable access, since `gcx` is the main context that is passed by immutable reference. // Return the emitted diagnostics as a `Result<(), _>`. // If any errors were emitted, this returns `Err(_)`, otherwise `Ok(())`. // Note that this discards warnings and other non-error diagnostics. compiler.sess().emitted_errors().unwrap() } ``` -------------------------------- ### GET /websites/rs_solar-sema/chunks Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Returns an iterator over elements of the slice in chunks of a specified size, starting from the beginning. The last chunk may be smaller if the size does not divide the slice length evenly. ```APIDOC ## GET /websites/rs_solar-sema/chunks ### Description Returns an iterator over `chunk_size` elements of the slice at a time, starting at the beginning of the slice. The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the slice, then the last chunk will not have length `chunk_size`. ### Method GET ### Endpoint /websites/rs_solar-sema/chunks ### Parameters #### Query Parameters - **chunk_size** (usize) - Required - The desired size of each chunk. ### Response #### Success Response (200) - **iterator** (Chunks<'_, T>) - An iterator yielding slices of the original data. #### Response Example ```json { "iterator": "..." } ``` ##### §Panics Panics if `chunk_size` is zero. ##### §Examples ```rust let slice = ['l', 'o', 'r', 'e', 'm']; let mut iter = slice.chunks(2); assert_eq!(iter.next().unwrap(), &['l', 'o']); assert_eq!(iter.next().unwrap(), &['r', 'e']); assert_eq!(iter.next().unwrap(), &['m']); assert!(iter.next().is_none()); ``` ``` -------------------------------- ### Rust: Get Last Slice Element using last() Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Block_search= Provides an example of accessing the last element of a slice using `last()`. Returns `None` if the slice is empty, ensuring safe access. ```rust let v = [10, 40, 30]; assert_eq!(Some(&30), v.last()); let w: &[i32] = &[]; assert_eq!(None, w.last()); ``` -------------------------------- ### GET /websites/rs_solar-sema/chunks_exact Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Returns an iterator over elements of the slice in chunks of a specified size, starting from the beginning. This iterator only yields chunks of exactly the specified size, and any remaining elements can be accessed separately. ```APIDOC ## GET /websites/rs_solar-sema/chunks_exact ### Description Returns an iterator over `chunk_size` elements of the slice at a time, starting at the beginning of the slice. The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the slice, then the last up to `chunk_size-1` elements will be omitted and can be retrieved from the `remainder` function of the iterator. ### Method GET ### Endpoint /websites/rs_solar-sema/chunks_exact ### Parameters #### Query Parameters - **chunk_size** (usize) - Required - The desired size of each chunk. ### Response #### Success Response (200) - **iterator** (ChunksExact<'_, T>) - An iterator yielding slices of exactly `chunk_size` elements. - **remainder** (T[]) - A slice containing the remaining elements that did not form a full chunk. #### Response Example ```json { "iterator": "...", "remainder": "..." } ``` ##### §Panics Panics if `chunk_size` is zero. ##### §Examples ```rust let slice = ['l', 'o', 'r', 'e', 'm']; let mut iter = slice.chunks_exact(2); assert_eq!(iter.next().unwrap(), &['l', 'o']); assert_eq!(iter.next().unwrap(), &['r', 'e']); assert!(iter.next().is_none()); assert_eq!(iter.remainder(), &['m']); ``` ``` -------------------------------- ### Rust: Initialize and Run Compiler Stages Source: https://docs.rs/solar-sema/latest/src/solar_sema/lib.rs_search=std%3A%3Avec This snippet demonstrates the initialization of the compiler and the execution of its various stages, such as lowering and analysis. It handles early exits for specific language targets (Yul) and checks for compilation errors. ```Rust #![doc = include_str!("../README.md")] #![doc( html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/solar/main/assets/logo.png", html_favicon_url = "https://raw.githubusercontent.com/paradigmxyz/solar/main/assets/favicon.ico" )] #![cfg_attr(feature = "nightly", feature(rustc_attrs), allow(internal_features))] #![cfg_attr(docsrs, feature(doc_cfg))] #[macro_use] extern crate tracing; use rayon::prelude::*; use solar_interface::{Result, Session, config::CompilerStage}; use std::ops::ControlFlow; // Convenience re-exports. pub use ::thread_local; pub use bumpalo; pub use solar_interface as interface; mod ast_lowering; mod ast_passes; mod compiler; pub use compiler::{Compiler, CompilerRef}; mod parse; pub use parse::{ParsingContext, Source, Sources}; pub mod builtins; pub mod eval; pub mod hir; pub use hir::Hir; pub mod ty; pub use ty::{Gcx, Ty}; mod typeck; mod emit; pub mod stats; mod span_visitor; pub(crate) fn lower(compiler: &mut CompilerRef<'_>) -> Result> { let gcx = compiler.gcx(); let sess = gcx.sess; if gcx.sources.is_empty() { let msg = "no files found"; let note = "if you wish to use the standard input, please specify `-` explicitly"; return Err(sess.dcx.err(msg).note(note).emit()); } if let Some(dump) = &sess.opts.unstable.dump && dump.kind.is_ast() { dump_ast(sess, &gcx.sources, dump.paths.as_deref())?; } if sess.opts.unstable.ast_stats { for source in gcx.sources.asts() { stats::print_ast_stats(source, "AST STATS", "ast-stats"); } } if sess.opts.unstable.span_visitor { use crate::span_visitor::SpanVisitor; use ast::visit::Visit; for source in gcx.sources.asts() { let mut visitor = SpanVisitor::new(sess); let _ = visitor.visit_source_unit(source); debug!(spans_visited = visitor.count(), "span visitor completed"); } } if sess.opts.language.is_yul() || gcx.advance_stage(CompilerStage::Lowering).is_break() { return Ok(ControlFlow::Break(())); } compiler.gcx_mut().sources.topo_sort(); debug_span!("all_ast_passes").in_scope(|| { gcx.sources.par_asts().for_each(|ast| { ast_passes::run(gcx.sess, ast); }); }); gcx.sess.dcx.has_errors()?; ast_lowering::lower(compiler.gcx_mut()); Ok(ControlFlow::Continue(())) } #[instrument(level = "debug", skip_all)] fn analysis(gcx: Gcx<'_>) -> Result> { if let ControlFlow::Break(()) = gcx.advance_stage(CompilerStage::Analysis) { return Ok(ControlFlow::Break(())); } if let Some(dump) = &gcx.sess.opts.unstable.dump && dump.kind.is_hir() { dump_hir(gcx, dump.paths.as_deref())?; } // Lower HIR types. gcx.hir.par_item_ids().for_each(|id| { let _ = gcx.type_of_item(id); match id { hir::ItemId::Struct(id) => _ = gcx.struct_field_types(id), hir::ItemId::Contract(id) => _ = gcx.interface_functions(id), _ => {} } }); gcx.sess.dcx.has_errors()?; typeck::check(gcx); gcx.sess.dcx.has_errors()?; if !gcx.sess.opts.emit.is_empty() { emit::emit(gcx); gcx.sess.dcx.has_errors()?; } Ok(ControlFlow::Continue(())) } ``` -------------------------------- ### Get Remaining Chunk Capacity - Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search= Retrieves the remaining capacity in bytes within the current memory chunk. This is useful for understanding how much more can be allocated before a new chunk is needed. Example demonstrates checking initial capacity. ```rust pub fn chunk_capacity(&self) -> usize ```rust use bumpalo::Bump; let bump = Bump::with_capacity(100); let capacity = bump.chunk_capacity(); assert!(capacity >= 100); ``` ``` -------------------------------- ### Get First Chunk of InterfaceFunctions Slice in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search= Explains the `first_chunk` method, inherited from slices. It attempts to return a reference to an array of `N` items from the beginning of the slice. Returns `None` if the slice is shorter than `N`. Useful for fixed-size processing at the start. ```rust pub fn first_chunk(&self) -> Option<&[T; N]> Returns an array reference to the first `N` items in the slice. If the slice is not at least `N` in length, this will return `None`. ##### §Examples ``` let u = [10, 40, 30]; assert_eq!(Some(&[10, 40]), u.first_chunk::<2>()); let v: &[i32] = &[10]; assert_eq!(None, v.first_chunk::<2>()); let w: &[i32] = &[]; assert_eq!(Some(&[]), w.first_chunk::<0>()); ``` ``` -------------------------------- ### Rust: Bump Allocator Alignment Example Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates how to set and verify the minimum alignment for allocations within a Bump arena using `with_min_align` and `min_align`. ```rust let bump2 = bumpalo::Bump::<2>::with_min_align(); assert_eq!(bump2.min_align(), 2); let bump4 = bumpalo::Bump::<4>::with_min_align(); assert_eq!(bump4.min_align(), 4); ``` -------------------------------- ### Get Element Offset in Rust Slice (Nightly) Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Block_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E The `element_offset` method (nightly-only) returns the index of an element within a slice based on its memory address, not its value. It returns `None` if the element reference is not aligned with the start of an element in the slice. This method uses pointer arithmetic and is useful for extending slice iterators, but it panics if `T` is zero-sized. For index-based searching, `.iter().position()` should be used. ```rust #![feature(substr_range)] let nums: &[u32] = &[1, 7, 1, 1]; let num = &nums[2]; assert_eq!(num, &1); assert_eq!(nums.element_offset(num), Some(2)); let arr: &[[u32; 2]] = &[[0, 1], [2, 3]]; let flat_arr: &[u32] = arr.as_flattened(); let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap(); let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap(); assert_eq!(ok_elm, &[0, 1]); assert_eq!(weird_elm, &[1, 2]); assert_eq!(arr.element_offset(ok_elm), Some(0)); // Points to element 0 assert_eq!(arr.element_offset(weird_elm), None); // Points between element 0 and 1 ``` -------------------------------- ### Rust: Initialize and Use Compiler for Parsing Source: https://docs.rs/solar-sema/latest/solar_sema/struct.Compiler_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates how to initialize the `Compiler` with a `Session`, load Solidity files, parse them, and then lower the Abstract Syntax Tree (AST) to the High-Level Intermediate Representation (HIR). This snippet highlights the use of `enter_mut` for operations requiring mutable compiler access and `gcx` for immutable access to compiler internals. ```rust use solar::{ interface::{Session, diagnostics::EmittedDiagnostics}, sema::Compiler, }; use std::{ops::ControlFlow, path::Path}; #[test] fn main() -> Result<(), EmittedDiagnostics> { let paths = [Path::new("src/AnotherCounter.sol")]; // Create a new session with a buffer emitter. // This is required to capture the emitted diagnostics and to return them at the end. let sess = Session::builder().with_buffer_emitter(solar::interface::ColorChoice::Auto).build(); // Create a new compiler. let mut compiler = Compiler::new(sess); // Enter the context and parse the file. // Counter will be parsed, even if not explicitly provided, since it is a dependency. let _ = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { // Parse the files. let mut parsing_context = compiler.parse(); parsing_context.load_files(paths)?; parsing_context.parse(); Ok(()) }); // Do some other stuff, store the compiler in a struct... // Enter the context again and lower the ASTs to inspect the HIR. let contracts = compiler.enter_mut(|compiler| -> solar::interface::Result<_> { // Perform AST lowering to populate the HIR. let ControlFlow::Continue(()) = compiler.lower_asts()? else { // Can't continue because HIR was not populated, // possibly because it was requested in `Session` with `stop_after`. return Ok(vec![]); }; // Inspect the HIR. let gcx = compiler.gcx(); let contracts = gcx.hir.contracts().map(|c| c.name.to_string()).collect::>(); Ok(contracts) }); if let Ok(mut contracts) = contracts { // No order is guaranteed. contracts.sort(); assert_eq!(contracts, ["AnotherCounter".to_string(), "Counter".to_string()]); } // `compiler` can be entered again to perform analysis, type checking, etc, without needing // mutable access, since `gcx` is the main context that is passed by immutable reference. // Return the emitted diagnostics as a `Result<(), _>`. // If any errors were emitted, this returns `Err(_)`, otherwise `Ok(())`. // Note that this discards warnings and other non-error diagnostics. compiler.sess().emitted_errors().unwrap() } ``` -------------------------------- ### Get Underlying Array Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search=std%3A%3Avec Attempts to get a reference to the underlying array if the slice has the specified length `N`. This is a nightly-only experimental API. ```APIDOC ## GET /slices/as_array/{N} ### Description Gets a reference to the underlying array. If `N` is not exactly equal to the length of `self`, then this method returns `None`. ### Method GET ### Endpoint `/slices/as_array/{N}` ### Parameters #### Path Parameters - **N** (usize) - Required - The expected length of the array. ### Request Example ```json { "N": 3 } ``` ### Response #### Success Response (200) - **array_ref** (&[T; N]) - An optional reference to the array if the length matches, otherwise null. #### Response Example ```json { "array_ref": [1, 2, 3] } ``` ### Note This is a nightly-only experimental API. (`slice_as_array`) ``` -------------------------------- ### Try Get As Array Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search= Attempts to get a reference to the underlying array if the slice length matches the specified size `N`. This is a nightly-only experimental API. ```APIDOC ## GET /websites/rs_solar-sema/as_array ### Description Attempts to get a reference to the underlying array. Returns `Some` if the slice length exactly matches `N`, otherwise returns `None`. ### Method GET ### Endpoint `/websites/rs_solar-sema/as_array` ### Parameters #### Query Parameters - **N** (usize) - Required - The expected length of the array. ### Request Body None ### Response #### Success Response (200) - **array_ref** (Option<&[T; N]>) - An optional reference to the array if the length matches, otherwise None. #### Response Example ```json { "array_ref": "reference_to_array_or_null" } ``` ### Note This is a nightly-only experimental API. ``` -------------------------------- ### Insertion using partition_point Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search= Demonstrates how to use `partition_point` to find the correct index for inserting an element into a sorted vector while maintaining order. ```APIDOC ## Insertion using partition_point ### Description This example shows how to efficiently insert an element into a sorted vector using `partition_point` to determine the correct insertion index, thereby maintaining the sort order. ### Method `partition_point` + `insert` ### Parameters * `vector`: The sorted vector to insert into. * `element`: The element to insert. ### Request Example ```rust let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; let num = 42; let idx = s.partition_point(|&x| x <= num); s.insert(idx, num); assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); ``` ### Response #### Success Response - The vector is modified in-place with the new element inserted at the correct position. #### Response Example ```json { "message": "Element inserted successfully", "vector_state": [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55] } ``` ``` -------------------------------- ### Rust: IdxSliceIndex for I Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.SourceId_search= Enables indexing into slices using a custom index type `I`. It provides methods for getting, getting mutably, indexing, and indexing mutably into an `IndexSlice`. ```rust impl IdxSliceIndex for I where I: Idx, { type Output = T; fn get(self, slice: &IndexSlice) -> Option<&>::Output>; fn get_mut(self, slice: &mut IndexSlice) -> Option<&mut >::Output>; fn index(self, slice: &IndexSlice) -> &>::Output; fn index_mut(self, slice: &mut IndexSlice) -> &mut >::Output; } ``` -------------------------------- ### Rust: Test Session Setup Source: https://docs.rs/solar-sema/latest/src/solar_sema/compiler.rs_search= This function sets up a test session for the compiler. It creates a `Session` with a buffer emitter (configured to never use color). It also adds a dummy source file to the source map. This is a helper function for setting up test environments. ```rust fn enter_tests_session() -> Session { let sess = Session::builder().with_buffer_emitter(ColorChoice::Never).build(); sess.source_map().new_source_file(PathBuf::from("test"), "abcd").unwrap(); sess } ``` -------------------------------- ### Check if Starts With Subslice Source: https://docs.rs/solar-sema/latest/solar_sema/struct.Sources_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Checks if the vector starts with the given subslice. This operation requires that the element type `T` implements `PartialEq`. It forwards to the slice's `starts_with` implementation. ```Rust pub fn starts_with(&self, needle: &S) -> bool where S: AsRef<[T]> + ?Sized, T: PartialEq, ``` -------------------------------- ### Rust Slice Binary Search Example Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Block_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Demonstrates the basic usage of `binary_search` on a sorted slice. It shows how to find an element, handle cases where the element is not found, and how to interpret the result for elements that may appear multiple times. ```Rust let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; assert_eq!(s.binary_search(&13), Ok(9)); assert_eq!(s.binary_search(&4), Err(7)); assert_eq!(s.binary_search(&100), Err(13)); let r = s.binary_search(&1); assert!(match r { Ok(1..=4) => true, _ => false, }); ``` -------------------------------- ### Check if Starts With (starts_with) Source: https://docs.rs/solar-sema/latest/solar_sema/struct.Sources Determines if the vector starts with the elements of a given slice. Requires `T` to implement `PartialEq`. Forwards to the slice’s `starts_with` implementation. ```Rust pub fn starts_with(&self, needle: &S) -> bool where S: AsRef<[T]> + ?Sized, T: PartialEq ``` -------------------------------- ### Rust: TyAbiPrinter Constructor and Buffer Methods Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.TyAbiPrinter Provides methods for creating a new TyAbiPrinter instance and accessing its underlying buffer. The `new` function initializes the printer with a context, writer, and mode, while `buf` and `into_buf` allow for buffer manipulation and retrieval. ```rust pub fn new(gcx: Gcx<'gcx>, buf: W, mode: TyAbiPrinterMode) -> Self pub fn buf(&mut self) -> &mut W pub fn into_buf(self) -> W ``` -------------------------------- ### Rust: Bump Allocator Allocation Example Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Arena_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Illustrates the usage of `alloc`, `try_alloc`, `alloc_with`, `try_alloc_with`, and `alloc_try_with` for allocating various types within a Bump arena. ```rust let bump = bumpalo::Bump::new(); let x = bump.alloc("hello"); assert_eq!(*x, "hello"); let x = bump.try_alloc("hello"); assert_eq!(x, Ok(&mut "hello")); let x = bump.alloc_with(|| "hello"); assert_eq!(*x, "hello"); let x = bump.try_alloc_with(|| "hello"); assert_eq!(x, Ok(&mut "hello")); let x = bump.alloc_try_with(|| Ok("hello"))?; assert_eq!(*x, "hello"); ``` -------------------------------- ### Attempt to Get Slice as Fixed-Size Array in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/ty/struct.InterfaceFunctions_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Tries to get a reference to the underlying array if its length exactly matches the specified size `N`. This is a nightly-only experimental API. ```rust let slice = [1, 2, 3]; let array_ref: Option<&[i32; 3]> = slice.as_array(); assert!(array_ref.is_some()); let short_slice = [1, 2]; let array_ref_mismatch: Option<&[i32; 3]> = short_slice.as_array(); assert!(array_ref_mismatch.is_none()); ``` -------------------------------- ### Rust Slice Binary Search Examples Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.Block_search= Demonstrates the usage of the `binary_search` method on a sorted slice to find elements. It shows how to handle found elements (Ok) and not found elements (Err), including cases where multiple identical elements exist. ```rust let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; assert_eq!(s.binary_search(&13), Ok(9)); assert_eq!(s.binary_search(&4), Err(7)); assert_eq!(s.binary_search(&100), Err(13)); let r = s.binary_search(&1); assert!(match r { Ok(1..=4) => true, _ => false, }); ``` -------------------------------- ### Manage Source Files and Topological Sort in Rust Source: https://docs.rs/solar-sema/latest/src/solar_sema/parse.rs_search=std%3A%3Avec This snippet demonstrates the process of initializing and managing source files in a Rust project. It includes adding source files, defining their imports, asserting file mapping correctness, and performing a topological sort. The code relies on the `Sources` and `PathBuf` types. ```Rust sources[aid].imports.push((ItemId::new(0), cid)); for (id, path) in &files { assert_eq!(sources[*id].file.name, FileName::Real(path.clone())); } let assert_maps = |sources: &mut Sources<'_>| { for (_, path) in &files { let file = sess.source_map().get_file(path).unwrap(); let id = sources.get_file(&file).unwrap().0; assert_eq!(sources[id].file, file); } }; assert_maps(&mut sources); sources.topo_sort(); assert_maps(&mut sources); }); } } ``` -------------------------------- ### Get Element by Index Slice in Rust Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.UdvtId_search= The `get` method provides safe access to an element within an `IndexSlice` using an index `I`. It returns `Some(&T)` if the index is valid, and `None` otherwise. ```rust fn get(self, slice: &IndexSlice) -> Option<&>::Output> ``` -------------------------------- ### Rust: IdxSliceIndex for Indexed Slices Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.ContractId_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Provides methods for indexing into a specialized `IndexSlice` type. It allows for getting, getting mutably, and indexing into slices using custom index types. ```rust impl IdxSliceIndex for I where I: Idx { type Output = T; fn get(self, slice: &IndexSlice) -> Option<&>::Output>; fn get_mut(self, slice: &mut IndexSlice) -> Option<&mut >::Output>; fn index(self, slice: &IndexSlice) -> &>::Output; fn index_mut(self, slice: &mut IndexSlice) -> &mut >::Output; } ``` -------------------------------- ### Rust: Get Contract Items with Inheritance Source: https://docs.rs/solar-sema/latest/src/solar_sema/hir/mod.rs_search= Provides an iterator over all Item objects within a contract, including inherited items. It leverages `contract_item_ids` to get all relevant IDs and then maps them to their corresponding Item objects. ```rust pub fn contract_items(&self, id: ContractId) -> impl Iterator> + Clone { self.contract_item_ids(id).map(move |id| self.item(id)) } ``` -------------------------------- ### Manage Source Files and Imports in Rust Source: https://docs.rs/solar-sema/latest/src/solar_sema/parse.rs_search= This Rust code snippet demonstrates how to initialize and populate a collection of source files, including their associated paths and import relationships. It asserts the correctness of file mapping and then performs a topological sort on the sources, followed by another assertion to verify the sorted order. ```rust let mut sources = Sources::new(sess.source_map()); let files = vec![ (aid, PathBuf::from("a.sol")), (bid, PathBuf::from("b.sol")), (cid, PathBuf::from("c.sol")), ]; sources[aid].imports.push((ItemId::new(0), cid)); for (id, path) in &files { assert_eq!(sources[*id].file.name, FileName::Real(path.clone())); } let assert_maps = |sources: &mut Sources<'_>| { for (_, path) in &files { let file = sess.source_map().get_file(path).unwrap(); let id = sources.get_file(&file).unwrap().0; assert_eq!(sources[id].file, file); } }; assert_maps(&mut sources); sources.topo_sort(); assert_maps(&mut sources); ``` -------------------------------- ### Rust: Get ExprId Value Source: https://docs.rs/solar-sema/latest/solar_sema/hir/struct.ExprId_search= Provides methods to retrieve the underlying numerical value of an ExprId. Both `get` and `index` return the stored u32 or usize representation respectively. ```rust pub const fn get(self) -> u32 Returns the underlying index value. ``` ```rust pub const fn index(self) -> usize Returns the underlying index value. ``` -------------------------------- ### Compiler Initialization and Context Entry (Rust) Source: https://docs.rs/solar-sema/latest/src/solar_sema/compiler.rs_search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Provides methods for creating a new `Compiler` instance and entering its execution context. `Compiler::new` initializes the compiler state, including the session and global context, using `MaybeUninit` for safety. The `enter` and `enter_mut` methods facilitate controlled access to the compiler's state within closures, ensuring proper thread-local storage setup. ```rust impl Compiler { /// Creates a new compiler. #[expect(clippy::missing_transmute_annotations)] pub fn new(sess: Session) -> Self { let mut inner = Box::pin(MaybeUninit::>::uninit()); // SAFETY: Valid pointer, `init` initializes all fields. unsafe { let inner = Pin::get_unchecked_mut(Pin::as_mut(&mut inner)); let inner = inner.as_mut_ptr(); CompilerInner::init(inner, sess); } // SAFETY: `inner` has been initialized, `MaybeUninit` is transmuted to `T`. Self(ManuallyDrop::new(unsafe { std::mem::transmute(inner) })) } /// Returns a reference to the compiler session. #[inline] pub fn sess(&self) -> &Session { &self.0.sess } /// Returns a mutable reference to the compiler session. #[inline] pub fn sess_mut(&mut self) -> &mut Session { self.as_mut().sess_mut() } /// Returns a reference to the diagnostics context. #[inline] pub fn dcx(&self) -> &DiagCtxt { &self.sess().dcx } /// Returns a mutable reference to the diagnostics context. #[inline] pub fn dcx_mut(&mut self) -> &mut DiagCtxt { &mut self.sess_mut().dcx } /// Enters the compiler context. /// /// See [`Session::enter`](Session::enter) for more details. pub fn enter(&self, f: impl FnOnce(&CompilerRef<'_>) -> T + Send) -> T { self.0.sess.enter(|| f(CompilerRef::new(&self.0))) } /// Enters the compiler context with mutable access. /// /// This is currently only necessary when parsing sources and lowering the ASTs. /// All accesses after can make use of `gcx`, passed by immutable reference. /// /// See [`Session::enter`](Session::enter) for more details. pub fn enter_mut(&mut self, f: impl FnOnce(&mut CompilerRef<'_>) -> T + Send) -> T { // SAFETY: `CompilerRef` does not allow mutable access to the session. let sess = unsafe { trustme::decouple_lt(&self.0.sess) }; sess.enter(|| f(self.as_mut())) } /// Enters the compiler context. /// /// Note that this does not set up the rayon thread pool. This is only useful when parsing /// sequentially, like manually using `Parser`. Otherwise, it might cause panics later on if a /// thread pool is expected to be set up correctly. /// /// See [`enter`](Self::enter) for more details. pub fn enter_sequential(&self, f: impl FnOnce(&CompilerRef<'_>) -> T) -> T { self.0.sess.enter_sequential(|| f(CompilerRef::new(&self.0))) } /// Enters the compiler context with mutable access. /// /// Note that this does not set up the rayon thread pool. This is only useful when parsing /// sequentially, like manually using `Parser`. Otherwise, it might cause panics later on if a /// thread pool is expected to be set up correctly. /// /// See [`enter_mut`](Self::enter_mut) for more details. pub fn enter_sequential_mut(&mut self, f: impl FnOnce(&mut CompilerRef<'_>) -> T) -> T { // SAFETY: `CompilerRef` does not allow mutable access to the session. let sess = unsafe { trustme::decouple_lt(&self.0.sess) }; sess.enter_sequential(|| f(self.as_mut())) } } ```