Proper type-checking where a function requires a tag identifier not just a tag (#6848)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
		@ -72,6 +72,10 @@ impl RuntimeType {
 | 
			
		||||
        RuntimeType::Primitive(PrimitiveType::Tag)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn tag_identifier() -> Self {
 | 
			
		||||
        RuntimeType::Primitive(PrimitiveType::TagId)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn bool() -> Self {
 | 
			
		||||
        RuntimeType::Primitive(PrimitiveType::Boolean)
 | 
			
		||||
    }
 | 
			
		||||
@ -337,6 +341,8 @@ pub enum PrimitiveType {
 | 
			
		||||
    String,
 | 
			
		||||
    Boolean,
 | 
			
		||||
    Tag,
 | 
			
		||||
    // Annoyingly some functions only want a TagIdentifier, not any kind of tag.
 | 
			
		||||
    TagId,
 | 
			
		||||
    Sketch,
 | 
			
		||||
    Solid,
 | 
			
		||||
    Plane,
 | 
			
		||||
@ -365,12 +371,14 @@ impl PrimitiveType {
 | 
			
		||||
            PrimitiveType::Axis3d => "3d axes".to_owned(),
 | 
			
		||||
            PrimitiveType::ImportedGeometry => "imported geometries".to_owned(),
 | 
			
		||||
            PrimitiveType::Tag => "tags".to_owned(),
 | 
			
		||||
            PrimitiveType::TagId => "tag identifiers".to_owned(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn subtype(&self, other: &PrimitiveType) -> bool {
 | 
			
		||||
        match (self, other) {
 | 
			
		||||
            (PrimitiveType::Number(n1), PrimitiveType::Number(n2)) => n1.subtype(n2),
 | 
			
		||||
            (PrimitiveType::TagId, PrimitiveType::Tag) => true,
 | 
			
		||||
            (t1, t2) => t1 == t2,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -386,6 +394,7 @@ impl fmt::Display for PrimitiveType {
 | 
			
		||||
            PrimitiveType::String => write!(f, "string"),
 | 
			
		||||
            PrimitiveType::Boolean => write!(f, "bool"),
 | 
			
		||||
            PrimitiveType::Tag => write!(f, "tag"),
 | 
			
		||||
            PrimitiveType::TagId => write!(f, "tag identifier"),
 | 
			
		||||
            PrimitiveType::Sketch => write!(f, "Sketch"),
 | 
			
		||||
            PrimitiveType::Solid => write!(f, "Solid"),
 | 
			
		||||
            PrimitiveType::Plane => write!(f, "Plane"),
 | 
			
		||||
@ -1159,6 +1168,10 @@ impl KclValue {
 | 
			
		||||
                KclValue::ImportedGeometry { .. } => Ok(value.clone()),
 | 
			
		||||
                _ => Err(self.into()),
 | 
			
		||||
            },
 | 
			
		||||
            PrimitiveType::TagId => match value {
 | 
			
		||||
                KclValue::TagIdentifier { .. } => Ok(value.clone()),
 | 
			
		||||
                _ => Err(self.into()),
 | 
			
		||||
            },
 | 
			
		||||
            PrimitiveType::Tag => match value {
 | 
			
		||||
                KclValue::TagDeclarator { .. } | KclValue::TagIdentifier { .. } | KclValue::Uuid { .. } => {
 | 
			
		||||
                    Ok(value.clone())
 | 
			
		||||
 | 
			
		||||
@ -408,13 +408,10 @@ impl Args {
 | 
			
		||||
        })?;
 | 
			
		||||
 | 
			
		||||
        T::from_kcl_val(&arg).ok_or_else(|| {
 | 
			
		||||
            KclError::Semantic(KclErrorDetails {
 | 
			
		||||
            KclError::Internal(KclErrorDetails {
 | 
			
		||||
                source_ranges: vec![self.source_range],
 | 
			
		||||
                message: format!(
 | 
			
		||||
                    "This function expected the input argument to be {}",
 | 
			
		||||
                    ty.human_friendly_type(),
 | 
			
		||||
                ),
 | 
			
		||||
            })
 | 
			
		||||
                message: "Mismatch between type coercion and value extraction (this isn't your fault).\nTo assist in bug-reporting, expected type: {ty:?}; actual value: {arg:?}".to_owned(),
 | 
			
		||||
           })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ use crate::{
 | 
			
		||||
 | 
			
		||||
/// Get the opposite edge to the edge given.
 | 
			
		||||
pub async fn get_opposite_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::edge(), exec_state)?;
 | 
			
		||||
    let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::tag_identifier(), exec_state)?;
 | 
			
		||||
 | 
			
		||||
    let edge = inner_get_opposite_edge(input_edge, exec_state, args.clone()).await?;
 | 
			
		||||
    Ok(KclValue::Uuid {
 | 
			
		||||
@ -98,7 +98,7 @@ async fn inner_get_opposite_edge(
 | 
			
		||||
 | 
			
		||||
/// Get the next adjacent edge to the edge given.
 | 
			
		||||
pub async fn get_next_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::edge(), exec_state)?;
 | 
			
		||||
    let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::tag_identifier(), exec_state)?;
 | 
			
		||||
 | 
			
		||||
    let edge = inner_get_next_adjacent_edge(input_edge, exec_state, args.clone()).await?;
 | 
			
		||||
    Ok(KclValue::Uuid {
 | 
			
		||||
@ -191,7 +191,7 @@ async fn inner_get_next_adjacent_edge(
 | 
			
		||||
 | 
			
		||||
/// Get the previous adjacent edge to the edge given.
 | 
			
		||||
pub async fn get_previous_adjacent_edge(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::edge(), exec_state)?;
 | 
			
		||||
    let input_edge = args.get_unlabeled_kw_arg_typed("edge", &RuntimeType::tag_identifier(), exec_state)?;
 | 
			
		||||
 | 
			
		||||
    let edge = inner_get_previous_adjacent_edge(input_edge, exec_state, args.clone()).await?;
 | 
			
		||||
    Ok(KclValue::Uuid {
 | 
			
		||||
 | 
			
		||||
@ -4,11 +4,12 @@ description: Error from executing panic_repro_cube.kcl
 | 
			
		||||
---
 | 
			
		||||
KCL Semantic error
 | 
			
		||||
 | 
			
		||||
  × semantic: This function expected the input argument to be Edge
 | 
			
		||||
    ╭─[43:5]
 | 
			
		||||
  × semantic: This function expected the input argument to be tag identifier
 | 
			
		||||
  │ but it's actually of type Unique ID (uuid)
 | 
			
		||||
    ╭─[43:25]
 | 
			
		||||
 42 │     // these double wrapped functions are the point of this test
 | 
			
		||||
 43 │     getNextAdjacentEdge(getNextAdjacentEdge(seg01)),
 | 
			
		||||
    ·     ───────────────────────┬───────────────────────
 | 
			
		||||
    ·                            ╰── tests/panic_repro_cube/input.kcl
 | 
			
		||||
    ·                         ─────────────┬────────────
 | 
			
		||||
    ·                                      ╰── tests/panic_repro_cube/input.kcl
 | 
			
		||||
 44 │     getNextAdjacentEdge(getNextAdjacentEdge(seg02))
 | 
			
		||||
    ╰────
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user