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