Fix to never have undefined iteration order and lint against it (#4665)
This commit is contained in:
		@ -77,6 +77,9 @@ http = "1"
 | 
			
		||||
kittycad = { version = "0.3.28", default-features = false, features = ["js", "requests"] }
 | 
			
		||||
kittycad-modeling-cmds = { version = "0.2.77", features = ["websocket"] }
 | 
			
		||||
 | 
			
		||||
[workspace.lints.clippy]
 | 
			
		||||
iter_over_hash_type = "warn"
 | 
			
		||||
 | 
			
		||||
[[test]]
 | 
			
		||||
name = "executor"
 | 
			
		||||
path = "tests/executor/main.rs"
 | 
			
		||||
 | 
			
		||||
@ -27,3 +27,6 @@ anyhow = "1.0.93"
 | 
			
		||||
expectorate = "1.1.0"
 | 
			
		||||
pretty_assertions = "1.4.1"
 | 
			
		||||
rustfmt-wrapper = "0.2.1"
 | 
			
		||||
 | 
			
		||||
[lints]
 | 
			
		||||
workspace = true
 | 
			
		||||
 | 
			
		||||
@ -13,3 +13,6 @@ pico-args = "0.5.0"
 | 
			
		||||
serde = { version = "1.0.214", features = ["derive"] }
 | 
			
		||||
serde_json = "1.0.128"
 | 
			
		||||
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] }
 | 
			
		||||
 | 
			
		||||
[lints]
 | 
			
		||||
workspace = true
 | 
			
		||||
 | 
			
		||||
@ -21,3 +21,6 @@ kittycad = { workspace = true, features = ["clap"] }
 | 
			
		||||
kittycad-modeling-cmds = { workspace = true }
 | 
			
		||||
tokio = { version = "1.41", features = ["full", "time", "rt", "tracing"] }
 | 
			
		||||
uuid = { version = "1.11.0", features = ["v4", "js", "serde"] }
 | 
			
		||||
 | 
			
		||||
[lints]
 | 
			
		||||
workspace = true
 | 
			
		||||
 | 
			
		||||
@ -121,6 +121,9 @@ pretty_assertions = "1.4.1"
 | 
			
		||||
tokio = { version = "1.41.1", features = ["rt-multi-thread", "macros", "time"] }
 | 
			
		||||
twenty-twenty = "0.8.0"
 | 
			
		||||
 | 
			
		||||
[lints]
 | 
			
		||||
workspace = true
 | 
			
		||||
 | 
			
		||||
[[bench]]
 | 
			
		||||
name = "compiler_benchmark_criterion"
 | 
			
		||||
harness = false
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,9 @@ members = ["."]
 | 
			
		||||
[profile.release]
 | 
			
		||||
debug = 1
 | 
			
		||||
 | 
			
		||||
[lints]
 | 
			
		||||
workspace = true
 | 
			
		||||
 | 
			
		||||
[[bin]]
 | 
			
		||||
name = "parser"
 | 
			
		||||
path = "fuzz_targets/parser.rs"
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,10 @@
 | 
			
		||||
use std::collections::{BTreeMap, HashMap};
 | 
			
		||||
use std::collections::BTreeMap;
 | 
			
		||||
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use base64::Engine;
 | 
			
		||||
use convert_case::Casing;
 | 
			
		||||
use handlebars::Renderable;
 | 
			
		||||
use indexmap::IndexMap;
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use serde_json::json;
 | 
			
		||||
 | 
			
		||||
