Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions baml_language/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions baml_language/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ version = "0.0.0-beta"
bex_str = { path = "crates/bex_str" }
baml_base = { path = "crates/baml_base" }
baml_type = { path = "crates/baml_type" }
baml_type_runtime = { path = "crates/baml_type_runtime" }
baml_type_macros = { path = "crates/baml_type_macros" }
baml_builtins2 = { path = "crates/baml_builtins2" }
baml_builtins2_codegen = { path = "crates/baml_builtins2_codegen" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,13 @@ class GenericSdkError {
class CompilationError {
message string
}

/// A value/type mismatch at the call boundary — a caller passed an argument
/// that doesn't fit the callee's (possibly inferred) type, a generic `TypeVar`
/// could not be inferred and must be specified, or repeat occurrences of a
/// `TypeVar` have no consistent binding. Synthesized host-side from
/// `EngineError::TypeMismatch`; each host SDK surfaces it as its native
/// type-error (Python `TypeError`).
class TypeMismatch {
message string
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class baml.errors.DevOther <builtin>/baml/ns_errors/error
class baml.errors.HostCallable <builtin>/baml/ns_errors/errors.baml:53
class baml.errors.GenericSdkError <builtin>/baml/ns_errors/errors.baml:74
class baml.errors.CompilationError <builtin>/baml/ns_errors/errors.baml:80
class baml.errors.TypeMismatch <builtin>/baml/ns_errors/errors.baml:90
class baml.errors.StackFrame <builtin>/baml/ns_errors/stack_trace.baml:2
class baml.errors.StackTrace <builtin>/baml/ns_errors/stack_trace.baml:9
class baml.fs.File <builtin>/baml/ns_fs/fs.baml:6
Expand Down
1 change: 1 addition & 0 deletions baml_language/crates/baml_compiler2_emit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,7 @@ pub fn generate_project_bytecode_with_opt(
type_tag,
ty_attr: TyAttr::default(),
has_cleanup,
generic_param_count: class_data.generic_params.len(),
})));
// Register with fully-qualified name for inter-package lookups.
class_object_indices.insert(fq_name.clone(), class_obj_idx);
Expand Down
1 change: 1 addition & 0 deletions baml_language/crates/baml_compiler2_tir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ baml_compiler2_ast = { workspace = true }
baml_compiler2_hir = { workspace = true }
baml_compiler2_ppir = { workspace = true }
baml_type = { workspace = true }
baml_type_runtime = { workspace = true }
baml_workspace = { workspace = true }
indexmap = { workspace = true }
num-bigint = { workspace = true }
Expand Down
34 changes: 33 additions & 1 deletion baml_language/crates/baml_compiler2_tir/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17449,9 +17449,41 @@ impl TypeInferenceBuilder<'_> {
// structural overlap check that respects runtime tag identity:
// primitives must agree on head, classes must agree on qtn AND
// overlap pairwise on their generic args.
// A `TypeVar` scrutinee member (e.g. the `T` in `T | string | null`)
// is an *open* type: at runtime it stands for whatever concrete type
// `T` is instantiated to. `atoms_overlap` deliberately reports a
// `TypeVar` as overlapping *everything* (a `let v: T` pattern can
// match any value). That symmetry is correct for a `TypeVar`
// *pattern* but wrong for a `TypeVar` *member*: a purely-concrete
// pattern (`string`, `null`, a bare class) must not over-claim the
// open `T` member, or it shadows the dedicated `let v: T` arm and
// that arm is then reported unreachable (the `tag_or_value<T>` bug).
//
// So make the overlap directional for `TypeVar` members: claim a
// `TypeVar` member only when the pattern itself can genuinely match
// open-`T` values — i.e. some atom of the pattern's natural type is a
// `TypeVar` (a `let v: T` pattern), or an `Unknown`/`Error` recovery
// atom. A pattern whose natural type is a union that *includes* a
// `TypeVar` (e.g. a `let p: T | Concrete` binding, as in the
// streaming `TStream | StreamNoYield` case) still claims it, because
// one of its atoms is a `TypeVar`. Concrete patterns skip the member.
let natural_atoms = {
let mut atoms = Vec::new();
self.collect_overlap_atoms(&natural, &mut atoms);
atoms
};
let pattern_claims_typevar = natural_atoms
.iter()
.any(|a| matches!(a, Ty::TypeVar(..) | Ty::Unknown { .. } | Ty::Error { .. }));
union_members
.iter()
.filter(|m| self.types_overlap(&natural, m))
.filter(|m| {
if matches!(m, Ty::TypeVar(..)) {
pattern_claims_typevar
} else {
self.types_overlap(&natural, m)
}
})
.cloned()
.collect()
}
Expand Down
Loading
Loading