@ -271,7 +272,7 @@ fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
 | 
			
		||||
    Ok(hbs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn generate_index(combined: &HashMap<String, Box<dyn StdLibFn>>) -> Result<()> {
 | 
			
		||||
fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>) -> Result<()> {
 | 
			
		||||
    let hbs = init_handlebars()?;
 | 
			
		||||
 | 
			
		||||
    let mut functions = Vec::new();
 | 
			
		||||
 | 
			
		||||
@ -213,7 +213,12 @@ impl EngineConnection {
 | 
			
		||||
                            WebSocketResponse::Success(SuccessWebSocketResponse {
 | 
			
		||||
                                resp: OkWebSocketResponseData::ModelingBatch { responses },
 | 
			
		||||
                                ..
 | 
			
		||||
                            }) => {
 | 
			
		||||
                            }) =>
 | 
			
		||||
                            {
 | 
			
		||||
                                #[expect(
 | 
			
		||||
                                    clippy::iter_over_hash_type,
 | 
			
		||||
                                    reason = "modeling command uses a HashMap and keys are random, so we don't really have a choice"
 | 
			
		||||
                                )]
 | 
			
		||||
                                for (resp_id, batch_response) in responses {
 | 
			
		||||
                                    let id: uuid::Uuid = (*resp_id).into();
 | 
			
		||||
                                    match batch_response {
 | 
			
		||||
 | 
			
		||||
@ -463,6 +463,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
 | 
			
		||||
        responses: HashMap<uuid::Uuid, BatchResponse>,
 | 
			
		||||
    ) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
 | 
			
		||||
        // Iterate over the responses and check for errors.
 | 
			
		||||
        #[expect(
 | 
			
		||||
            clippy::iter_over_hash_type,
 | 
			
		||||
            reason = "modeling command uses a HashMap and keys are random, so we don't really have a choice"
 | 
			
		||||
        )]
 | 
			
		||||
        for (cmd_id, resp) in responses.iter() {
 | 
			
		||||
            match resp {
 | 
			
		||||
                BatchResponse::Success { response } => {
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,6 @@
 | 
			
		||||
//! The executor for the AST.
 | 
			
		||||
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::{HashMap, HashSet},
 | 
			
		||||
    sync::Arc,
 | 
			
		||||
};
 | 
			
		||||
use std::{collections::HashSet, sync::Arc};
 | 
			
		||||
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use async_recursion::async_recursion;
 | 
			
		||||
@ -193,7 +190,7 @@ impl EnvironmentRef {
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
 | 
			
		||||
pub struct Environment {
 | 
			
		||||
    bindings: HashMap<String, KclValue>,
 | 
			
		||||
    bindings: IndexMap<String, KclValue>,
 | 
			
		||||
    parent: Option<EnvironmentRef>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -203,7 +200,7 @@ impl Environment {
 | 
			
		||||
    pub fn root() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            // Prelude
 | 
			
		||||
            bindings: HashMap::from([
 | 
			
		||||
            bindings: IndexMap::from([
 | 
			
		||||
                ("ZERO".to_string(), KclValue::from_number(0.0, NO_META)),
 | 
			
		||||
                ("QUARTER_TURN".to_string(), KclValue::from_number(90.0, NO_META)),
 | 
			
		||||
                ("HALF_TURN".to_string(), KclValue::from_number(180.0, NO_META)),
 | 
			
		||||
@ -215,7 +212,7 @@ impl Environment {
 | 
			
		||||
 | 
			
		||||
    pub fn new(parent: EnvironmentRef) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            bindings: HashMap::new(),
 | 
			
		||||
            bindings: IndexMap::new(),
 | 
			
		||||
            parent: Some(parent),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -770,8 +767,8 @@ pub struct Sketch {
 | 
			
		||||
    /// The starting path.
 | 
			
		||||
    pub start: BasePath,
 | 
			
		||||
    /// Tag identifiers that have been declared in this sketch.
 | 
			
		||||
    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
 | 
			
		||||
    pub tags: HashMap<String, TagIdentifier>,
 | 
			
		||||
    #[serde(default, skip_serializing_if = "IndexMap::is_empty")]
 | 
			
		||||
    pub tags: IndexMap<String, TagIdentifier>,
 | 
			
		||||
    /// The original id of the sketch. This stays the same even if the sketch is
 | 
			
		||||
    /// is sketched on face etc.
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
 | 
			
		||||
@ -25,11 +25,10 @@ pub mod types;
 | 
			
		||||
pub mod units;
 | 
			
		||||
pub mod utils;
 | 
			
		||||
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
pub use args::Args;
 | 
			
		||||
use derive_docs::stdlib;
 | 
			
		||||
use indexmap::IndexMap;
 | 
			
		||||
use lazy_static::lazy_static;
 | 
			
		||||
use parse_display::{Display, FromStr};
 | 
			
		||||
use schemars::JsonSchema;
 | 
			
		||||
@ -167,8 +166,8 @@ pub fn get_stdlib_fn(name: &str) -> Option<Box<dyn StdLibFn>> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct StdLib {
 | 
			
		||||
    pub fns: HashMap<String, Box<dyn StdLibFn>>,
 | 
			
		||||
    pub kcl_fns: HashMap<String, Box<dyn KclStdLibFn>>,
 | 
			
		||||
    pub fns: IndexMap<String, Box<dyn StdLibFn>>,
 | 
			
		||||
    pub kcl_fns: IndexMap<String, Box<dyn KclStdLibFn>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl std::fmt::Debug for StdLib {
 | 
			
		||||
@ -198,7 +197,7 @@ impl StdLib {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get the combined hashmaps.
 | 
			
		||||
    pub fn combined(&self) -> HashMap<String, Box<dyn StdLibFn>> {
 | 
			
		||||
    pub fn combined(&self) -> IndexMap<String, Box<dyn StdLibFn>> {
 | 
			
		||||
        let mut combined = self.fns.clone();
 | 
			
		||||
        for (k, v) in self.kcl_fns.clone() {
 | 
			
		||||
            combined.insert(k, v.std_lib());
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
//! Functions related to sketching.
 | 
			
		||||
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use derive_docs::stdlib;
 | 
			
		||||
use indexmap::IndexMap;
 | 
			
		||||
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
 | 
			
		||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
 | 
			
		||||
use kittycad_modeling_cmds as kcmc;
 | 
			
		||||
@ -1301,7 +1300,7 @@ pub(crate) async fn inner_start_profile_at(
 | 
			
		||||
                }),
 | 
			
		||||
                surface: None,
 | 
			
		||||
            });
 | 
			
		||||
            HashMap::from([(tag.name.to_string(), tag_identifier)])
 | 
			
		||||
            IndexMap::from([(tag.name.to_string(), tag_identifier)])
 | 
			
		||||
        } else {
 | 
			
		||||
            Default::default()
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user