From 9b140f23b597168b99d7be90dff6d83f42718370 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 14:13:00 -0700 Subject: [PATCH 01/10] =?UTF-8?q?Phase=201:=20test-first=20=E2=80=94=20upd?= =?UTF-8?q?ate=20fixtures=20and=20add=20test=20expectations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update namespaces_root_fallback fixture: bare Config → root.Config - Create namespaces_bare_name_rejected fixture for bare cross-ns refs - Add ignored tests: bare_name_cross_namespace_rejected, multi_segment_bare_path_rejected - Capture baseline snapshots for both fixtures --- .../namespaces_bare_name_rejected/main.baml | 3 + .../ns_llm/models.baml | 9 +++ .../ns_llm/models.baml | 5 +- ...es_bare_name_rejected__01_lexer__main.snap | 9 +++ ...ame_rejected__01_lexer__ns_llm_models.snap | 60 +++++++++++++++++ ...s_bare_name_rejected__02_parser__main.snap | 17 +++++ ...me_rejected__02_parser__ns_llm_models.snap | 46 +++++++++++++ ...namespaces_bare_name_rejected__03_hir.snap | 13 ++++ ...mespaces_bare_name_rejected__04_5_mir.snap | 20 ++++++ ...namespaces_bare_name_rejected__04_tir.snap | 21 ++++++ ...es_bare_name_rejected__05_diagnostics.snap | 5 ++ ...spaces_bare_name_rejected__06_codegen.snap | 11 +++ ...are_name_rejected__10_formatter__main.snap | 6 ++ ...rejected__10_formatter__ns_llm_models.snap | 12 ++++ ...oot_fallback__01_lexer__ns_llm_models.snap | 25 ++----- ...ot_fallback__02_parser__ns_llm_models.snap | 4 +- ...sts__namespaces_root_fallback__03_hir.snap | 2 +- ...fallback__10_formatter__ns_llm_models.snap | 5 +- .../baml_tests/src/compiler2_tir/phase5.rs | 67 +++++++++++++++++++ 19 files changed, 313 insertions(+), 27 deletions(-) create mode 100644 baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/main.baml create mode 100644 baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/ns_llm/models.baml create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__03_hir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__ns_llm_models.snap diff --git a/baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/main.baml b/baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/main.baml new file mode 100644 index 0000000000..8a9655fe41 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/main.baml @@ -0,0 +1,3 @@ +class Config { + key string +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/ns_llm/models.baml b/baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/ns_llm/models.baml new file mode 100644 index 0000000000..36be9b0be6 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_bare_name_rejected/ns_llm/models.baml @@ -0,0 +1,9 @@ +class Response { + text string +} + +// This bare reference to Config should fail — it's in root namespace, +// not in the llm namespace. Must use root.Config instead. +function UseConfig(cfg: Config) -> Response { + Response { text: cfg.key } +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_root_fallback/ns_llm/models.baml b/baml_language/crates/baml_tests/projects/namespaces_root_fallback/ns_llm/models.baml index 1402ee685c..31895b9dbc 100644 --- a/baml_language/crates/baml_tests/projects/namespaces_root_fallback/ns_llm/models.baml +++ b/baml_language/crates/baml_tests/projects/namespaces_root_fallback/ns_llm/models.baml @@ -2,8 +2,7 @@ class Response { text string } -// Root-level types are accessible from child namespaces without root. prefix. -// Config resolves via fallback to the root namespace. -function UseConfig(cfg: Config) -> Response { +// Cross-namespace references require explicit root. prefix. +function UseConfig(cfg: root.Config) -> Response { Response { text: cfg.key } } diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__main.snap new file mode 100644 index 0000000000..edfcf8a9a8 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__main.snap @@ -0,0 +1,9 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Class "class" +Word "Config" +LBrace "{" +Word "key" +Word "string" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__ns_llm_models.snap new file mode 100644 index 0000000000..b805246eb3 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__01_lexer__ns_llm_models.snap @@ -0,0 +1,60 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Class "class" +Word "Response" +LBrace "{" +Word "text" +Word "string" +RBrace "}" +Slash "/" +Slash "/" +Word "This" +Word "bare" +Word "reference" +Word "to" +Word "Config" +Word "should" +Word "fail" +Error "—" +Word "it" +Error "'" +Word "s" +In "in" +Word "root" +Word "namespace" +Comma "," +Slash "/" +Slash "/" +Word "not" +In "in" +Word "the" +Word "llm" +Word "namespace" +Dot "." +Word "Must" +Word "use" +Word "root" +Dot "." +Word "Config" +Word "instead" +Dot "." +Function "function" +Word "UseConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "Config" +RParen ")" +Arrow "->" +Word "Response" +LBrace "{" +Word "Response" +LBrace "{" +Word "text" +Colon ":" +Word "cfg" +Dot "." +Word "key" +RBrace "}" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__main.snap new file mode 100644 index 0000000000..1880a89d3f --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__main.snap @@ -0,0 +1,17 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Config" + L_BRACE "{" + FIELD + WORD "key" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__ns_llm_models.snap new file mode 100644 index 0000000000..662ba14192 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__02_parser__ns_llm_models.snap @@ -0,0 +1,46 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Response" + L_BRACE "{" + FIELD + WORD "text" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "UseConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Response" + WORD "Response" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Response" + L_BRACE "{" + OBJECT_FIELD + WORD "text" + COLON ":" + PATH_EXPR "cfg.key" + WORD "cfg" + DOT "." + WORD "key" + R_BRACE "}" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__03_hir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__03_hir.snap new file mode 100644 index 0000000000..6814f0177b --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__03_hir.snap @@ -0,0 +1,13 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== HIR2 === +class user.Config { + key: string +} +class user.llm.Response { + text: string +} +function user.llm.UseConfig(cfg: user.llm.Config) -> user.llm.Response [expr] { + { } user.llm.Response { text: cfg.key } +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap new file mode 100644 index 0000000000..9182fc690d --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap @@ -0,0 +1,20 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== MIR2 === +fn user.llm.UseConfig(cfg: Config) -> void { + // Locals: + let _0: void // _0 // return + let _1: Config // cfg // param + let _2: string + + bb0: { + _2 = copy _1.0; + _0 = Response { copy _2 }; + goto -> bb1; + } + + bb1: { + return; + } +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap new file mode 100644 index 0000000000..ed48925c34 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap @@ -0,0 +1,21 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== TIR2 === +class user.Config { + key: string +} +class user.Config$stream { + key: null | string +} +class user.llm.Response { + text: string +} +function user.llm.UseConfig(cfg: user.Config) -> user.llm.Response throws never { + { : user.llm.Response + Response { text: cfg.key } : user.llm.Response + } +} +class user.llm.Response$stream { + text: null | string +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap new file mode 100644 index 0000000000..40cf564409 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap @@ -0,0 +1,5 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== COMPILER2 DIAGNOSTICS === +No errors found. diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap new file mode 100644 index 0000000000..7319a247b0 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap @@ -0,0 +1,11 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +function user.llm.UseConfig(cfg: Config) -> void { + alloc_instance Response + copy 0 + load_var cfg + load_field .key + store_field .text + return +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__main.snap new file mode 100644 index 0000000000..29950e9367 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__main.snap @@ -0,0 +1,6 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +class Config { + key: string +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__ns_llm_models.snap new file mode 100644 index 0000000000..cfca30ab31 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__10_formatter__ns_llm_models.snap @@ -0,0 +1,12 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +class Response { + text: string +} + +// This bare reference to Config should fail — it's in root namespace, +// not in the llm namespace. Must use root.Config instead. +function UseConfig(cfg: Config) -> Response { + Response { text: cfg.key } +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__01_lexer__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__01_lexer__ns_llm_models.snap index 036a745eaf..b0b544de7c 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__01_lexer__ns_llm_models.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__01_lexer__ns_llm_models.snap @@ -9,34 +9,21 @@ Word "string" RBrace "}" Slash "/" Slash "/" -Word "Root-level" -Word "types" -Word "are" -Word "accessible" -Word "from" -Word "child" -Word "namespaces" -Word "without" +Word "Cross-namespace" +Word "references" +Word "require" +Word "explicit" Word "root" Dot "." Word "prefix" Dot "." -Slash "/" -Slash "/" -Word "Config" -Word "resolves" -Word "via" -Word "fallback" -Word "to" -Word "the" -Word "root" -Word "namespace" -Dot "." Function "function" Word "UseConfig" LParen "(" Word "cfg" Colon ":" +Word "root" +Dot "." Word "Config" RParen ")" Arrow "->" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__02_parser__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__02_parser__ns_llm_models.snap index 662ba14192..7d641716f1 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__02_parser__ns_llm_models.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__02_parser__ns_llm_models.snap @@ -20,7 +20,9 @@ SOURCE_FILE PARAMETER WORD "cfg" COLON ":" - TYPE_EXPR "Config" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." WORD "Config" R_PAREN ")" ARROW "->" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__03_hir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__03_hir.snap index 6814f0177b..2aea93c68e 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__03_hir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__03_hir.snap @@ -8,6 +8,6 @@ class user.Config { class user.llm.Response { text: string } -function user.llm.UseConfig(cfg: user.llm.Config) -> user.llm.Response [expr] { +function user.llm.UseConfig(cfg: root.Config) -> user.llm.Response [expr] { { } user.llm.Response { text: cfg.key } } diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__10_formatter__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__10_formatter__ns_llm_models.snap index 47ca3d617c..e7602f2f5e 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__10_formatter__ns_llm_models.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__10_formatter__ns_llm_models.snap @@ -5,8 +5,7 @@ class Response { text: string } -// Root-level types are accessible from child namespaces without root. prefix. -// Config resolves via fallback to the root namespace. -function UseConfig(cfg: Config) -> Response { +// Cross-namespace references require explicit root. prefix. +function UseConfig(cfg: root.Config) -> Response { Response { text: cfg.key } } diff --git a/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs b/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs index a38612f097..8dc5dd2453 100644 --- a/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs +++ b/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs @@ -690,3 +690,70 @@ fn nested_namespace_resolution() { "root.llm.openai.OpenAIClient should not resolve to Unknown" ); } + +#[test] +#[ignore] // Passes after Phase 3 removes bare fallback +fn bare_name_cross_namespace_rejected() { + // Config is in root, but ns_context is ["llm"] — bare "Config" should not resolve + use baml_compiler2_tir::lower_type_expr::lower_type_expr_in_ns; + + let mut db = make_db(); + let _root_file = db.add_file("main.baml", "class Config { key string }"); + let _ns_file = db.add_file("ns_llm/models.baml", "class Response { text string }"); + + let pkg_id = PackageId::new(&db, Name::new("user")); + let pkg_items = package_items(&db, pkg_id); + + let segments = vec![Name::new("Config")]; + let ns_context = vec![Name::new("llm")]; + let mut diags = Vec::new(); + let ty = lower_type_expr_in_ns( + &db, + &baml_compiler2_ast::TypeExpr::Path { + segments, + attrs: vec![], + }, + pkg_items, + &ns_context, + &[], + &mut diags, + ); + assert!( + matches!(ty, baml_compiler2_tir::ty::Ty::Unknown { .. }), + "bare Config from ns_llm should not resolve" + ); + assert!(!diags.is_empty(), "should emit UnresolvedType diagnostic"); +} + +#[test] +#[ignore] // Passes after Phase 3 +fn multi_segment_bare_path_rejected() { + // "ns2.MyClass" from ns1 without root. prefix should fail + use baml_compiler2_tir::lower_type_expr::lower_type_expr_in_ns; + + let mut db = make_db(); + let _f1 = db.add_file("ns_ns1/a.baml", "class Foo { x int }"); + let _f2 = db.add_file("ns_ns2/b.baml", "class MyClass { y string }"); + + let pkg_id = PackageId::new(&db, Name::new("user")); + let pkg_items = package_items(&db, pkg_id); + + let segments = vec![Name::new("ns2"), Name::new("MyClass")]; + let ns_context = vec![Name::new("ns1")]; + let mut diags = Vec::new(); + let ty = lower_type_expr_in_ns( + &db, + &baml_compiler2_ast::TypeExpr::Path { + segments, + attrs: vec![], + }, + pkg_items, + &ns_context, + &[], + &mut diags, + ); + assert!( + matches!(ty, baml_compiler2_tir::ty::Ty::Unknown { .. }), + "ns2.MyClass from ns1 should not resolve without root. prefix" + ); +} From ec73a92605c57a5aeb8a0c0d49dbe86ef08d2bc9 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 14:45:08 -0700 Subject: [PATCH 02/10] Phase 2: change lookup_type/lookup_value API to (namespace, item) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace split-loop (path: &[Name]) signature with explicit (namespace: &[Name], item: &Name) on PackageItems and PackageInterface. Update all ~34 call sites. Behavior-preserving — same lookups happen, just with explicit namespace/item split at the caller. --- .../crates/baml_compiler2_hir/src/package.rs | 43 ++------ .../crates/baml_compiler2_mir/src/lower.rs | 2 +- .../crates/baml_compiler2_ppir/src/expand.rs | 18 ++- .../crates/baml_compiler2_tir/src/builder.rs | 103 +++++++----------- .../baml_compiler2_tir/src/inference.rs | 5 +- .../baml_compiler2_tir/src/lower_type_expr.rs | 21 ++-- .../src/package_interface.rs | 82 +++++++------- .../crates/baml_compiler2_tir/src/resolve.rs | 22 ++-- .../baml_compiler2_tir/src/throw_inference.rs | 11 +- .../baml_lsp2_actions/src/completions.rs | 6 +- .../crates/baml_lsp2_actions/src/tokens.rs | 2 +- .../crates/baml_tests/src/compiler2_hir.rs | 52 +++++++-- .../baml_tests/src/compiler2_tir/mod.rs | 4 +- 13 files changed, 178 insertions(+), 193 deletions(-) diff --git a/baml_language/crates/baml_compiler2_hir/src/package.rs b/baml_language/crates/baml_compiler2_hir/src/package.rs index b37b298f91..188ce9ab30 100644 --- a/baml_language/crates/baml_compiler2_hir/src/package.rs +++ b/baml_language/crates/baml_compiler2_hir/src/package.rs @@ -134,24 +134,13 @@ unsafe impl salsa::Update for PackageItems<'_> { } impl<'db> PackageItems<'db> { - /// Look up a type by path segments (e.g., `["llm", "render_prompt"]`). + /// Look up a type by explicit namespace and item name. /// - /// Tries progressively longer namespace prefixes: for path `["a", "B"]`, - /// first tries namespace `["a"]` + name `"B"`, then namespace `[]` + name `"a"`. - pub fn lookup_type(&self, path: &[Name]) -> Option> { - if path.is_empty() { - return None; - } - for split in (0..path.len()).rev() { - let ns_path = &path[..split]; - let item_name = &path[split]; - if let Some(ns) = self.namespaces.get(ns_path) { - if let Some(def) = ns.types.get(item_name) { - return Some(*def); - } - } - } - None + /// Single hash lookup — no split-loop ambiguity. + /// `namespace` is the namespace path (e.g. `["llm"]` or `[]` for root). + /// `item` is the unqualified item name (e.g. `"Response"`). + pub fn lookup_type(&self, namespace: &[Name], item: &Name) -> Option> { + self.namespaces.get(namespace)?.types.get(item).copied() } /// Look up a type by short name, searching across ALL namespaces. @@ -167,21 +156,11 @@ impl<'db> PackageItems<'db> { None } - /// Look up a value by path segments. - pub fn lookup_value(&self, path: &[Name]) -> Option> { - if path.is_empty() { - return None; - } - for split in (0..path.len()).rev() { - let ns_path = &path[..split]; - let item_name = &path[split]; - if let Some(ns) = self.namespaces.get(ns_path) { - if let Some(def) = ns.values.get(item_name) { - return Some(*def); - } - } - } - None + /// Look up a value by explicit namespace and item name. + /// + /// Single hash lookup — no split-loop ambiguity. + pub fn lookup_value(&self, namespace: &[Name], item: &Name) -> Option> { + self.namespaces.get(namespace)?.values.get(item).copied() } } diff --git a/baml_language/crates/baml_compiler2_mir/src/lower.rs b/baml_language/crates/baml_compiler2_mir/src/lower.rs index 9767e5aa2b..049c36018e 100644 --- a/baml_language/crates/baml_compiler2_mir/src/lower.rs +++ b/baml_language/crates/baml_compiler2_mir/src/lower.rs @@ -855,7 +855,7 @@ impl LoweringContext<'_> { enclosing_class_name .as_ref() .and_then(|cn| { - pkg_items.lookup_type(std::slice::from_ref(cn)).map(|def| { + pkg_items.lookup_type(&[], cn).map(|def| { let tir_ty = baml_compiler2_tir::ty::Ty::Class( baml_compiler2_tir::lower_type_expr::qualify_def(self.db, def, cn), baml_compiler2_tir::ty::TyAttr::default(), diff --git a/baml_language/crates/baml_compiler2_ppir/src/expand.rs b/baml_language/crates/baml_compiler2_ppir/src/expand.rs index eac543e6c9..a584957031 100644 --- a/baml_language/crates/baml_compiler2_ppir/src/expand.rs +++ b/baml_language/crates/baml_compiler2_ppir/src/expand.rs @@ -19,12 +19,18 @@ pub enum SymbolKind { } pub fn classify_type(package_items: &PackageItems<'_>, path: &[Name]) -> Option { - package_items.lookup_type(path).and_then(|def| match def { - Definition::Class(_) => Some(SymbolKind::Class), - Definition::Enum(_) => Some(SymbolKind::Enum), - Definition::TypeAlias(_) => Some(SymbolKind::TypeAlias), - _ => None, - }) + if path.is_empty() { + return None; + } + let item = path.last().unwrap(); + package_items + .lookup_type(&path[..path.len() - 1], item) + .and_then(|def| match def { + Definition::Class(_) => Some(SymbolKind::Class), + Definition::Enum(_) => Some(SymbolKind::Enum), + Definition::TypeAlias(_) => Some(SymbolKind::TypeAlias), + _ => None, + }) } /// Classify a type, falling back to `root.*` prefix handling, bare-name diff --git a/baml_language/crates/baml_compiler2_tir/src/builder.rs b/baml_language/crates/baml_compiler2_tir/src/builder.rs index c660eee9a8..13242f9471 100644 --- a/baml_language/crates/baml_compiler2_tir/src/builder.rs +++ b/baml_language/crates/baml_compiler2_tir/src/builder.rs @@ -366,14 +366,12 @@ impl<'db> TypeInferenceBuilder<'db> { type_name .as_ref() .and_then(|n| { - self.package_items - .lookup_type(std::slice::from_ref(n)) - .map(|def| { - Ty::Class( - crate::lower_type_expr::qualify_def(self.context.db(), def, n), - TyAttr::default(), - ) - }) + self.package_items.lookup_type(&[], n).map(|def| { + Ty::Class( + crate::lower_type_expr::qualify_def(self.context.db(), def, n), + TyAttr::default(), + ) + }) }) .unwrap_or(Ty::Unknown { attr: TyAttr::default(), @@ -1475,10 +1473,7 @@ impl<'db> TypeInferenceBuilder<'db> { return Ty::EnumVariant(qn.clone(), variant.clone(), TyAttr::default()); } } - if let Some(def) = self - .package_items - .lookup_type(std::slice::from_ref(enum_name)) - { + if let Some(def) = self.package_items.lookup_type(&[], enum_name) { if matches!(def, Definition::Enum(_)) { return Ty::EnumVariant( crate::lower_type_expr::qualify_def(self.context.db(), def, enum_name), @@ -1530,10 +1525,7 @@ impl<'db> TypeInferenceBuilder<'db> { matches!( name.as_str(), "int" | "float" | "string" | "bool" | "null" | "image" | "audio" | "video" | "pdf" - ) || self - .package_items - .lookup_type(std::slice::from_ref(name)) - .is_some() + ) || self.package_items.lookup_type(&[], name).is_some() } fn catch_base_throw_types(&self, base_expr_id: ExprId, body: &ExprBody) -> BTreeSet { @@ -2083,12 +2075,6 @@ impl<'db> TypeInferenceBuilder<'db> { if segments.len() == 1 { let name = &segments[0]; let ty = self.infer_single_name(name); - let ns_name: Vec = self - .ns_context - .iter() - .chain(std::iter::once(name)) - .cloned() - .collect(); // Namespace shorthands like `env`, `sys`, `http` etc. can appear as // the base of a FieldAccess expression (e.g. `env.get("KEY")`), where // the parent will route them to the `"baml"` package. Don't emit @@ -2110,8 +2096,14 @@ impl<'db> TypeInferenceBuilder<'db> { ); if matches!(ty, Ty::Unknown { .. }) && !self.locals.contains_key(name) - && self.package_items.lookup_value(&ns_name).is_none() - && self.package_items.lookup_type(&ns_name).is_none() + && self + .package_items + .lookup_value(&self.ns_context, name) + .is_none() + && self + .package_items + .lookup_type(&self.ns_context, name) + .is_none() && !is_baml_ns_shorthand { self.context @@ -2185,7 +2177,8 @@ impl<'db> TypeInferenceBuilder<'db> { } // Try as a value (function) in a nested namespace - let lookup_val = pkg_items.lookup_value(path); + let item = path.last().expect("non-empty path"); + let lookup_val = pkg_items.lookup_value(&path[..path.len() - 1], item); if let Some(Definition::Function(func_loc)) = lookup_val { let db = self.context.db(); let item_tree_for_func = baml_compiler2_ppir::file_item_tree(db, func_loc.file(db)); @@ -2240,9 +2233,9 @@ impl<'db> TypeInferenceBuilder<'db> { } // Try as a type (class/enum) - if let Some(def) = pkg_items.lookup_type(path) { + if let Some(def) = pkg_items.lookup_type(&path[..path.len() - 1], item) { let db = self.context.db(); - let name = path.last().unwrap(); + let name = item; match def { Definition::Class(_) => { let class_qtn = crate::lower_type_expr::qualify_def(db, def, name); @@ -2271,14 +2264,7 @@ impl<'db> TypeInferenceBuilder<'db> { other => other.clone(), }; } - // Build namespace-qualified lookup path. - let lookup_path: Vec = self - .ns_context - .iter() - .chain(std::iter::once(name)) - .cloned() - .collect(); - if let Some(def) = self.package_items.lookup_value(&lookup_path) { + if let Some(def) = self.package_items.lookup_value(&self.ns_context, name) { match def { Definition::Function(func_loc) => { // Get function signature to build the function type @@ -2336,7 +2322,7 @@ impl<'db> TypeInferenceBuilder<'db> { attr: TyAttr::default(), }, } - } else if let Some(def) = self.package_items.lookup_type(&lookup_path) { + } else if let Some(def) = self.package_items.lookup_type(&self.ns_context, name) { let db = self.context.db(); match def { Definition::Class(_) => Ty::Class( @@ -2404,9 +2390,8 @@ impl<'db> TypeInferenceBuilder<'db> { } // Known class but member not found — error - let class_def = self - .package_items - .lookup_type(&[Self::unqualify(class_name)]); + let short = Self::unqualify(class_name); + let class_def = self.package_items.lookup_type(&[], &short); let related = class_def .map(|def| vec![(RelatedLocation::Item(def), "class defined here")]) .unwrap_or_default(); @@ -2440,9 +2425,8 @@ impl<'db> TypeInferenceBuilder<'db> { } // Known enum but variant not found — error - let enum_def = self - .package_items - .lookup_type(&[Self::unqualify(enum_name)]); + let short_enum = Self::unqualify(enum_name); + let enum_def = self.package_items.lookup_type(&[], &short_enum); let related = enum_def .map(|def| vec![(RelatedLocation::Item(def), "enum defined here")]) .unwrap_or_default(); @@ -2746,15 +2730,12 @@ impl<'db> TypeInferenceBuilder<'db> { qtn: &crate::ty::QualifiedTypeName, ) -> Option> { let db = self.context.db(); - let short = Self::unqualify(qtn); let items = if *qtn.package() == self.package_id.name(db) { self.package_items } else { self.res_ctx.items_for_package(db, qtn.package())? }; - let mut lookup_path: Vec = qtn.namespace().clone(); - lookup_path.push(short); - match items.lookup_type(&lookup_path)? { + match items.lookup_type(qtn.namespace(), qtn.name())? { Definition::Enum(enum_loc) => Some(enum_loc), _ => None, } @@ -2972,17 +2953,14 @@ impl<'db> TypeInferenceBuilder<'db> { // When there is a non-empty item_path, try class/enum member resolution // first (e.g. `baml.Array.length` → Array class, then method "length"). if !item_path.is_empty() { - if let Some(def) = pkg_items.lookup_type(item_path) { + let item_name = item_path.last().expect("non-empty item_path"); + if let Some(def) = pkg_items.lookup_type(&item_path[..item_path.len() - 1], item_name) { match def { Definition::Class(_class_loc) => { if first.as_str() == "root" || first.as_str() == self.package_id.name(db).as_str() { - let class_qtn = crate::lower_type_expr::qualify_def( - db, - def, - item_path.last().unwrap(), - ); + let class_qtn = crate::lower_type_expr::qualify_def(db, def, item_name); let base_ty = Ty::Class(class_qtn, TyAttr::default()); return Some(self.resolve_member(&base_ty, member, at)); } @@ -2991,18 +2969,14 @@ impl<'db> TypeInferenceBuilder<'db> { return self .resolve_builtin_member(&class_path, &[], member, at) .or_else(|| { - let class_qtn = crate::lower_type_expr::qualify_def( - db, - def, - item_path.last().unwrap(), - ); + let class_qtn = + crate::lower_type_expr::qualify_def(db, def, item_name); let base_ty = Ty::Class(class_qtn, TyAttr::default()); Some(self.resolve_member(&base_ty, member, at)) }); } Definition::Enum(_) => { - let enum_qtn = - crate::lower_type_expr::qualify_def(db, def, item_path.last().unwrap()); + let enum_qtn = crate::lower_type_expr::qualify_def(db, def, item_name); let base_ty = Ty::Enum(enum_qtn, TyAttr::default()); return Some(self.resolve_member(&base_ty, member, at)); } @@ -3102,7 +3076,8 @@ impl<'db> TypeInferenceBuilder<'db> { // Look up the class by path (e.g. &["Array"] or &["media", "Image"]). let path: Vec = class_path.iter().map(baml_base::Name::new).collect(); - let def = baml_items.lookup_type(&path)?; + let item = path.last().expect("non-empty class_path"); + let def = baml_items.lookup_type(&path[..path.len() - 1], item)?; let baml_compiler2_hir::contributions::Definition::Class(class_loc) = def else { return None; }; @@ -3270,7 +3245,6 @@ impl<'db> TypeInferenceBuilder<'db> { /// not just the current file's package. fn lookup_enum_variants(&self, enum_name: &crate::ty::QualifiedTypeName) -> Vec { let db = self.context.db(); - let short = Self::unqualify(enum_name); // Resolve the package that owns the enum via res_ctx. let items = if *enum_name.package() == self.package_id.name(db) { @@ -3282,10 +3256,9 @@ impl<'db> TypeInferenceBuilder<'db> { } }; - // Build the lookup path: namespace segments + enum name. - let mut lookup_path: Vec = enum_name.namespace().clone(); - lookup_path.push(short); - if let Some(Definition::Enum(enum_loc)) = items.lookup_type(&lookup_path) { + if let Some(Definition::Enum(enum_loc)) = + items.lookup_type(enum_name.namespace(), enum_name.name()) + { let file = enum_loc.file(db); let item_tree = baml_compiler2_ppir::file_item_tree(db, file); let enum_data = &item_tree[enum_loc.id(db)]; diff --git a/baml_language/crates/baml_compiler2_tir/src/inference.rs b/baml_language/crates/baml_compiler2_tir/src/inference.rs index 4acff0dd52..57f13a1ef6 100644 --- a/baml_language/crates/baml_compiler2_tir/src/inference.rs +++ b/baml_language/crates/baml_compiler2_tir/src/inference.rs @@ -302,9 +302,8 @@ pub fn infer_scope_types<'db>( enclosing_class_name .as_ref() .and_then(|cn| { - let mut ns_path = pkg_info.namespace_path.clone(); - ns_path.push(cn.clone()); - pkg_items.lookup_type(&ns_path).map(|def| { + let ns_path = &pkg_info.namespace_path; + pkg_items.lookup_type(ns_path, cn).map(|def| { Ty::Class( crate::lower_type_expr::qualify_def(db, def, cn), TyAttr::default(), diff --git a/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs b/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs index c531f5b924..3d8ddc388d 100644 --- a/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs +++ b/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs @@ -51,16 +51,19 @@ pub fn lower_type_expr_in_ns( ) -> Ty { match type_expr { TypeExpr::Path { segments, .. } => { + let item = segments.last().expect("non-empty path"); + let seg_ns = &segments[..segments.len() - 1]; // When we have a namespace context, try the qualified path first. - // e.g. for ns_context=["fs"], segments=["File"], try ["fs", "File"]. + // e.g. for ns_context=["fs"], segments=["File"], try namespace ["fs"] item "File". let resolved = if !ns_context.is_empty() { - let qualified: Vec = - ns_context.iter().chain(segments.iter()).cloned().collect(); - package_items - .lookup_type(&qualified) - .or_else(|| package_items.lookup_type(segments)) + let ns: Vec = + ns_context.iter().chain(seg_ns.iter()).cloned().collect(); + package_items.lookup_type(&ns, item).or_else(|| { + // Bare fallback — resolve in root namespace with segments as path + package_items.lookup_type(seg_ns, item) + }) } else { - package_items.lookup_type(segments) + package_items.lookup_type(seg_ns, item) }; // Cross-package fallback: if not found in the current package and // the first segment is a known package name, look in that package @@ -69,11 +72,11 @@ pub fn lower_type_expr_in_ns( let resolved = resolved.or_else(|| { if segments.len() >= 2 { if segments[0].as_str() == "root" { - package_items.lookup_type(&segments[1..]) + package_items.lookup_type(&segments[1..segments.len() - 1], item) } else { let pkg_id = PackageId::new(db, segments[0].clone()); let pkg = baml_compiler2_ppir::package_items(db, pkg_id); - pkg.lookup_type(&segments[1..]) + pkg.lookup_type(&segments[1..segments.len() - 1], item) } } else { None diff --git a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs index 5f933bb1cc..f9f6b741e0 100644 --- a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs +++ b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs @@ -149,38 +149,16 @@ unsafe impl salsa::Update for PackageResolutionContext<'_> { // ── PackageInterface lookup helpers ──────────────────────────────────────── impl PackageInterface { - /// Look up a type by path, using the same namespace-prefix-split logic as `PackageItems`. - pub fn lookup_type(&self, path: &[Name]) -> Option<&ExportedType> { - if path.is_empty() { - return None; - } - for split in (0..path.len()).rev() { - let ns_path = &path[..split]; - let name = &path[split]; - if let Some(ns) = self.types.get(ns_path) { - if let Some(exported) = ns.get(name) { - return Some(exported); - } - } - } - None + /// Look up a type by explicit namespace and item name. + /// + /// Single hash lookup — no split-loop ambiguity. + pub fn lookup_type(&self, namespace: &[Name], item: &Name) -> Option<&ExportedType> { + self.types.get(namespace)?.get(item) } - /// Look up a function by path. - pub fn lookup_function(&self, path: &[Name]) -> Option<&ExportedFunction> { - if path.is_empty() { - return None; - } - for split in (0..path.len()).rev() { - let ns_path = &path[..split]; - let name = &path[split]; - if let Some(ns) = self.functions.get(ns_path) { - if let Some(exported) = ns.get(name) { - return Some(exported); - } - } - } - None + /// Look up a function by explicit namespace and item name. + pub fn lookup_function(&self, namespace: &[Name], item: &Name) -> Option<&ExportedFunction> { + self.functions.get(namespace)?.get(item) } /// Look up a type by short name across all namespaces. @@ -550,31 +528,36 @@ impl<'db> PackageResolutionContext<'db> { path: &[Name], ns_context: &[Name], ) -> Option<(ResolvedSource, Ty)> { + let item = path.last()?; // Try namespace-qualified path first if !ns_context.is_empty() { - let mut qualified = ns_context.to_vec(); - qualified.extend_from_slice(path); - if let Some(result) = self.resolve_type_in_own_then_deps(db, &qualified) { + let ns: Vec<_> = ns_context + .iter() + .chain(path[..path.len() - 1].iter()) + .cloned() + .collect(); + if let Some(result) = self.resolve_type_in_own_then_deps(db, &ns, item) { return Some(result); } } // Try unqualified path - if let Some(result) = self.resolve_type_in_own_then_deps(db, path) { + if let Some(result) = self.resolve_type_in_own_then_deps(db, &path[..path.len() - 1], item) + { return Some(result); } // Try package-prefixed path (first segment is package name) if path.len() >= 2 { if path[0].as_str() == "root" { - if let Some(def) = self.own_items.lookup_type(&path[1..]) { + if let Some(def) = self.own_items.lookup_type(&path[1..path.len() - 1], item) { let ty = def_to_ty(db, def); return Some((ResolvedSource::Item, ty)); } } for (dep_name, dep_iface) in &self.dep_interfaces { if &path[0] == dep_name { - if let Some(exported) = dep_iface.lookup_type(&path[1..]) { + if let Some(exported) = dep_iface.lookup_type(&path[1..path.len() - 1], item) { return Some((ResolvedSource::Builtin, exported.to_ty())); } } @@ -587,14 +570,15 @@ impl<'db> PackageResolutionContext<'db> { fn resolve_type_in_own_then_deps( &self, db: &'db dyn crate::Db, - path: &[Name], + namespace: &[Name], + item: &Name, ) -> Option<(ResolvedSource, Ty)> { - if let Some(def) = self.own_items.lookup_type(path) { + if let Some(def) = self.own_items.lookup_type(namespace, item) { let ty = def_to_ty(db, def); return Some((ResolvedSource::Item, ty)); } for (_dep_name, dep_iface) in &self.dep_interfaces { - if let Some(exported) = dep_iface.lookup_type(path) { + if let Some(exported) = dep_iface.lookup_type(namespace, item) { return Some((ResolvedSource::Builtin, exported.to_ty())); } } @@ -608,18 +592,26 @@ impl<'db> PackageResolutionContext<'db> { path: &[Name], ns_context: &[Name], ) -> Option<(ResolvedSource, Definition<'db>)> { + let item = path.last()?; if !ns_context.is_empty() { - let mut qualified = ns_context.to_vec(); - qualified.extend_from_slice(path); - if let Some(result) = self.resolve_value_in_own(&qualified) { + let ns: Vec<_> = ns_context + .iter() + .chain(path[..path.len() - 1].iter()) + .cloned() + .collect(); + if let Some(result) = self.resolve_value_in_own(&ns, item) { return Some(result); } } - self.resolve_value_in_own(path) + self.resolve_value_in_own(&path[..path.len() - 1], item) } - fn resolve_value_in_own(&self, path: &[Name]) -> Option<(ResolvedSource, Definition<'db>)> { - if let Some(def) = self.own_items.lookup_value(path) { + fn resolve_value_in_own( + &self, + namespace: &[Name], + item: &Name, + ) -> Option<(ResolvedSource, Definition<'db>)> { + if let Some(def) = self.own_items.lookup_value(namespace, item) { return Some((ResolvedSource::Item, def)); } None diff --git a/baml_language/crates/baml_compiler2_tir/src/resolve.rs b/baml_language/crates/baml_compiler2_tir/src/resolve.rs index 6544ef618a..2c2a6d297c 100644 --- a/baml_language/crates/baml_compiler2_tir/src/resolve.rs +++ b/baml_language/crates/baml_compiler2_tir/src/resolve.rs @@ -94,28 +94,24 @@ pub fn resolve_name_at<'db>( let res_ctx = crate::package_interface::package_resolution_context(db, pkg_id); let pkg_items = res_ctx.own_items; - // Build the lookup path: [namespace_path..., name]. // For files with non-empty namespace_path (e.g. ["llm"]), // this resolves bare names only within that namespace. // For root namespace files (namespace_path == []), this is - // equivalent to the previous [name] lookup. - let mut full_path: Vec = pkg_info.namespace_path.clone(); - full_path.push(name.clone()); - - if let Some(def) = pkg_items.lookup_value(&full_path) { + // equivalent to a root lookup. + if let Some(def) = pkg_items.lookup_value(&pkg_info.namespace_path, name) { return ResolvedName::Item(def); } - if let Some(def) = pkg_items.lookup_type(&full_path) { + if let Some(def) = pkg_items.lookup_type(&pkg_info.namespace_path, name) { return ResolvedName::Item(def); } // Check declared dependencies (e.g. `baml` builtins) via res_ctx. for (dep_name, _) in &res_ctx.dep_interfaces { if let Some(dep_items) = res_ctx.items_for_package(db, dep_name) { - if let Some(def) = dep_items.lookup_value(std::slice::from_ref(name)) { + if let Some(def) = dep_items.lookup_value(&[], name) { return ResolvedName::Builtin(def); } - if let Some(def) = dep_items.lookup_type(std::slice::from_ref(name)) { + if let Some(def) = dep_items.lookup_type(&[], name) { return ResolvedName::Builtin(def); } } @@ -165,11 +161,15 @@ pub fn resolve_path_at<'db>( }; let after_pkg = &segments[1..]; + let item = after_pkg + .last() + .expect("multi-segment path has elements after pkg prefix"); + let ns = &after_pkg[..after_pkg.len() - 1]; - if let Some(def) = pkg_items.lookup_value(after_pkg) { + if let Some(def) = pkg_items.lookup_value(ns, item) { return ResolvedName::Builtin(def); } - if let Some(def) = pkg_items.lookup_type(after_pkg) { + if let Some(def) = pkg_items.lookup_type(ns, item) { return ResolvedName::Builtin(def); } diff --git a/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs b/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs index 9500cbf60d..aa17593a36 100644 --- a/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs +++ b/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs @@ -343,7 +343,7 @@ fn throw_fact_from_expr<'db>( type_name: Some(name), .. } => { - if let Some(def) = pkg_items.lookup_type(std::slice::from_ref(name)) { + if let Some(def) = pkg_items.lookup_type(&[], name) { match def { Definition::Class(_) => { Ty::Class(qualify_def(db, def, name), TyAttr::default()) @@ -395,9 +395,10 @@ fn resolve_path_to_ty<'db>( if segments.len() >= 2 { let enum_path = &segments[..segments.len() - 1]; let variant = &segments[segments.len() - 1]; - if let Some(def) = pkg_items.lookup_type(enum_path) { + let enum_name = enum_path.last().expect("enum_path is non-empty"); + let enum_ns = &enum_path[..enum_path.len() - 1]; + if let Some(def) = pkg_items.lookup_type(enum_ns, enum_name) { if let Definition::Enum(_) = def { - let enum_name = &enum_path[enum_path.len() - 1]; let qtn = qualify_def(db, def, enum_name); return Ty::EnumVariant(qtn, variant.clone(), TyAttr::default()); } @@ -406,8 +407,8 @@ fn resolve_path_to_ty<'db>( // Try the full path as a type lookup (handles namespaced types and // single-segment names). - if let Some(def) = pkg_items.lookup_type(segments) { - let name = segments.last().unwrap(); + let name = segments.last().expect("segments is non-empty"); + if let Some(def) = pkg_items.lookup_type(&segments[..segments.len() - 1], name) { return match def { Definition::Class(_) => Ty::Class(qualify_def(db, def, name), TyAttr::default()), Definition::Enum(_) => Ty::Enum(qualify_def(db, def, name), TyAttr::default()), diff --git a/baml_language/crates/baml_lsp2_actions/src/completions.rs b/baml_language/crates/baml_lsp2_actions/src/completions.rs index 4645d9e66b..8c7f7c9abf 100644 --- a/baml_language/crates/baml_lsp2_actions/src/completions.rs +++ b/baml_language/crates/baml_lsp2_actions/src/completions.rs @@ -464,9 +464,8 @@ fn completions_for_ty_members(db: &dyn Db, ty: &Ty) -> Vec { let pkg_info_name = qn.package().as_str(); let pkg_id = PackageId::new(db, Name::new(pkg_info_name)); let pkg = package_items(db, pkg_id); - let path = qn.to_path_in_package(); - let class_def = pkg.lookup_type(&path); + let class_def = pkg.lookup_type(qn.namespace(), qn.name()); let Some(Definition::Class(class_loc)) = class_def else { return Vec::new(); }; @@ -502,9 +501,8 @@ fn completions_for_ty_members(db: &dyn Db, ty: &Ty) -> Vec { // Find the enum and return its variants. let pkg_id = PackageId::new(db, Name::new(qn.package().as_str())); let pkg = package_items(db, pkg_id); - let path = qn.to_path_in_package(); - let enum_def = pkg.lookup_type(&path); + let enum_def = pkg.lookup_type(qn.namespace(), qn.name()); let Some(Definition::Enum(enum_loc)) = enum_def else { return Vec::new(); }; diff --git a/baml_language/crates/baml_lsp2_actions/src/tokens.rs b/baml_language/crates/baml_lsp2_actions/src/tokens.rs index 020f199b33..9c5757fefb 100644 --- a/baml_language/crates/baml_lsp2_actions/src/tokens.rs +++ b/baml_language/crates/baml_lsp2_actions/src/tokens.rs @@ -406,7 +406,7 @@ fn resolve_type_name(db: &dyn Db, file: SourceFile, name: &str) -> SemanticToken let pkg_items = baml_compiler2_hir::package::package_items(db, pkg_id); let name_obj = baml_base::Name::new(name); - match pkg_items.lookup_type(&[name_obj]) { + match pkg_items.lookup_type(&[], &name_obj) { Some(Definition::Class(_)) => SemanticTokenType::Class, Some(Definition::Enum(_)) => SemanticTokenType::Enum, Some(Definition::TypeAlias(_)) => SemanticTokenType::Type, diff --git a/baml_language/crates/baml_tests/src/compiler2_hir.rs b/baml_language/crates/baml_tests/src/compiler2_hir.rs index e30a0acb45..883cc6f60c 100644 --- a/baml_language/crates/baml_tests/src/compiler2_hir.rs +++ b/baml_language/crates/baml_tests/src/compiler2_hir.rs @@ -117,21 +117,57 @@ mod tests { let pkg_id = PackageId::new(&db, Name::new("user")); let items = package_items(&db, pkg_id); - let point_path = vec![Name::new("Point")]; - let dir_path = vec![Name::new("Dir")]; - let missing_path = vec![Name::new("Missing")]; - assert!( - items.lookup_type(&point_path).is_some(), + items.lookup_type(&[], &Name::new("Point")).is_some(), "Point should resolve" ); - assert!(items.lookup_type(&dir_path).is_some(), "Dir should resolve"); assert!( - items.lookup_type(&missing_path).is_none(), + items.lookup_type(&[], &Name::new("Dir")).is_some(), + "Dir should resolve" + ); + assert!( + items.lookup_type(&[], &Name::new("Missing")).is_none(), "Missing should not resolve" ); } + /// The new (namespace, item) API correctly handles namespace-qualified lookups. + #[test] + fn lookup_type_namespace_item_api() { + let mut db = make_db(); + let _f1 = db.add_file("main.baml", "class Config { key string }"); + let _f2 = db.add_file("ns_llm/models.baml", "class Response { text string }"); + + let pkg_id = PackageId::new(&db, Name::new("user")); + let pkg_items = package_items(&db, pkg_id); + + // Response is only in ["llm"] namespace + let response_name = Name::new("Response"); + assert!( + pkg_items + .lookup_type(&[Name::new("llm")], &response_name) + .is_some(), + "lookup_type(['llm'], 'Response') should find it" + ); + assert!( + pkg_items.lookup_type(&[], &response_name).is_none(), + "lookup_type([], 'Response') should not find it in root" + ); + + // Config is only in root namespace + let config_name = Name::new("Config"); + assert!( + pkg_items.lookup_type(&[], &config_name).is_some(), + "lookup_type([], 'Config') should find it in root" + ); + assert!( + pkg_items + .lookup_type(&[Name::new("llm")], &config_name) + .is_none(), + "lookup_type(['llm'], 'Config') should not find it in llm namespace" + ); + } + // ── 2. namespace_items query ────────────────────────────────────────────── /// namespace_items for a specific NamespaceId returns the right symbols. @@ -340,7 +376,7 @@ mod tests { assert_eq!(items.conflicts()[0].name, Name::new("Dup")); // Resolution still works (first wins) - let resolved = items.lookup_type(&[Name::new("Dup")]); + let resolved = items.lookup_type(&[], &Name::new("Dup")); assert!(resolved.is_some()); } diff --git a/baml_language/crates/baml_tests/src/compiler2_tir/mod.rs b/baml_language/crates/baml_tests/src/compiler2_tir/mod.rs index e7f610725b..f11ec4e538 100644 --- a/baml_language/crates/baml_tests/src/compiler2_tir/mod.rs +++ b/baml_language/crates/baml_tests/src/compiler2_tir/mod.rs @@ -745,9 +745,7 @@ pub(crate) mod support { let parent = &index.scopes[parent_idx.index() as usize]; if matches!(parent.kind, ScopeKind::Class) { parent.name.as_ref().and_then(|cn| { - let mut ns_path = ns.to_vec(); - ns_path.push(cn.clone()); - pkg_items.lookup_type(&ns_path).map(|def| { + pkg_items.lookup_type(ns, cn).map(|def| { baml_compiler2_tir::ty::Ty::Class( baml_compiler2_tir::lower_type_expr::qualify_def( db, def, cn, From c4a3f5a122616d0c02c1cb8fb439190aef325fb8 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 14:51:30 -0700 Subject: [PATCH 03/10] Phase 3: remove bare-name fallback, add "did you mean" diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the .or_else() bare fallback from lower_type_expr_in_ns — bare names from child namespaces no longer silently resolve to root. Add suggestions field to TirTypeError::UnresolvedType with namespace scan to emit "did you mean root.Config?" hints. Un-ignore Phase 1 tests. --- .../baml_compiler2_tir/src/infer_context.rs | 23 ++++++++++++-- .../baml_compiler2_tir/src/lower_type_expr.rs | 31 +++++++++++++++---- ...mespaces_bare_name_rejected__04_5_mir.snap | 4 +-- ...namespaces_bare_name_rejected__04_tir.snap | 3 +- ...es_bare_name_rejected__05_diagnostics.snap | 10 +++++- ...spaces_bare_name_rejected__06_codegen.snap | 3 +- .../baml_tests__stream_types__04_tir.snap | 2 +- .../baml_tests/src/compiler2_tir/phase5.rs | 2 -- 8 files changed, 59 insertions(+), 19 deletions(-) diff --git a/baml_language/crates/baml_compiler2_tir/src/infer_context.rs b/baml_language/crates/baml_compiler2_tir/src/infer_context.rs index c2d44dd2ed..230f77beb6 100644 --- a/baml_language/crates/baml_compiler2_tir/src/infer_context.rs +++ b/baml_language/crates/baml_compiler2_tir/src/infer_context.rs @@ -65,7 +65,10 @@ pub enum TirTypeError { operand: Ty, }, /// A type name in a type annotation could not be resolved. - UnresolvedType { name: Name }, + UnresolvedType { + name: Name, + suggestions: Vec, + }, /// Wrong number of arguments in a function call. ArgumentCountMismatch { expected: usize, got: usize }, /// Function body ends without returning a value. @@ -146,8 +149,22 @@ impl fmt::Display for TirTypeError { TirTypeError::InvalidUnaryOp { op, operand } => { write!(f, "operator `{op:?}` cannot be applied to `{operand}`") } - TirTypeError::UnresolvedType { name } => { - write!(f, "unresolved type: {name}") + TirTypeError::UnresolvedType { name, suggestions } => { + if suggestions.is_empty() { + write!(f, "unresolved type: {name}") + } else if suggestions.len() == 1 { + write!( + f, + "unresolved type: {name}. Did you mean `{}`?", + suggestions[0] + ) + } else { + write!( + f, + "unresolved type: {name}. Did you mean one of these: `{}`?", + suggestions.join("`, `") + ) + } } TirTypeError::ArgumentCountMismatch { expected, got } => { write!(f, "expected {expected} argument(s), got {got}") diff --git a/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs b/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs index 3d8ddc388d..9bdcdbd58b 100644 --- a/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs +++ b/baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs @@ -58,10 +58,7 @@ pub fn lower_type_expr_in_ns( let resolved = if !ns_context.is_empty() { let ns: Vec = ns_context.iter().chain(seg_ns.iter()).cloned().collect(); - package_items.lookup_type(&ns, item).or_else(|| { - // Bare fallback — resolve in root namespace with segments as path - package_items.lookup_type(seg_ns, item) - }) + package_items.lookup_type(&ns, item) } else { package_items.lookup_type(seg_ns, item) }; @@ -105,13 +102,35 @@ pub fn lower_type_expr_in_ns( return Ty::TypeVar(segments[0].clone(), TyAttr::default()); } } - let name = segments + let name_str = segments .iter() .map(smol_str::SmolStr::as_str) .collect::>() .join("."); + // Scan all namespaces for the item name to build "did you mean" suggestions. + // Only do this for single-segment bare names — multi-segment paths already + // encode the intended namespace. + let mut suggestions = Vec::new(); + if segments.len() == 1 { + for (ns_path, ns_items) in &package_items.namespaces { + if ns_items.types.contains_key(item) { + if ns_path.is_empty() { + suggestions.push(format!("root.{item}")); + } else { + let ns_str = ns_path + .iter() + .map(smol_str::SmolStr::as_str) + .collect::>() + .join("."); + suggestions.push(format!("root.{ns_str}.{item}")); + } + } + } + suggestions.sort(); + } diagnostics.push(TirTypeError::UnresolvedType { - name: baml_base::Name::new(&name), + name: baml_base::Name::new(&name_str), + suggestions, }); Ty::Unknown { attr: TyAttr::default(), diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap index 9182fc690d..8de32871f6 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap @@ -6,11 +6,9 @@ fn user.llm.UseConfig(cfg: Config) -> void { // Locals: let _0: void // _0 // return let _1: Config // cfg // param - let _2: string bb0: { - _2 = copy _1.0; - _0 = Response { copy _2 }; + _0 = Response { const null }; goto -> bb1; } diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap index ed48925c34..3382779c6d 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap @@ -11,10 +11,11 @@ class user.Config$stream { class user.llm.Response { text: string } -function user.llm.UseConfig(cfg: user.Config) -> user.llm.Response throws never { +function user.llm.UseConfig(cfg: unknown) -> user.llm.Response throws never { { : user.llm.Response Response { text: cfg.key } : user.llm.Response } + !! 187..198: unresolved type: Config. Did you mean `root.Config`? } class user.llm.Response$stream { text: null | string diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap index 40cf564409..03befffee8 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap @@ -2,4 +2,12 @@ source: crates/baml_tests/src/generated_tests.rs --- === COMPILER2 DIAGNOSTICS === -No errors found. + [type] Error: unresolved type: Config. Did you mean `root.Config`? + ╭─[ models.baml:7:22 ] + │ + 7 │ function UseConfig(cfg: Config) -> Response { + │ ─────┬───── + │ ╰─────── unresolved type: Config. Did you mean `root.Config`? + │ + │ Note: Error code: E0001 +───╯ diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap index 7319a247b0..a582c3e13c 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__06_codegen.snap @@ -4,8 +4,7 @@ source: crates/baml_tests/src/generated_tests.rs function user.llm.UseConfig(cfg: Config) -> void { alloc_instance Response copy 0 - load_var cfg - load_field .key + load_const null store_field .text return } diff --git a/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap b/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap index b8c6460aac..5e8fc9f05b 100644 --- a/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap +++ b/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap @@ -385,7 +385,7 @@ class user.foo.NsRefToTop$stream { inner: null | user.Inner$stream status: null | user.Status items: user.Inner$stream[] - alias_ref: null | user.Inner$stream + alias_ref: null | unknown } class user.TopRefToNs { ns_class: user.foo.NsClass diff --git a/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs b/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs index 8dc5dd2453..12409e6b28 100644 --- a/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs +++ b/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs @@ -692,7 +692,6 @@ fn nested_namespace_resolution() { } #[test] -#[ignore] // Passes after Phase 3 removes bare fallback fn bare_name_cross_namespace_rejected() { // Config is in root, but ns_context is ["llm"] — bare "Config" should not resolve use baml_compiler2_tir::lower_type_expr::lower_type_expr_in_ns; @@ -726,7 +725,6 @@ fn bare_name_cross_namespace_rejected() { } #[test] -#[ignore] // Passes after Phase 3 fn multi_segment_bare_path_rejected() { // "ns2.MyClass" from ns1 without root. prefix should fail use baml_compiler2_tir::lower_type_expr::lower_type_expr_in_ns; From 98fc2a4346fc66f328cf07fad754c3e160e0d2c8 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 14:59:33 -0700 Subject: [PATCH 04/10] Phase 4: remove lookup_type_any_ns and unqualify Replace all 9 lookup_type_any_ns(unqualify(qtn)) call sites with lookup_type(qtn.namespace(), qtn.name()). Remove both unqualify functions and both lookup_type_any_ns methods. --- .../crates/baml_compiler2_hir/src/package.rs | 13 -------- .../crates/baml_compiler2_tir/src/builder.rs | 26 +++++++--------- .../src/package_interface.rs | 31 ++++++------------- .../baml_lsp2_actions/src/definition.rs | 7 ++--- .../crates/baml_lsp2_actions/src/usages.rs | 6 ++-- 5 files changed, 26 insertions(+), 57 deletions(-) diff --git a/baml_language/crates/baml_compiler2_hir/src/package.rs b/baml_language/crates/baml_compiler2_hir/src/package.rs index 188ce9ab30..8935aebb0d 100644 --- a/baml_language/crates/baml_compiler2_hir/src/package.rs +++ b/baml_language/crates/baml_compiler2_hir/src/package.rs @@ -143,19 +143,6 @@ impl<'db> PackageItems<'db> { self.namespaces.get(namespace)?.types.get(item).copied() } - /// Look up a type by short name, searching across ALL namespaces. - /// - /// Use when the caller only has a short name (e.g. `"File"`) without - /// knowing which namespace it lives in. Returns the first match found. - pub fn lookup_type_any_ns(&self, name: &Name) -> Option> { - for ns in self.namespaces.values() { - if let Some(def) = ns.types.get(name) { - return Some(*def); - } - } - None - } - /// Look up a value by explicit namespace and item name. /// /// Single hash lookup — no split-loop ambiguity. diff --git a/baml_language/crates/baml_compiler2_tir/src/builder.rs b/baml_language/crates/baml_compiler2_tir/src/builder.rs index 13242f9471..6549f72835 100644 --- a/baml_language/crates/baml_compiler2_tir/src/builder.rs +++ b/baml_language/crates/baml_compiler2_tir/src/builder.rs @@ -2062,11 +2062,6 @@ impl<'db> TypeInferenceBuilder<'db> { } } - /// Extract the short name from a qualified type name for package item lookups. - fn unqualify(qn: &crate::ty::QualifiedTypeName) -> Name { - qn.name().clone() - } - fn infer_literal(lit: &baml_base::Literal) -> Ty { Ty::Literal(lit.clone(), Freshness::Fresh, TyAttr::default()) } @@ -2390,8 +2385,9 @@ impl<'db> TypeInferenceBuilder<'db> { } // Known class but member not found — error - let short = Self::unqualify(class_name); - let class_def = self.package_items.lookup_type(&[], &short); + let class_def = self + .package_items + .lookup_type(class_name.namespace(), class_name.name()); let related = class_def .map(|def| vec![(RelatedLocation::Item(def), "class defined here")]) .unwrap_or_default(); @@ -2425,8 +2421,9 @@ impl<'db> TypeInferenceBuilder<'db> { } // Known enum but variant not found — error - let short_enum = Self::unqualify(enum_name); - let enum_def = self.package_items.lookup_type(&[], &short_enum); + let enum_def = self + .package_items + .lookup_type(enum_name.namespace(), enum_name.name()); let related = enum_def .map(|def| vec![(RelatedLocation::Item(def), "enum defined here")]) .unwrap_or_default(); @@ -2659,11 +2656,12 @@ impl<'db> TypeInferenceBuilder<'db> { class_name: &crate::ty::QualifiedTypeName, ) -> FxHashMap { let mut result = FxHashMap::default(); - let short = Self::unqualify(class_name); let Some(pkg_items_for_class) = self.resolve_class_pkg_items(class_name.package()) else { return result; }; - if let Some(Definition::Class(class_loc)) = pkg_items_for_class.lookup_type_any_ns(&short) { + if let Some(Definition::Class(class_loc)) = + pkg_items_for_class.lookup_type(class_name.namespace(), class_name.name()) + { let file = class_loc.file(self.context.db()); let ns_context = baml_compiler2_hir::file_package::file_package(self.context.db(), file) @@ -2716,9 +2714,8 @@ impl<'db> TypeInferenceBuilder<'db> { &self, qtn: &crate::ty::QualifiedTypeName, ) -> Option> { - let short = Self::unqualify(qtn); let pkg_items = self.resolve_class_pkg_items(qtn.package())?; - match pkg_items.lookup_type_any_ns(&short)? { + match pkg_items.lookup_type(qtn.namespace(), qtn.name())? { Definition::Class(class_loc) => Some(class_loc), _ => None, } @@ -2756,9 +2753,8 @@ impl<'db> TypeInferenceBuilder<'db> { baml_compiler2_hir::loc::ClassLoc<'db>, baml_compiler2_hir::loc::FunctionLoc<'db>, )> { - let short = Self::unqualify(class_name); let pkg_items_for_class = self.resolve_class_pkg_items(class_name.package())?; - let def = pkg_items_for_class.lookup_type_any_ns(&short)?; + let def = pkg_items_for_class.lookup_type(class_name.namespace(), class_name.name())?; let Definition::Class(class_loc) = def else { return None; }; diff --git a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs index f9f6b741e0..11dcb2880e 100644 --- a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs +++ b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs @@ -160,16 +160,6 @@ impl PackageInterface { pub fn lookup_function(&self, namespace: &[Name], item: &Name) -> Option<&ExportedFunction> { self.functions.get(namespace)?.get(item) } - - /// Look up a type by short name across all namespaces. - pub fn lookup_type_any_ns(&self, name: &Name) -> Option<&ExportedType> { - for ns in self.types.values() { - if let Some(exported) = ns.get(name) { - return Some(exported); - } - } - None - } } impl ExportedType { @@ -630,9 +620,8 @@ impl<'db> PackageResolutionContext<'db> { self.lookup_own_class_fields(db, class_name) } else { for (_dep_name, dep_iface) in &self.dep_interfaces { - let short = unqualify(class_name); if let Some(ExportedType::Class { fields, .. }) = - dep_iface.lookup_type_any_ns(&short) + dep_iface.lookup_type(class_name.namespace(), class_name.name()) { return fields.clone(); } @@ -653,12 +642,11 @@ impl<'db> PackageResolutionContext<'db> { self.lookup_own_class_method(db, class_name, method_name) } else { for (_dep_name, dep_iface) in &self.dep_interfaces { - let short = unqualify(class_name); if let Some(ExportedType::Class { methods, generic_params, .. - }) = dep_iface.lookup_type_any_ns(&short) + }) = dep_iface.lookup_type(class_name.namespace(), class_name.name()) { if let Some(method) = methods.iter().find(|m| &m.name == method_name) { return Some(ResolvedMethod { @@ -685,8 +673,10 @@ impl<'db> PackageResolutionContext<'db> { db: &'db dyn crate::Db, class_name: &QualifiedTypeName, ) -> Vec<(Name, Ty)> { - let short = unqualify(class_name); - let Some(def) = self.own_items.lookup_type_any_ns(&short) else { + let Some(def) = self + .own_items + .lookup_type(class_name.namespace(), class_name.name()) + else { return Vec::new(); }; let Definition::Class(class_loc) = def else { @@ -726,8 +716,9 @@ impl<'db> PackageResolutionContext<'db> { class_name: &QualifiedTypeName, method_name: &Name, ) -> Option { - let short = unqualify(class_name); - let def = self.own_items.lookup_type_any_ns(&short)?; + let def = self + .own_items + .lookup_type(class_name.namespace(), class_name.name())?; let Definition::Class(class_loc) = def else { return None; }; @@ -835,7 +826,3 @@ fn def_to_ty<'db>(db: &'db dyn crate::Db, def: Definition<'db>) -> Ty { }, } } - -fn unqualify(qtn: &QualifiedTypeName) -> Name { - qtn.name().clone() -} diff --git a/baml_language/crates/baml_lsp2_actions/src/definition.rs b/baml_language/crates/baml_lsp2_actions/src/definition.rs index 8a55593efb..7a531a57f3 100644 --- a/baml_language/crates/baml_lsp2_actions/src/definition.rs +++ b/baml_language/crates/baml_lsp2_actions/src/definition.rs @@ -382,7 +382,7 @@ fn resolve_field_access_at( /// Cursor is on a constructor literal field (e.g. `data:` in `Success { data: "..." }`). fn resolve_constructor_field_at( db: &dyn Db, - file: SourceFile, + _file: SourceFile, offset: TextSize, token_text: &str, expr_body: &baml_compiler2_ast::ExprBody, @@ -411,10 +411,9 @@ fn resolve_constructor_field_at( }; // Resolve QualifiedTypeName → ClassLoc - let pkg_info = baml_compiler2_hir::file_package::file_package(db, file); - let pkg_id = baml_compiler2_hir::package::PackageId::new(db, pkg_info.package); + let pkg_id = baml_compiler2_hir::package::PackageId::new(db, qtn.package().clone()); let pkg_items = baml_compiler2_hir::package::package_items(db, pkg_id); - let def = pkg_items.lookup_type_any_ns(qtn.name())?; + let def = pkg_items.lookup_type(qtn.namespace(), qtn.name())?; let baml_compiler2_hir::contributions::Definition::Class(class_loc) = def else { return None; }; diff --git a/baml_language/crates/baml_lsp2_actions/src/usages.rs b/baml_language/crates/baml_lsp2_actions/src/usages.rs index 7494f63211..8ccc9e4081 100644 --- a/baml_language/crates/baml_lsp2_actions/src/usages.rs +++ b/baml_language/crates/baml_lsp2_actions/src/usages.rs @@ -424,10 +424,10 @@ fn find_field_definition_usages( }; // Resolve QualifiedTypeName to ClassLoc and compare - let pkg_info = baml_compiler2_hir::file_package::file_package(db, sf); - let pkg_id = baml_compiler2_hir::package::PackageId::new(db, pkg_info.package); + let pkg_id = + baml_compiler2_hir::package::PackageId::new(db, qtn.package().clone()); let pkg_items = baml_compiler2_hir::package::package_items(db, pkg_id); - let Some(def) = pkg_items.lookup_type_any_ns(qtn.name()) else { + let Some(def) = pkg_items.lookup_type(qtn.namespace(), qtn.name()) else { continue; }; let baml_compiler2_hir::contributions::Definition::Class(obj_class_loc) = def From 2d5575fc9f73ed4b0a079447a0245b272db1aff4 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 15:04:37 -0700 Subject: [PATCH 05/10] Phase 5: wire resolve_name_at through PRC, give resolve_value parity - Remove bare-name fallback from PRC::resolve_type for non-root ns - Add root. prefix handling and dep search to PRC::resolve_value - Route resolve_name_at through PRC::resolve_value/resolve_type - Route resolve_path_at through PRC --- .../src/package_interface.rs | 41 ++++++++++-- .../crates/baml_compiler2_tir/src/resolve.rs | 63 ++++++++++--------- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs index 11dcb2880e..b854303909 100644 --- a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs +++ b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs @@ -531,11 +531,15 @@ impl<'db> PackageResolutionContext<'db> { } } - // Try unqualified path - if let Some(result) = self.resolve_type_in_own_then_deps(db, &path[..path.len() - 1], item) - { - return Some(result); + // When ns_context is empty, try unqualified path (same-namespace for root files) + if ns_context.is_empty() { + if let Some(result) = + self.resolve_type_in_own_then_deps(db, &path[..path.len() - 1], item) + { + return Some(result); + } } + // No bare fallback from non-root namespaces — cross-namespace requires explicit qualification // Try package-prefixed path (first segment is package name) if path.len() >= 2 { @@ -578,7 +582,7 @@ impl<'db> PackageResolutionContext<'db> { /// Resolve a function/value by path. Returns the Definition for own-package values. pub fn resolve_value( &self, - _db: &'db dyn crate::Db, + db: &'db dyn crate::Db, path: &[Name], ns_context: &[Name], ) -> Option<(ResolvedSource, Definition<'db>)> { @@ -593,7 +597,32 @@ impl<'db> PackageResolutionContext<'db> { return Some(result); } } - self.resolve_value_in_own(&path[..path.len() - 1], item) + // When ns_context is empty, try unqualified path (same-namespace for root files) + if ns_context.is_empty() { + if let Some(result) = self.resolve_value_in_own(&path[..path.len() - 1], item) { + return Some(result); + } + } + // No bare fallback from non-root namespaces — cross-namespace requires explicit qualification + // root.* prefix handling (parity with resolve_type) + if path.len() >= 2 { + if path[0].as_str() == "root" { + if let Some(def) = self.own_items.lookup_value(&path[1..path.len() - 1], item) { + return Some((ResolvedSource::Item, def)); + } + } + // dep-prefixed search (parity with resolve_type) + for (dep_name, _dep_iface) in &self.dep_interfaces { + if &path[0] == dep_name { + let dep_pkg_id = PackageId::new(db, dep_name.clone()); + let dep_items = package_items(db, dep_pkg_id); + if let Some(def) = dep_items.lookup_value(&path[1..path.len() - 1], item) { + return Some((ResolvedSource::Builtin, def)); + } + } + } + } + None } fn resolve_value_in_own( diff --git a/baml_language/crates/baml_compiler2_tir/src/resolve.rs b/baml_language/crates/baml_compiler2_tir/src/resolve.rs index 2c2a6d297c..a8efb35bc6 100644 --- a/baml_language/crates/baml_compiler2_tir/src/resolve.rs +++ b/baml_language/crates/baml_compiler2_tir/src/resolve.rs @@ -87,32 +87,35 @@ pub fn resolve_name_at<'db>( } } - // At File/Package scope, check package_items via PackageResolutionContext + // At File/Package scope, resolve through PRC if matches!(scope.kind, ScopeKind::File | ScopeKind::Package) { let pkg_info = baml_compiler2_hir::file_package::file_package(db, file); let pkg_id = PackageId::new(db, pkg_info.package.clone()); let res_ctx = crate::package_interface::package_resolution_context(db, pkg_id); - let pkg_items = res_ctx.own_items; - - // For files with non-empty namespace_path (e.g. ["llm"]), - // this resolves bare names only within that namespace. - // For root namespace files (namespace_path == []), this is - // equivalent to a root lookup. - if let Some(def) = pkg_items.lookup_value(&pkg_info.namespace_path, name) { - return ResolvedName::Item(def); - } - if let Some(def) = pkg_items.lookup_type(&pkg_info.namespace_path, name) { - return ResolvedName::Item(def); - } - // Check declared dependencies (e.g. `baml` builtins) via res_ctx. - for (dep_name, _) in &res_ctx.dep_interfaces { - if let Some(dep_items) = res_ctx.items_for_package(db, dep_name) { - if let Some(def) = dep_items.lookup_value(&[], name) { - return ResolvedName::Builtin(def); - } - if let Some(def) = dep_items.lookup_type(&[], name) { - return ResolvedName::Builtin(def); + let name_path = std::slice::from_ref(name); + if let Some((source, def)) = + res_ctx.resolve_value(db, name_path, &pkg_info.namespace_path) + { + return match source { + crate::package_interface::ResolvedSource::Item => ResolvedName::Item(def), + crate::package_interface::ResolvedSource::Builtin => ResolvedName::Builtin(def), + }; + } + // For types, resolve_type returns Ty — we need Definition, so fall back to direct lookup + if let Some((_source, _ty)) = + res_ctx.resolve_type(db, name_path, &pkg_info.namespace_path) + { + let pkg_items = res_ctx.own_items; + if let Some(def) = pkg_items.lookup_type(&pkg_info.namespace_path, name) { + return ResolvedName::Item(def); + } + // The type was found in deps — search deps + for (dep_name, _) in &res_ctx.dep_interfaces { + if let Some(dep_items) = res_ctx.items_for_package(db, dep_name) { + if let Some(def) = dep_items.lookup_type(&[], name) { + return ResolvedName::Builtin(def); + } } } } @@ -161,16 +164,18 @@ pub fn resolve_path_at<'db>( }; let after_pkg = &segments[1..]; - let item = after_pkg - .last() - .expect("multi-segment path has elements after pkg prefix"); - let ns = &after_pkg[..after_pkg.len() - 1]; - - if let Some(def) = pkg_items.lookup_value(ns, item) { + // Route through PRC — ns_context is empty because the full path includes the namespace + if let Some((_source, def)) = res_ctx.resolve_value(db, after_pkg, &[]) { return ResolvedName::Builtin(def); } - if let Some(def) = pkg_items.lookup_type(ns, item) { - return ResolvedName::Builtin(def); + if let Some((_source, _ty)) = res_ctx.resolve_type(db, after_pkg, &[]) { + let item = after_pkg + .last() + .expect("multi-segment path has elements after pkg prefix"); + let ns = &after_pkg[..after_pkg.len() - 1]; + if let Some(def) = pkg_items.lookup_type(ns, item) { + return ResolvedName::Builtin(def); + } } ResolvedName::Unknown From 7ec64d2409bc776dc7c1206a49a93064cf88e034 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 15:08:10 -0700 Subject: [PATCH 06/10] Phase 6: update PPIR resolve_in_package to use new API Replace direct pkg_items.namespaces access with lookup_type(namespace, item) calls. Change resolve_in_package signature to accept pre-split (namespace, item) pair. Update all callers in resolve_qualified_key. --- .../crates/baml_compiler2_ppir/src/expand.rs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/baml_language/crates/baml_compiler2_ppir/src/expand.rs b/baml_language/crates/baml_compiler2_ppir/src/expand.rs index a584957031..1bb37bc3fa 100644 --- a/baml_language/crates/baml_compiler2_ppir/src/expand.rs +++ b/baml_language/crates/baml_compiler2_ppir/src/expand.rs @@ -68,56 +68,63 @@ fn classify_type_cross_pkg(path: &[Name], ctx: &ExpandCtx<'_>) -> Option, ) -> Option> { - if path.is_empty() { - return None; - } - for split in (0..path.len()).rev() { - let ns_path = &path[..split]; - let item_name = &path[split]; - if let Some(ns) = pkg_items.namespaces.get(ns_path) { - if ns.types.contains_key(item_name) { - let mut key = vec![pkg_name.clone()]; - key.extend_from_slice(ns_path); - key.push(item_name.clone()); - return Some(key); - } - } - } - None + pkg_items.lookup_type(namespace, item).map(|_| { + let mut key = vec![pkg_name.clone()]; + key.extend_from_slice(namespace); + key.push(item.clone()); + key + }) } /// Resolve a PPIR type path to its qualified key `[package, ...ns, name]`. /// Handles direct lookup, `root.*` prefix, bare names in non-root namespaces, /// and cross-package references. fn resolve_qualified_key(path: &[Name], ctx: &ExpandCtx<'_>) -> Option> { + if path.is_empty() { + return None; + } + let item = path.last().unwrap(); // 1. Direct lookup in current package - if let Some(key) = resolve_in_package(path, ctx.package_name, ctx.package_items) { + let ns = &path[..path.len() - 1]; + if let Some(key) = resolve_in_package(ns, item, ctx.package_name, ctx.package_items) { return Some(key); } // 2. Handle `root.*` prefix if path.len() >= 2 && path[0].as_str() == "root" { - if let Some(key) = resolve_in_package(&path[1..], ctx.package_name, ctx.package_items) { + let after_root = &path[1..]; + let root_item = after_root.last().unwrap(); + let root_ns = &after_root[..after_root.len() - 1]; + if let Some(key) = + resolve_in_package(root_ns, root_item, ctx.package_name, ctx.package_items) + { return Some(key); } } // 3. Bare name in current (non-root) namespace if path.len() == 1 && !ctx.namespace_path.is_empty() { - let mut ns_qualified: Vec = ctx.namespace_path.to_vec(); - ns_qualified.push(path[0].clone()); - if let Some(key) = resolve_in_package(&ns_qualified, ctx.package_name, ctx.package_items) { + if let Some(key) = resolve_in_package( + ctx.namespace_path, + item, + ctx.package_name, + ctx.package_items, + ) { return Some(key); } } // 4. Cross-package (first segment = package name) if path.len() >= 2 { if let Some(foreign_items) = ctx.all_package_items.get(&path[0]) { - return resolve_in_package(&path[1..], &path[0], foreign_items); + let after_pkg = &path[1..]; + let pkg_item = after_pkg.last().unwrap(); + let pkg_ns = &after_pkg[..after_pkg.len() - 1]; + return resolve_in_package(pkg_ns, pkg_item, &path[0], foreign_items); } } None From 175fe14364650a524bd916775d39a9f8b73780ae Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 15:16:40 -0700 Subject: [PATCH 07/10] Phase 7: thread namespace context through MIR lowering and LSP tokens Use pkg_info.namespace_path instead of &[] in MIR lowering and LSP semantic token resolution. Fixes self parameter and return type resolution for functions in non-root namespaces. --- .../crates/baml_compiler2_mir/src/lower.rs | 53 +++++++++--- .../crates/baml_lsp2_actions/src/tokens.rs | 2 +- .../baml_tests____baml_std____04_5_mir.snap | 82 +++++++++---------- .../baml_tests____baml_std____06_codegen.snap | 58 ++++++------- ...mespaces_bare_name_rejected__04_5_mir.snap | 6 +- ...aml_tests__namespaces_basic__04_5_mir.snap | 4 +- ...s__namespaces_root_fallback__04_5_mir.snap | 4 +- 7 files changed, 119 insertions(+), 90 deletions(-) diff --git a/baml_language/crates/baml_compiler2_mir/src/lower.rs b/baml_language/crates/baml_compiler2_mir/src/lower.rs index 049c36018e..249c3bd6ed 100644 --- a/baml_language/crates/baml_compiler2_mir/src/lower.rs +++ b/baml_language/crates/baml_compiler2_mir/src/lower.rs @@ -786,12 +786,19 @@ impl<'db> LoweringContext<'db> { /// Used for `TypedBinding` patterns where TIR may not have populated the /// bindings map (e.g. catch arm and match arm patterns). fn resolve_type_annotation(&self, ty_expr: &baml_compiler2_ast::TypeExpr) -> Ty { - use baml_compiler2_tir::lower_type_expr::lower_type_expr; + use baml_compiler2_tir::lower_type_expr::lower_type_expr_in_ns; let pkg_info = file_package(self.db, self.file); let pkg_id = PackageId::new(self.db, pkg_info.package); let pkg_items = package_items(self.db, pkg_id); let mut diags = Vec::new(); - let tir_ty = lower_type_expr(self.db, ty_expr, pkg_items, &[], &mut diags); + let tir_ty = lower_type_expr_in_ns( + self.db, + ty_expr, + pkg_items, + &pkg_info.namespace_path, + &[], + &mut diags, + ); convert_tir2_ty(&tir_ty, &self.type_aliases, &self.recursive_aliases) } } @@ -800,7 +807,7 @@ impl<'db> LoweringContext<'db> { impl LoweringContext<'_> { fn lower_function_body(&mut self) -> MirFunction { - use baml_compiler2_tir::lower_type_expr::lower_type_expr; + use baml_compiler2_tir::lower_type_expr::lower_type_expr_in_ns; let func_loc = self .func_loc @@ -817,7 +824,14 @@ impl LoweringContext<'_> { .as_ref() .map(|te| { let mut diags = Vec::new(); - let tir_ty = lower_type_expr(self.db, te, pkg_items, &[], &mut diags); + let tir_ty = lower_type_expr_in_ns( + self.db, + te, + pkg_items, + &pkg_info.namespace_path, + &[], + &mut diags, + ); convert_tir2_ty(&tir_ty, &self.type_aliases, &self.recursive_aliases) }) .unwrap_or(Ty::Null { @@ -855,20 +869,35 @@ impl LoweringContext<'_> { enclosing_class_name .as_ref() .and_then(|cn| { - pkg_items.lookup_type(&[], cn).map(|def| { - let tir_ty = baml_compiler2_tir::ty::Ty::Class( - baml_compiler2_tir::lower_type_expr::qualify_def(self.db, def, cn), - baml_compiler2_tir::ty::TyAttr::default(), - ); - convert_tir2_ty(&tir_ty, &self.type_aliases, &self.recursive_aliases) - }) + pkg_items + .lookup_type(&pkg_info.namespace_path, cn) + .map(|def| { + let tir_ty = baml_compiler2_tir::ty::Ty::Class( + baml_compiler2_tir::lower_type_expr::qualify_def( + self.db, def, cn, + ), + baml_compiler2_tir::ty::TyAttr::default(), + ); + convert_tir2_ty( + &tir_ty, + &self.type_aliases, + &self.recursive_aliases, + ) + }) }) .unwrap_or(Ty::Null { attr: TyAttr::default(), }) } else { let mut diags = Vec::new(); - let tir_ty = lower_type_expr(self.db, param_te, pkg_items, &[], &mut diags); + let tir_ty = lower_type_expr_in_ns( + self.db, + param_te, + pkg_items, + &pkg_info.namespace_path, + &[], + &mut diags, + ); convert_tir2_ty(&tir_ty, &self.type_aliases, &self.recursive_aliases) }; let local = self diff --git a/baml_language/crates/baml_lsp2_actions/src/tokens.rs b/baml_language/crates/baml_lsp2_actions/src/tokens.rs index 9c5757fefb..319d019759 100644 --- a/baml_language/crates/baml_lsp2_actions/src/tokens.rs +++ b/baml_language/crates/baml_lsp2_actions/src/tokens.rs @@ -406,7 +406,7 @@ fn resolve_type_name(db: &dyn Db, file: SourceFile, name: &str) -> SemanticToken let pkg_items = baml_compiler2_hir::package::package_items(db, pkg_id); let name_obj = baml_base::Name::new(name); - match pkg_items.lookup_type(&[], &name_obj) { + match pkg_items.lookup_type(&pkg_info.namespace_path, &name_obj) { Some(Definition::Class(_)) => SemanticTokenType::Class, Some(Definition::Enum(_)) => SemanticTokenType::Enum, Some(Definition::TypeAlias(_)) => SemanticTokenType::Type, diff --git a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap index da3890b6ee..c4bb8179a8 100644 --- a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap +++ b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap @@ -100,10 +100,10 @@ fn baml.fs.File.read = builtin(io) fn baml.http.fetch = builtin(io) -fn baml.http.Response.ok(self: null) -> bool { +fn baml.http.Response.ok(self: baml.http.Response) -> bool { // Locals: let _0: bool // _0 // return - let _1: null // self // param + let _1: baml.http.Response // self // param let _2: bool let _3: int let _4: int @@ -134,10 +134,10 @@ fn baml.http.send = builtin(io) fn baml.http.Response.text = builtin(io) -fn baml.llm.build_request(client: void, function_name: string, args: map) -> baml.http.Request { +fn baml.llm.build_request(client: baml.llm.Client, function_name: string, args: map) -> baml.http.Request { // Locals: let _0: baml.http.Request // _0 // return - let _1: void // client // param + let _1: baml.llm.Client // client // param let _2: string // function_name // param let _3: map // args // param let _4: baml.llm.PrimitiveClient // primitive_client @@ -173,10 +173,10 @@ fn baml.llm.build_request(client: void, function_name: string, args: map) -> void { +fn baml.llm.call_llm_function(client: baml.llm.Client, function_name: string, args: map) -> void { // Locals: let _0: void // _0 // return - let _1: void // client // param + let _1: baml.llm.Client // client // param let _2: string // function_name // param let _3: map // args // param let _4: string // jinja_string @@ -211,10 +211,10 @@ fn baml.llm.call_llm_function(client: void, function_name: string, args: map) -> void { +fn baml.llm.render_prompt(client: baml.llm.Client, function_name: string, args: map) -> baml.llm.PromptAst { // Locals: - let _0: void // _0 // return - let _1: void // client // param + let _0: baml.llm.PromptAst // _0 // return + let _1: baml.llm.Client // client // param let _2: string // function_name // param let _3: map // args // param let _4: string // jinja_string @@ -226,7 +226,7 @@ fn baml.llm.render_prompt(client: void, function_name: string, args: map let _11: baml.llm.PrimitiveClient let _12: baml.llm.PromptAst - let _13: future + let _13: future bb0: { _5 = dispatch_future const fn baml.llm.get_jinja_template(copy _2) -> bb1; @@ -269,10 +269,10 @@ fn baml.llm.render_prompt(client: void, function_name: string, args: map int { +fn baml.llm.PlannerState.rr_local_offset(self: baml.llm.PlannerState, client_name: string) -> int { // Locals: let _0: int // _0 // return - let _1: null // self // param + let _1: baml.llm.PlannerState // self // param let _2: string // client_name // param let _3: int // offset let _4: string[] @@ -333,10 +333,10 @@ fn baml.llm.PlannerState.rr_local_offset(self: null, client_name: string) -> int } } -fn baml.llm.PlannerState.rr_pick_index(self: null, client_name: string, counter: int, sub_client_count: int) -> int { +fn baml.llm.PlannerState.rr_pick_index(self: baml.llm.PlannerState, client_name: string, counter: int, sub_client_count: int) -> int { // Locals: let _0: int // _0 // return - let _1: null // self // param + let _1: baml.llm.PlannerState // self // param let _2: string // client_name // param let _3: int // counter // param let _4: int // sub_client_count // param @@ -367,10 +367,10 @@ fn baml.llm.PlannerState.rr_pick_index(self: null, client_name: string, counter: } } -fn baml.llm.Client.build_attempt(self: null) -> void[] { +fn baml.llm.Client.build_attempt(self: baml.llm.Client) -> baml.llm.OrchestrationStep[] { // Locals: - let _0: void[] // _0 // return - let _1: null // self // param + let _0: baml.llm.OrchestrationStep[] // _0 // return + let _1: baml.llm.Client // self // param let _2: void // planner_state let _3: void[] let _4: void @@ -391,11 +391,11 @@ fn baml.llm.Client.build_attempt(self: null) -> void[] { } } -fn baml.llm.Client.build_attempt_with_state(self: null, planner_state: void) -> void[] { +fn baml.llm.Client.build_attempt_with_state(self: baml.llm.Client, planner_state: baml.llm.PlannerState) -> baml.llm.OrchestrationStep[] { // Locals: - let _0: void[] // _0 // return - let _1: null // self // param - let _2: void // planner_state // param + let _0: baml.llm.OrchestrationStep[] // _0 // return + let _1: baml.llm.Client // self // param + let _2: baml.llm.PlannerState // planner_state // param let _3: baml.llm.ClientType let _4: int let _5: () -> baml.llm.PrimitiveClient // resolve_fn @@ -575,10 +575,10 @@ fn baml.llm.Client.build_attempt_with_state(self: null, planner_state: void) -> } } -fn baml.llm.Client.build_plan(self: null) -> void[] { +fn baml.llm.Client.build_plan(self: baml.llm.Client) -> baml.llm.OrchestrationStep[] { // Locals: - let _0: void[] // _0 // return - let _1: null // self // param + let _0: baml.llm.OrchestrationStep[] // _0 // return + let _1: baml.llm.Client // self // param let _2: void // planner_state let _3: void[] let _4: void @@ -599,14 +599,14 @@ fn baml.llm.Client.build_plan(self: null) -> void[] { } } -fn baml.llm.Client.build_plan_with_state(self: null, planner_state: void) -> void[] { +fn baml.llm.Client.build_plan_with_state(self: baml.llm.Client, planner_state: baml.llm.PlannerState) -> baml.llm.OrchestrationStep[] { // Locals: - let _0: void[] // _0 // return - let _1: null // self // param - let _2: void // planner_state // param + let _0: baml.llm.OrchestrationStep[] // _0 // return + let _1: baml.llm.Client // self // param + let _2: baml.llm.PlannerState // planner_state // param let _3: baml.llm.RetryPolicy? let _4: bool - let _5: void // r + let _5: baml.llm.RetryPolicy // r let _6: baml.llm.OrchestrationStep[] // result let _7: float // current_delay let _8: int @@ -648,7 +648,7 @@ fn baml.llm.Client.build_plan_with_state(self: null, planner_state: void) -> voi bb0: { _3 = copy _1.3; - _4 = is_type(copy _3, Void { attr: TyAttr { sap_parse_without_null: Unset, sap_pending_never: Unset, sap_in_progress_never: Unset, asserts: [] } }); + _4 = is_type(copy _3, Class(TypeName { name: "RetryPolicy", module_path: ["baml", "llm"], display_name: "baml.llm.RetryPolicy" }, TyAttr { sap_parse_without_null: Unset, sap_pending_never: Unset, sap_in_progress_never: Unset, asserts: [] })); branch copy _4 -> [bb5, bb1]; } @@ -793,15 +793,15 @@ fn baml.llm.Client.build_plan_with_state(self: null, planner_state: void) -> voi fn baml.llm.PrimitiveClient.build_request = builtin(io) -fn baml.llm.Client.execute(self: null, context: void, inherited_delay_ms: int) -> void { +fn baml.llm.Client.execute(self: baml.llm.Client, context: baml.llm.ExecutionContext, inherited_delay_ms: int) -> void { // Locals: let _0: void // _0 // return - let _1: null // self // param - let _2: void // context // param + let _1: baml.llm.Client // self // param + let _2: baml.llm.ExecutionContext // context // param let _3: int // inherited_delay_ms // param let _4: baml.llm.RetryPolicy? let _5: bool - let _6: void // r + let _6: baml.llm.RetryPolicy // r let _7: float // current_delay let _8: int let _9: baml.llm.RetryPolicy @@ -838,7 +838,7 @@ fn baml.llm.Client.execute(self: null, context: void, inherited_delay_ms: int) - bb0: { _4 = copy _1.3; - _5 = is_type(copy _4, Void { attr: TyAttr { sap_parse_without_null: Unset, sap_pending_never: Unset, sap_in_progress_never: Unset, asserts: [] } }); + _5 = is_type(copy _4, Class(TypeName { name: "RetryPolicy", module_path: ["baml", "llm"], display_name: "baml.llm.RetryPolicy" }, TyAttr { sap_parse_without_null: Unset, sap_pending_never: Unset, sap_in_progress_never: Unset, asserts: [] })); branch copy _5 -> [bb6, bb1]; } @@ -980,11 +980,11 @@ fn baml.llm.Client.execute(self: null, context: void, inherited_delay_ms: int) - } } -fn baml.llm.Client.execute_once(self: null, context: void, active_delay_ms: int) -> void { +fn baml.llm.Client.execute_once(self: baml.llm.Client, context: baml.llm.ExecutionContext, active_delay_ms: int) -> void { // Locals: let _0: void // _0 // return - let _1: null // self // param - let _2: void // context // param + let _1: baml.llm.Client // self // param + let _2: baml.llm.ExecutionContext // context // param let _3: int // active_delay_ms // param let _4: baml.llm.ClientType let _5: int @@ -1285,10 +1285,10 @@ fn baml.llm.PrimitiveClient.render_prompt = builtin(io) fn baml.llm.PrimitiveClient.specialize_prompt = builtin(io) -fn baml.llm.Client.to_primitive_client(self: null) -> void { +fn baml.llm.Client.to_primitive_client(self: baml.llm.Client) -> baml.llm.PrimitiveClient { // Locals: - let _0: void // _0 // return - let _1: null // self // param + let _0: baml.llm.PrimitiveClient // _0 // return + let _1: baml.llm.Client // self // param let _2: bool let _3: string let _4: void diff --git a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____06_codegen.snap b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____06_codegen.snap index de013d9ca1..4284c6d183 100644 --- a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____06_codegen.snap +++ b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____06_codegen.snap @@ -133,7 +133,7 @@ function baml.fs.open(path: string) -> void { function baml.http.Response.ok(self: null) -> bool { load_var self - load_field .0 + load_field .status_code load_const 200 cmp_op >= store_var _2 @@ -142,7 +142,7 @@ function baml.http.Response.ok(self: null) -> bool { load_var _2 pop_jump_if_false L0 load_var self - load_field .0 + load_field .status_code load_const 300 cmp_op < store_var _0 @@ -173,7 +173,7 @@ function baml.llm.Client.build_attempt(self: null) -> void[] { function baml.llm.Client.build_attempt_with_state(self: null, planner_state: void) -> void[] { load_var self - load_field .1 + load_field .client_type discriminant copy 0 load_const ClientType.Primitive @@ -193,7 +193,7 @@ function baml.llm.Client.build_attempt_with_state(self: null, planner_state: voi L1: pop 1 load_var self - load_field .2 + load_field .sub_clients call baml.Array.length load_const 0 cmp_op == @@ -202,13 +202,13 @@ function baml.llm.Client.build_attempt_with_state(self: null, planner_state: voi L2: load_var self - load_field .0 + load_field .name store_var _32 load_var self - load_field .4 + load_field .counter store_var _33 load_var self - load_field .2 + load_field .sub_clients call baml.Array.length store_var _34 load_var planner_state @@ -218,7 +218,7 @@ function baml.llm.Client.build_attempt_with_state(self: null, planner_state: voi call baml.llm.PlannerState.rr_pick_index store_var idx load_var self - load_field .2 + load_field .sub_clients load_var idx load_array_element load_var planner_state @@ -233,7 +233,7 @@ function baml.llm.Client.build_attempt_with_state(self: null, planner_state: voi alloc_array 0 store_var steps load_var self - load_field .2 + load_field .sub_clients store_var _12 load_const 0 store_var __for_idx @@ -319,11 +319,11 @@ function baml.llm.Client.build_plan(self: null) -> void[] { function baml.llm.Client.build_plan_with_state(self: null, planner_state: void) -> void[] { load_var self - load_field .3 + load_field .retry store_var _3 load_var _3 - pop 1 - load_const false + load_const baml.llm.RetryPolicy + cmp_op instanceof pop_jump_if_false L0 jump L1 @@ -446,11 +446,11 @@ function baml.llm.Client.build_plan_with_state(self: null, planner_state: void) function baml.llm.Client.execute(self: null, context: void, inherited_delay_ms: int) -> void { load_var self - load_field .3 + load_field .retry store_var _4 load_var _4 - pop 1 - load_const false + load_const baml.llm.RetryPolicy + cmp_op instanceof pop_jump_if_false L0 jump L1 @@ -558,7 +558,7 @@ function baml.llm.Client.execute(self: null, context: void, inherited_delay_ms: function baml.llm.Client.execute_once(self: null, context: void, active_delay_ms: int) -> void { load_var self - load_field .1 + load_field .client_type discriminant copy 0 load_const ClientType.Primitive @@ -578,20 +578,20 @@ function baml.llm.Client.execute_once(self: null, context: void, active_delay_ms L1: pop 1 load_var self - load_field .4 + load_field .counter store_var _57 load_var self - load_field .2 + load_field .sub_clients call baml.Array.length store_var _58 load_var self load_var self - load_field .4 + load_field .counter load_const 1 bin_op + - store_field .4 + store_field .counter load_var self - load_field .2 + load_field .sub_clients load_var _57 load_var _58 bin_op % @@ -603,7 +603,7 @@ function baml.llm.Client.execute_once(self: null, context: void, active_delay_ms L2: load_var self - load_field .2 + load_field .sub_clients store_var _46 load_const 0 store_var __for_idx @@ -652,9 +652,9 @@ function baml.llm.Client.execute_once(self: null, context: void, active_delay_ms store_var primitive load_var primitive load_var context - load_field .0 + load_field .jinja_string load_var context - load_field .1 + load_field .args dispatch_future baml.llm.PrimitiveClient.render_prompt await store_var prompt @@ -688,7 +688,7 @@ function baml.llm.Client.execute_once(self: null, context: void, active_delay_ms await store_var body load_var context - load_field .2 + load_field .function_name dispatch_future baml.llm.get_return_type await store_var return_type @@ -724,7 +724,7 @@ function baml.llm.Client.get_constructor(self: null) -> () -> void { function baml.llm.Client.to_primitive_client(self: null) -> void { load_var self - load_field .0 + load_field .name load_const "/" call baml.String.includes pop_jump_if_false L0 @@ -742,7 +742,7 @@ function baml.llm.Client.to_primitive_client(self: null) -> void { copy 0 load_const "Invalid short hand name: " load_var self - load_field .0 + load_field .name bin_op + store_field .message throw @@ -752,7 +752,7 @@ function baml.llm.PlannerState.rr_local_offset(self: null, client_name: string) load_const 0 store_var offset load_var self - load_field .0 + load_field .rr_client_names store_var _4 load_const 0 store_var __for_idx @@ -795,7 +795,7 @@ function baml.llm.PlannerState.rr_pick_index(self: null, client_name: string, co call baml.llm.PlannerState.rr_local_offset store_var local_offset load_var self - load_field .0 + load_field .rr_client_names load_var client_name call baml.Array.push pop 1 diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap index 8de32871f6..27e9fda436 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_5_mir.snap @@ -2,10 +2,10 @@ source: crates/baml_tests/src/generated_tests.rs --- === MIR2 === -fn user.llm.UseConfig(cfg: Config) -> void { +fn user.llm.UseConfig(cfg: void) -> llm.Response { // Locals: - let _0: void // _0 // return - let _1: Config // cfg // param + let _0: llm.Response // _0 // return + let _1: void // cfg // param bb0: { _0 = Response { const null }; diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_basic/baml_tests__namespaces_basic__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_basic/baml_tests__namespaces_basic__04_5_mir.snap index 9464eb80c0..da4eea7342 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_basic/baml_tests__namespaces_basic__04_5_mir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_basic/baml_tests__namespaces_basic__04_5_mir.snap @@ -19,9 +19,9 @@ fn user.GetResponse(cfg: Config) -> llm.Response { } } -fn user.llm.MakeResponse(cfg: Config) -> void { +fn user.llm.MakeResponse(cfg: Config) -> llm.Response { // Locals: - let _0: void // _0 // return + let _0: llm.Response // _0 // return let _1: Config // cfg // param let _2: string diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__04_5_mir.snap index 9182fc690d..046c50bfe9 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__04_5_mir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_root_fallback/baml_tests__namespaces_root_fallback__04_5_mir.snap @@ -2,9 +2,9 @@ source: crates/baml_tests/src/generated_tests.rs --- === MIR2 === -fn user.llm.UseConfig(cfg: Config) -> void { +fn user.llm.UseConfig(cfg: Config) -> llm.Response { // Locals: - let _0: void // _0 // return + let _0: llm.Response // _0 // return let _1: Config // cfg // param let _2: string From 272bb1a909e7745b2849bbac11fce61b013f758b Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 17:39:38 -0700 Subject: [PATCH 08/10] Fix namespace-aware type resolution across builder, throw inference, and match patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - builder.rs: use ns_context instead of &[] for constructor, enum variant, and type-pattern sugar lookups; add enum_name_matches() to resolve dotted enum names (e.g. "root.Status") against QualifiedTypeName in match exhaustiveness - throw_inference.rs: thread ns_context through collect_direct_throws → throw_fact_from_expr → resolve_path_to_ty so throw types resolve in namespaced files - resolve.rs: fix dep type lookup to try namespace_path then &[]; use direct pkg_items lookup for qualified paths instead of routing through PRC - package_interface.rs: filter dep class field/method lookups by package name - expand.rs: requalify_for_caller() to fix cross-namespace alias stream expansion; use alias definition's namespace when recursing into alias bodies - signature.rs: add param_type_spans for precise error span on type annotations - Add comprehensive namespaces_type_resolution test fixture (4 namespaces, same-named types, 0 diagnostics) and namespaces_stream_direct_ref fixture Co-Authored-By: Claude Opus 4.6 (1M context) --- .../baml_compiler2_hir/src/signature.rs | 8 + .../crates/baml_compiler2_ppir/src/expand.rs | 69 +- .../crates/baml_compiler2_tir/src/builder.rs | 66 +- .../baml_compiler2_tir/src/inference.rs | 9 +- .../src/package_interface.rs | 10 +- .../crates/baml_compiler2_tir/src/resolve.rs | 26 +- .../baml_compiler2_tir/src/throw_inference.rs | 70 +- .../namespaces_stream_direct_ref/main.baml | 33 + .../ns_llm/models.baml | 25 + .../namespaces_type_resolution/main.baml | 128 ++ .../ns_auth/auth.baml | 153 ++ .../ns_llm/models.baml | 194 ++ .../ns_llm/ns_openai/client.baml | 142 ++ .../baml_tests____baml_std____04_5_mir.snap | 16 +- .../baml_tests____baml_std____04_tir.snap | 14 +- ...namespaces_bare_name_rejected__04_tir.snap | 2 +- ...es_bare_name_rejected__05_diagnostics.snap | 6 +- ...ces_stream_direct_ref__01_lexer__main.snap | 171 ++ ...m_direct_ref__01_lexer__ns_llm_models.snap | 86 + ...es_stream_direct_ref__02_parser__main.snap | 91 + ..._direct_ref__02_parser__ns_llm_models.snap | 87 + ..._namespaces_stream_direct_ref__03_hir.snap | 36 + ...amespaces_stream_direct_ref__04_5_mir.snap | 63 + ..._namespaces_stream_direct_ref__04_tir.snap | 68 + ...ces_stream_direct_ref__05_diagnostics.snap | 43 + ...espaces_stream_direct_ref__06_codegen.snap | 22 + ...stream_direct_ref__10_formatter__main.snap | 36 + ...rect_ref__10_formatter__ns_llm_models.snap | 28 + ...paces_type_resolution__01_lexer__main.snap | 900 ++++++++++ ...pe_resolution__01_lexer__ns_auth_auth.snap | 1013 +++++++++++ ...e_resolution__01_lexer__ns_llm_models.snap | 1247 +++++++++++++ ...on__01_lexer__ns_llm_ns_openai_client.snap | 978 +++++++++++ ...aces_type_resolution__02_parser__main.snap | 560 ++++++ ...e_resolution__02_parser__ns_auth_auth.snap | 777 ++++++++ ..._resolution__02_parser__ns_llm_models.snap | 840 +++++++++ ...n__02_parser__ns_llm_ns_openai_client.snap | 776 ++++++++ ...s__namespaces_type_resolution__03_hir.snap | 294 ++++ ..._namespaces_type_resolution__04_5_mir.snap | 1559 +++++++++++++++++ ...s__namespaces_type_resolution__04_tir.snap | 618 +++++++ ...paces_type_resolution__05_diagnostics.snap | 5 + ...amespaces_type_resolution__06_codegen.snap | 943 ++++++++++ ...s_type_resolution__10_formatter__main.snap | 135 ++ ...esolution__10_formatter__ns_auth_auth.snap | 158 ++ ...solution__10_formatter__ns_llm_models.snap | 205 +++ ...10_formatter__ns_llm_ns_openai_client.snap | 146 ++ .../baml_tests__stream_types__04_tir.snap | 2 +- ...aml_tests__unknown_type_error__04_tir.snap | 2 +- ...s__unknown_type_error__05_diagnostics.snap | 6 +- .../baml_tests/src/compiler2_tir/phase3a.rs | 2 +- 49 files changed, 12786 insertions(+), 82 deletions(-) create mode 100644 baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/main.baml create mode 100644 baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/ns_llm/models.baml create mode 100644 baml_language/crates/baml_tests/projects/namespaces_type_resolution/main.baml create mode 100644 baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_auth/auth.baml create mode 100644 baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/models.baml create mode 100644 baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/ns_openai/client.baml create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__03_hir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_5_mir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_tir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__05_diagnostics.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__06_codegen.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_auth_auth.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_ns_openai_client.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_auth_auth.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_ns_openai_client.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__03_hir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_5_mir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_tir.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__05_diagnostics.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__06_codegen.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__main.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_auth_auth.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_models.snap create mode 100644 baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_ns_openai_client.snap diff --git a/baml_language/crates/baml_compiler2_hir/src/signature.rs b/baml_language/crates/baml_compiler2_hir/src/signature.rs index 1ae39b1a19..900b70a05e 100644 --- a/baml_language/crates/baml_compiler2_hir/src/signature.rs +++ b/baml_language/crates/baml_compiler2_hir/src/signature.rs @@ -37,6 +37,9 @@ pub struct FunctionSignature { pub struct SignatureSourceMap { /// One span per parameter, parallel to `FunctionSignature::params`. pub param_spans: Vec, + /// One span per parameter's type expression (just the type, not the name). + /// `None` when the parameter has no explicit type annotation. + pub param_type_spans: Vec>, /// Span of the return type annotation, if present. pub return_type_span: Option, /// Span of the throws type annotation, if present. @@ -79,6 +82,11 @@ fn function_signature_with_source_map<'db>( // Build source map — spans only (separate for early-cutoff) let source_map = SignatureSourceMap { param_spans: func_data.params.iter().map(|p| p.span).collect(), + param_type_spans: func_data + .params + .iter() + .map(|p| p.type_expr.as_ref().map(|te| te.span)) + .collect(), return_type_span: func_data.return_type.as_ref().map(|te| te.span), throws_type_span: func_data.throws.as_ref().map(|te| te.span), }; diff --git a/baml_language/crates/baml_compiler2_ppir/src/expand.rs b/baml_language/crates/baml_compiler2_ppir/src/expand.rs index 1bb37bc3fa..6c098f005c 100644 --- a/baml_language/crates/baml_compiler2_ppir/src/expand.rs +++ b/baml_language/crates/baml_compiler2_ppir/src/expand.rs @@ -130,6 +130,50 @@ fn resolve_qualified_key(path: &[Name], ctx: &ExpandCtx<'_>) -> Option None } +/// When a type alias in one namespace resolves to a type in a different +/// namespace, the resulting `Named` path (and paths inside unions/lists/etc.) +/// must be qualified so that `lower_type_expr_in_ns` can find them from the +/// caller's namespace. Prepends `root.` to single-segment `Named` paths when +/// the alias namespace differs from the caller namespace. +fn requalify_for_caller(ty: PpirTy, alias_ns: &[Name], caller_ns: &[Name]) -> PpirTy { + if alias_ns == caller_ns { + return ty; + } + match ty { + PpirTy::Named { path, attrs } if path.len() == 1 && path[0].as_str() != "root" => { + let mut qualified = Vec::with_capacity(alias_ns.len() + 2); + qualified.push(SmolStr::from("root")); + qualified.extend(alias_ns.iter().cloned()); + qualified.extend(path); + PpirTy::Named { + path: qualified, + attrs, + } + } + PpirTy::Union { variants, attrs } => PpirTy::Union { + variants: variants + .into_iter() + .map(|v| requalify_for_caller(v, alias_ns, caller_ns)) + .collect(), + attrs, + }, + PpirTy::List { inner, attrs } => PpirTy::List { + inner: Box::new(requalify_for_caller(*inner, alias_ns, caller_ns)), + attrs, + }, + PpirTy::Optional { inner, attrs } => PpirTy::Optional { + inner: Box::new(requalify_for_caller(*inner, alias_ns, caller_ns)), + attrs, + }, + PpirTy::Map { key, value, attrs } => PpirTy::Map { + key, + value: Box::new(requalify_for_caller(*value, alias_ns, caller_ns)), + attrs, + }, + other => other, + } +} + // ── Context ────────────────────────────────────────────────────────────────── /// Shared context threaded through all stream-expansion functions. @@ -392,11 +436,32 @@ fn stream_expand_inner(ty: &PpirTy, ctx: &ExpandCtx<'_>, depth: u32) -> (PpirTy, if depth < MAX_ALIAS_DEPTH { if let Some(key) = resolve_qualified_key(path, ctx) { if let Some(body) = ctx.alias_bodies.get(&key) { - // Set merged attrs on the resolved body and recurse + // The alias body's paths are relative to the alias + // definition's namespace (key = [pkg, ...ns, name]). + // Recurse with the alias's namespace so that + // classify_type / resolve_qualified_key resolve + // the body's bare names correctly. + let alias_ns = key[1..key.len() - 1].to_vec(); + let alias_ctx = ExpandCtx { + namespace_path: &alias_ns, + ..*ctx + }; let mut resolved = body.clone(); resolved.attrs_mut().stream_must_exist = must_exist; resolved.attrs_mut().stream_done = done; - return stream_expand_inner(&resolved, ctx, depth + 1); + let (result_ty, sap) = + stream_expand_inner(&resolved, &alias_ctx, depth + 1); + // The result's Named paths are relative to alias_ns. + // If the caller is in a different namespace, qualify + // them so lower_type_expr_in_ns can resolve them. + return ( + requalify_for_caller( + result_ty, + &alias_ns, + ctx.namespace_path, + ), + sap, + ); } } } diff --git a/baml_language/crates/baml_compiler2_tir/src/builder.rs b/baml_language/crates/baml_compiler2_tir/src/builder.rs index 47818db250..16d0686b45 100644 --- a/baml_language/crates/baml_compiler2_tir/src/builder.rs +++ b/baml_language/crates/baml_compiler2_tir/src/builder.rs @@ -366,12 +366,14 @@ impl<'db> TypeInferenceBuilder<'db> { type_name .as_ref() .and_then(|n| { - self.package_items.lookup_type(&[], n).map(|def| { - Ty::Class( - crate::lower_type_expr::qualify_def(self.context.db(), def, n), - TyAttr::default(), - ) - }) + self.package_items + .lookup_type(&self.ns_context, n) + .map(|def| { + Ty::Class( + crate::lower_type_expr::qualify_def(self.context.db(), def, n), + TyAttr::default(), + ) + }) }) .unwrap_or(Ty::Unknown { attr: TyAttr::default(), @@ -1353,10 +1355,12 @@ impl<'db> TypeInferenceBuilder<'db> { } baml_compiler2_ast::Pattern::Null => BTreeSet::from(["null".to_string()]), baml_compiler2_ast::Pattern::EnumVariant { enum_name, variant } => { - // Use the qualified name from scrutinee_ty when available, - // so the case string matches required_match_cases output. + // Use the qualified name from scrutinee_ty when the pattern's + // enum_name matches (bare or namespace-qualified). For + // `root.Status.Ok`, enum_name is "root.Status" — strip the + // `root.` prefix and compare against the QTN's ns+name path. let qualified_enum = match scrutinee_ty { - Ty::Enum(qtn, _) if qtn.name() == enum_name => qtn.to_string(), + Ty::Enum(qtn, _) if Self::enum_name_matches(enum_name, qtn) => qtn.to_string(), _ => enum_name.to_string(), }; BTreeSet::from([format!("{qualified_enum}.{variant}")]) @@ -1469,11 +1473,11 @@ impl<'db> TypeInferenceBuilder<'db> { } baml_compiler2_ast::Pattern::EnumVariant { enum_name, variant } => { if let Ty::Enum(qn, _) = scrutinee_ty { - if qn.name() == enum_name { + if Self::enum_name_matches(enum_name, qn) { return Ty::EnumVariant(qn.clone(), variant.clone(), TyAttr::default()); } } - if let Some(def) = self.package_items.lookup_type(&[], enum_name) { + if let Some(def) = self.package_items.lookup_type(&self.ns_context, enum_name) { if matches!(def, Definition::Enum(_)) { return Ty::EnumVariant( crate::lower_type_expr::qualify_def(self.context.db(), def, enum_name), @@ -1525,7 +1529,39 @@ impl<'db> TypeInferenceBuilder<'db> { matches!( name.as_str(), "int" | "float" | "string" | "bool" | "null" | "image" | "audio" | "video" | "pdf" - ) || self.package_items.lookup_type(&[], name).is_some() + ) || self + .package_items + .lookup_type(&self.ns_context, name) + .is_some() + } + + /// Check if a pattern's `enum_name` (which may be dotted like `"root.Status"` or + /// `"root.llm.Status"`) refers to the same enum as a `QualifiedTypeName`. + fn enum_name_matches(enum_name: &Name, qtn: &crate::ty::QualifiedTypeName) -> bool { + // Bare name match: "Status" == qtn.name() + if qtn.name() == enum_name { + return true; + } + // Dotted name: split on "." and compare + let parts: Vec<&str> = enum_name.as_str().split('.').collect(); + if parts.len() < 2 { + return false; + } + let name = parts[parts.len() - 1]; + let path = &parts[..parts.len() - 1]; + // Strip leading "root" if present + let ns_parts = if path.first() == Some(&"root") { + &path[1..] + } else { + path + }; + // Compare namespace and name + name == qtn.name().as_str() + && ns_parts.len() == qtn.namespace().len() + && ns_parts + .iter() + .zip(qtn.namespace().iter()) + .all(|(a, b): (&&str, &Name)| *a == b.as_str()) } fn catch_base_throw_types(&self, base_expr_id: ExprId, body: &ExprBody) -> BTreeSet { @@ -1628,8 +1664,10 @@ impl<'db> TypeInferenceBuilder<'db> { } baml_compiler2_ast::Pattern::EnumVariant { enum_name, variant } => { let matches_variant = match throw_fact { - Ty::EnumVariant(qn, v, _) => qn.name() == enum_name && v == variant, - Ty::Enum(qn, _) => qn.name() == enum_name, + Ty::EnumVariant(qn, v, _) => { + Self::enum_name_matches(enum_name, qn) && v == variant + } + Ty::Enum(qn, _) => Self::enum_name_matches(enum_name, qn), _ => false, }; if matches_variant { diff --git a/baml_language/crates/baml_compiler2_tir/src/inference.rs b/baml_language/crates/baml_compiler2_tir/src/inference.rs index 57f13a1ef6..38c5c0d9c9 100644 --- a/baml_language/crates/baml_compiler2_tir/src/inference.rs +++ b/baml_language/crates/baml_compiler2_tir/src/inference.rs @@ -324,8 +324,13 @@ pub fn infer_scope_types<'db>( &mut param_diags, ); if !param_diags.is_empty() { - let span = - sig_sm.param_spans.get(i).copied().unwrap_or_default(); + let span = sig_sm + .param_type_spans + .get(i) + .copied() + .flatten() + .or_else(|| sig_sm.param_spans.get(i).copied()) + .unwrap_or_default(); for diag in param_diags { builder.report_at_span(diag, span); } diff --git a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs index b854303909..580ce355a7 100644 --- a/baml_language/crates/baml_compiler2_tir/src/package_interface.rs +++ b/baml_language/crates/baml_compiler2_tir/src/package_interface.rs @@ -648,7 +648,10 @@ impl<'db> PackageResolutionContext<'db> { if class_pkg.as_str() == self.own_package_name.as_str() { self.lookup_own_class_fields(db, class_name) } else { - for (_dep_name, dep_iface) in &self.dep_interfaces { + for (dep_name, dep_iface) in &self.dep_interfaces { + if dep_name != class_pkg { + continue; + } if let Some(ExportedType::Class { fields, .. }) = dep_iface.lookup_type(class_name.namespace(), class_name.name()) { @@ -670,7 +673,10 @@ impl<'db> PackageResolutionContext<'db> { if class_pkg.as_str() == self.own_package_name.as_str() { self.lookup_own_class_method(db, class_name, method_name) } else { - for (_dep_name, dep_iface) in &self.dep_interfaces { + for (dep_name, dep_iface) in &self.dep_interfaces { + if dep_name != class_pkg { + continue; + } if let Some(ExportedType::Class { methods, generic_params, diff --git a/baml_language/crates/baml_compiler2_tir/src/resolve.rs b/baml_language/crates/baml_compiler2_tir/src/resolve.rs index a8efb35bc6..3484c5f019 100644 --- a/baml_language/crates/baml_compiler2_tir/src/resolve.rs +++ b/baml_language/crates/baml_compiler2_tir/src/resolve.rs @@ -110,10 +110,14 @@ pub fn resolve_name_at<'db>( if let Some(def) = pkg_items.lookup_type(&pkg_info.namespace_path, name) { return ResolvedName::Item(def); } - // The type was found in deps — search deps + // The type was found in deps — search deps. + // Dep builtins are in the root namespace (&[]). for (dep_name, _) in &res_ctx.dep_interfaces { if let Some(dep_items) = res_ctx.items_for_package(db, dep_name) { - if let Some(def) = dep_items.lookup_type(&[], name) { + if let Some(def) = dep_items + .lookup_type(&pkg_info.namespace_path, name) + .or_else(|| dep_items.lookup_type(&[], name)) + { return ResolvedName::Builtin(def); } } @@ -164,18 +168,16 @@ pub fn resolve_path_at<'db>( }; let after_pkg = &segments[1..]; - // Route through PRC — ns_context is empty because the full path includes the namespace - if let Some((_source, def)) = res_ctx.resolve_value(db, after_pkg, &[]) { + // The path already includes namespace segments, so look up directly. + let item = after_pkg + .last() + .expect("multi-segment path has elements after pkg prefix"); + let ns = &after_pkg[..after_pkg.len() - 1]; + if let Some(def) = pkg_items.lookup_value(ns, item) { return ResolvedName::Builtin(def); } - if let Some((_source, _ty)) = res_ctx.resolve_type(db, after_pkg, &[]) { - let item = after_pkg - .last() - .expect("multi-segment path has elements after pkg prefix"); - let ns = &after_pkg[..after_pkg.len() - 1]; - if let Some(def) = pkg_items.lookup_type(ns, item) { - return ResolvedName::Builtin(def); - } + if let Some(def) = pkg_items.lookup_type(ns, item) { + return ResolvedName::Builtin(def); } ResolvedName::Unknown diff --git a/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs b/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs index aa17593a36..00ae9543f3 100644 --- a/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs +++ b/baml_language/crates/baml_compiler2_tir/src/throw_inference.rs @@ -92,18 +92,18 @@ pub fn function_throw_sets<'db>( let key = function_key(db, *func_loc, short_name); let sig = baml_compiler2_hir::signature::function_signature(db, *func_loc); let body = baml_compiler2_hir::body::function_body(db, *func_loc); + let func_ns = baml_compiler2_hir::file_package::file_package(db, func_loc.file(db)) + .namespace_path; let declared_throws = sig.throws.as_ref().map(|te| { let mut diags = Vec::new(); - let ns = baml_compiler2_hir::file_package::file_package(db, func_loc.file(db)) - .namespace_path; let item_tree = baml_compiler2_hir::file_item_tree(db, func_loc.file(db)); let func_data = &item_tree[func_loc.id(db)]; let lowered = lower_type_expr_in_ns( db, te, pkg_items, - &ns, + &func_ns, &func_data.generic_params, &mut diags, ); @@ -114,7 +114,7 @@ pub fn function_throw_sets<'db>( let direct = if let Some(declared) = declared_throws.clone() { declared } else if let baml_compiler2_hir::body::FunctionBody::Expr(expr_body) = body.as_ref() { - collect_direct_throws(db, pkg_items, expr_body) + collect_direct_throws(db, pkg_items, &func_ns, expr_body) } else { BTreeSet::new() }; @@ -147,15 +147,15 @@ pub fn function_throw_sets<'db>( let sig = baml_compiler2_hir::signature::function_signature(db, func_loc); let body = baml_compiler2_hir::body::function_body(db, func_loc); + let method_ns = + baml_compiler2_hir::file_package::file_package(db, file).namespace_path; let declared_throws = sig.throws.as_ref().map(|te| { let mut diags = Vec::new(); - let ns_path = - baml_compiler2_hir::file_package::file_package(db, file).namespace_path; let lowered = lower_type_expr_in_ns( db, te, pkg_items, - &ns_path, + &method_ns, &method_data.generic_params, &mut diags, ); @@ -168,7 +168,7 @@ pub fn function_throw_sets<'db>( } else if let baml_compiler2_hir::body::FunctionBody::Expr(expr_body) = body.as_ref() { - collect_direct_throws(db, pkg_items, expr_body) + collect_direct_throws(db, pkg_items, &method_ns, expr_body) } else { BTreeSet::new() }; @@ -264,18 +264,23 @@ fn function_key<'db>( pub fn collect_direct_throws<'db>( db: &'db dyn crate::Db, pkg_items: &PackageItems<'db>, + ns_context: &[Name], body: &ExprBody, ) -> BTreeSet { let mut facts = BTreeSet::new(); for (_, expr) in body.exprs.iter() { if let Expr::Throw { value } = expr { - facts.insert(throw_fact_from_expr(db, pkg_items, *value, body)); + facts.insert(throw_fact_from_expr( + db, pkg_items, ns_context, *value, body, + )); } } for (_, stmt) in body.stmts.iter() { if let baml_compiler2_ast::Stmt::Throw { value } = stmt { - facts.insert(throw_fact_from_expr(db, pkg_items, *value, body)); + facts.insert(throw_fact_from_expr( + db, pkg_items, ns_context, *value, body, + )); } } @@ -322,6 +327,7 @@ pub fn collect_call_targets(body: &ExprBody) -> BTreeSet { fn throw_fact_from_expr<'db>( db: &'db dyn crate::Db, pkg_items: &PackageItems<'db>, + ns_context: &[Name], expr_id: baml_compiler2_ast::ExprId, body: &ExprBody, ) -> Ty { @@ -333,9 +339,11 @@ fn throw_fact_from_expr<'db>( Expr::Literal(Literal::Float(_)) => Ty::Primitive(PrimitiveType::Float, TyAttr::default()), Expr::Literal(Literal::Bool(_)) => Ty::Primitive(PrimitiveType::Bool, TyAttr::default()), Expr::Null => Ty::Primitive(PrimitiveType::Null, TyAttr::default()), - Expr::Path(segments) if !segments.is_empty() => resolve_path_to_ty(db, pkg_items, segments), + Expr::Path(segments) if !segments.is_empty() => { + resolve_path_to_ty(db, pkg_items, ns_context, segments) + } Expr::FieldAccess { .. } => expr_to_path(expr_id, body) - .map(|segments| resolve_path_to_ty(db, pkg_items, &segments)) + .map(|segments| resolve_path_to_ty(db, pkg_items, ns_context, &segments)) .unwrap_or(Ty::Unknown { attr: TyAttr::default(), }), @@ -343,7 +351,7 @@ fn throw_fact_from_expr<'db>( type_name: Some(name), .. } => { - if let Some(def) = pkg_items.lookup_type(&[], name) { + if let Some(def) = pkg_items.lookup_type(ns_context, name) { match def { Definition::Class(_) => { Ty::Class(qualify_def(db, def, name), TyAttr::default()) @@ -381,23 +389,26 @@ fn rewrite_self_target(target: &Name, class_name: &Name) -> Name { fn resolve_path_to_ty<'db>( db: &'db dyn crate::Db, pkg_items: &PackageItems<'db>, + ns_context: &[Name], segments: &[Name], ) -> Ty { // Try treating the last segment as an enum variant and the prefix as - // the enum path. We try progressively shorter prefixes so that - // ["ns", "Status", "HttpError"] → enum_path=["ns", "Status"], variant="HttpError" - // works alongside ["Status", "HttpError"] → enum_path=["Status"], variant="HttpError". - // - // This must run BEFORE the generic lookup because the namespace system - // registers enum variants as types in a child namespace, so - // `lookup_type(&["Status", "HttpError"])` would incorrectly match - // "HttpError" as a standalone enum rather than a variant of Status. + // the enum path. For bare `["Status", "HttpError"]` from a namespaced file, + // try namespace-qualified first, then unqualified. if segments.len() >= 2 { let enum_path = &segments[..segments.len() - 1]; let variant = &segments[segments.len() - 1]; let enum_name = enum_path.last().expect("enum_path is non-empty"); let enum_ns = &enum_path[..enum_path.len() - 1]; - if let Some(def) = pkg_items.lookup_type(enum_ns, enum_name) { + // Try with namespace context for bare enum names + let def = if !ns_context.is_empty() && enum_ns.is_empty() { + pkg_items + .lookup_type(ns_context, enum_name) + .or_else(|| pkg_items.lookup_type(enum_ns, enum_name)) + } else { + pkg_items.lookup_type(enum_ns, enum_name) + }; + if let Some(def) = def { if let Definition::Enum(_) = def { let qtn = qualify_def(db, def, enum_name); return Ty::EnumVariant(qtn, variant.clone(), TyAttr::default()); @@ -405,10 +416,19 @@ fn resolve_path_to_ty<'db>( } } - // Try the full path as a type lookup (handles namespaced types and - // single-segment names). + // Try the full path as a type lookup. For single-segment bare names, + // try namespace-qualified first, then unqualified. let name = segments.last().expect("segments is non-empty"); - if let Some(def) = pkg_items.lookup_type(&segments[..segments.len() - 1], name) { + let seg_ns = &segments[..segments.len() - 1]; + let def = if !ns_context.is_empty() && seg_ns.is_empty() { + let ns: Vec = ns_context.iter().chain(seg_ns.iter()).cloned().collect(); + pkg_items + .lookup_type(&ns, name) + .or_else(|| pkg_items.lookup_type(seg_ns, name)) + } else { + pkg_items.lookup_type(seg_ns, name) + }; + if let Some(def) = def { return match def { Definition::Class(_) => Ty::Class(qualify_def(db, def, name), TyAttr::default()), Definition::Enum(_) => Ty::Enum(qualify_def(db, def, name), TyAttr::default()), diff --git a/baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/main.baml b/baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/main.baml new file mode 100644 index 0000000000..9d24e833c5 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/main.baml @@ -0,0 +1,33 @@ +// Test: direct references to $stream companion types in user code. +// +// $stream types are synthetic (generated by PPIR expansion) and live in +// PPIR's package_items but not HIR's. User-written type annotations are +// resolved via HIR's package_items during package_interface construction, +// so $stream types are currently not user-referenceable. +// +// This fixture captures that limitation. When $stream types become +// user-referenceable, these errors should disappear. + +class Config { + key string +} + +class Response { + text string +} + +// Bare $stream from root namespace +function RootUsesOwnStream(c: Config$stream) -> string { + c.key +} + +// Qualified $stream from llm namespace +function RootUsesLlmStream(r: root.llm.Response$stream) -> string { + r.text +} + +// Class with $stream fields +class RootWithStreamFields { + own_stream Config$stream + llm_stream root.llm.Config$stream +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/ns_llm/models.baml b/baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/ns_llm/models.baml new file mode 100644 index 0000000000..5a92f68068 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_stream_direct_ref/ns_llm/models.baml @@ -0,0 +1,25 @@ +// llm namespace types for cross-namespace $stream references. + +class Config { + model string +} + +class Response { + text string +} + +// Bare $stream from same namespace +function LlmUsesOwnStream(r: Response$stream) -> string { + r.text +} + +// Qualified $stream from root namespace +function LlmUsesRootStream(c: root.Config$stream) -> string { + c.key +} + +// Class with cross-namespace $stream fields +class LlmWithStreamFields { + own_stream Response$stream + root_stream root.Config$stream +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_type_resolution/main.baml b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/main.baml new file mode 100644 index 0000000000..a250c48986 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/main.baml @@ -0,0 +1,128 @@ +// ═══════════════════════════════════════════════════════════════════ +// ROOT NAMESPACE — defines Config, Error, Status, ConfigAlias +// +// IMPORTANT: ns_llm and ns_auth ALSO define types with these exact +// same names. Bare references here must resolve to the ROOT versions. +// ═══════════════════════════════════════════════════════════════════ + +class Config { + key string + env string +} + +class Error { + code int + message string +} + +enum Status { + Ok + Failed + Pending +} + +type ConfigAlias = Config + +// ── Bare name usage from root ─────────────────────────────────── + +// Param + return types: bare Config/Status must be root.Config/root.Status +function RootIdentity(cfg: Config) -> Config { + cfg +} + +// Constructor: bare Config must build root.Config +function RootConstruct(key: string) -> Config { + Config { key: key, env: "prod" } +} + +// Enum variant: bare Status.Ok must be root.Status.Ok +function RootEnumReturn() -> Status { + Status.Ok +} + +// Enum match: all arms must resolve to root.Status variants +function RootEnumMatch(s: Status) -> string { + match (s) { + Status.Ok => "ok", + Status.Failed => "failed", + Status.Pending => "pending" + } +} + +// Type alias: bare ConfigAlias must be root.ConfigAlias = root.Config +function RootAliasParam(cfg: ConfigAlias) -> string { + cfg.key +} + +// Throw class: bare Error must be root.Error +function RootThrowClass(x: int) -> string { + match (x) { + 0 => throw Error { code: 500, message: "root error" }, + _ => "ok" + } +} + +// Throw enum: bare Status.Failed must be root.Status.Failed +function RootThrowEnum(x: int) -> string { + match (x) { + 0 => throw Status.Failed, + _ => "ok" + } +} + +// ── Cross-namespace from root ─────────────────────────────────── + +// Reference ns_llm types (which have SAME names as root types) +function RootUsesLlmConfig(cfg: root.llm.Config) -> string { + cfg.model +} + +function RootUsesLlmError(e: root.llm.Error) -> string { + e.reason +} + +function RootUsesLlmStatus() -> root.llm.Status { + root.llm.Status.Ready +} + +// Reference ns_auth types +function RootUsesAuthConfig(cfg: root.auth.Config) -> string { + cfg.provider +} + +function RootUsesAuthError(e: root.auth.Error) -> string { + e.realm +} + +// Reference nested ns_llm.openai types +function RootUsesNestedClient(c: root.llm.openai.Client) -> string { + c.api_key +} + +// ── Mixed: root types alongside qualified cross-ns types ──────── + +// Takes root.Config, returns root.llm.Config — must be different types +function RootMixedConfigs(root_cfg: Config, llm_cfg: root.llm.Config) -> string { + root_cfg.key +} + +// ── Stream companion types ────────────────────────────────────── +// Classes whose fields reference cross-namespace types. +// The $stream companions must resolve all field types correctly. + +// Root class with fields from other namespaces +class RootWithCrossNsFields { + own_config Config + llm_config root.llm.Config + auth_config root.auth.Config + llm_response root.llm.Response + nested_client root.llm.openai.Client + own_status Status + own_alias ConfigAlias +} + +// Root class referencing a cross-namespace type alias +class RootWithCrossNsAlias { + llm_alias root.llm.ResponseAlias + own_alias ConfigAlias +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_auth/auth.baml b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_auth/auth.baml new file mode 100644 index 0000000000..2e1f1f3c06 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_auth/auth.baml @@ -0,0 +1,153 @@ +// ═══════════════════════════════════════════════════════════════════ +// AUTH NAMESPACE — defines Config, Error, Role +// +// Config and Error have the SAME names as root and llm types. +// Bare references here must resolve to the AUTH versions. +// ═══════════════════════════════════════════════════════════════════ + +class Config { + provider string + secret string +} + +class Error { + realm string + expired bool +} + +enum Role { + Admin + User + Guest +} + +class Token { + value string + role Role +} + +type TokenAlias = Token + +// ── Bare name usage (must resolve to auth.* NOT root.*) ───────── + +// Bare Config param: must be auth.Config (.provider), not root (.key) or llm (.model) +function AuthIdentity(cfg: Config) -> Config { + cfg +} + +// Bare constructor: must build auth.Config +function AuthConstruct(provider: string) -> Config { + Config { provider: provider, secret: "s3cret" } +} + +// Bare enum return: must be auth.Role.Admin +function AuthEnumReturn() -> Role { + Role.Admin +} + +// Bare enum match: must match against auth.Role variants +function AuthEnumMatch(r: Role) -> string { + match (r) { + Role.Admin => "admin", + Role.User => "user", + Role.Guest => "guest" + } +} + +// Bare alias: must be auth.TokenAlias = auth.Token +function AuthAliasParam(t: TokenAlias) -> string { + t.value +} + +// Bare class in throw +function AuthThrowClass(x: int) -> string { + match (x) { + 0 => throw Error { realm: "auth failed", expired: true }, + _ => "ok" + } +} + +// Bare enum in throw +function AuthThrowEnum(x: int) -> string { + match (x) { + 0 => throw Role.Guest, + _ => "ok" + } +} + +// Token constructor with nested enum field +function AuthMakeToken(v: string) -> Token { + Token { value: v, role: Role.User } +} + +// ── Cross-namespace: root.X ───────────────────────────────────── + +function AuthUsesRootConfig(cfg: root.Config) -> string { + cfg.key +} + +function AuthUsesRootStatus() -> root.Status { + root.Status.Pending +} + +function AuthMatchesRootStatus(s: root.Status) -> string { + match (s) { + root.Status.Ok => "ok", + root.Status.Failed => "failed", + root.Status.Pending => "pending" + } +} + +function AuthThrowsRootError(x: int) -> string { + match (x) { + 0 => throw root.Error { code: 403, message: "forbidden" }, + _ => "ok" + } +} + +// ── Cross-namespace: sibling (root.llm.X) ─────────────────────── + +function AuthUsesLlmConfig(cfg: root.llm.Config) -> string { + cfg.model +} + +function AuthUsesLlmResponse(r: root.llm.Response) -> string { + r.text +} + +function AuthUsesLlmStatus() -> root.llm.Status { + root.llm.Status.Ready +} + +function AuthMatchesLlmStatus(s: root.llm.Status) -> string { + match (s) { + root.llm.Status.Ready => "ready", + root.llm.Status.Generating => "generating", + root.llm.Status.Done => "done" + } +} + +// ── Cross-namespace: nested (root.llm.openai.X) ──────────────── + +function AuthUsesNestedClient(c: root.llm.openai.Client) -> string { + c.api_key +} + +// ── Mixed: auth + root + llm types ────────────────────────────── + +function AuthMixedConfigs( + auth_cfg: Config, + root_cfg: root.Config, + llm_cfg: root.llm.Config +) -> string { + auth_cfg.provider +} + +// auth.Error + root.Error + llm.Error — three different types +function AuthMixedErrors( + auth_err: Error, + root_err: root.Error, + llm_err: root.llm.Error +) -> string { + auth_err.realm +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/models.baml b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/models.baml new file mode 100644 index 0000000000..94c0414dff --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/models.baml @@ -0,0 +1,194 @@ +// ═══════════════════════════════════════════════════════════════════ +// LLM NAMESPACE — defines Config, Error, Status, ConfigAlias +// +// These have the SAME names as root types. Bare references here +// must resolve to the LLM versions, NOT root versions. +// ═══════════════════════════════════════════════════════════════════ + +class Config { + model string + temperature float +} + +class Error { + reason string + retryable bool +} + +enum Status { + Ready + Generating + Done +} + +enum Model { + GPT4 + Claude +} + +class Response { + text string + tokens int +} + +type ConfigAlias = Config + +type ResponseAlias = Response + +// ── Bare name usage (must resolve to llm.* NOT root.*) ────────── + +// Bare Config param: must be llm.Config (has .model), not root.Config (has .key) +function LlmIdentity(cfg: Config) -> Config { + cfg +} + +// Bare constructor: must build llm.Config +function LlmConstruct(model: string) -> Config { + Config { model: model, temperature: 0.7 } +} + +// Bare enum return: must be llm.Status.Ready, not root.Status.Ok +function LlmEnumReturn() -> Status { + Status.Ready +} + +// Bare enum match: must match against llm.Status variants +function LlmEnumMatch(s: Status) -> string { + match (s) { + Status.Ready => "ready", + Status.Generating => "generating", + Status.Done => "done" + } +} + +// Bare alias: must be llm.ConfigAlias = llm.Config +function LlmAliasParam(cfg: ConfigAlias) -> string { + cfg.model +} + +// Bare class in throw +function LlmThrowClass(x: int) -> string { + match (x) { + 0 => throw Error { reason: "llm failed", retryable: true }, + _ => "ok" + } +} + +// Bare enum in throw +function LlmThrowEnum(x: int) -> string { + match (x) { + 0 => throw Status.Done, + _ => "ok" + } +} + +// Bare constructor with field access +function LlmResponseConstruct(text: string) -> Response { + Response { text: text, tokens: 42 } +} + +// ── Cross-namespace: root.X (must get root types, not llm) ────── + +// root.Config has .key (not .model) — proves it's root.Config +function LlmUsesRootConfig(cfg: root.Config) -> string { + cfg.key +} + +// root.Error has .code (not .reason) — proves it's root.Error +function LlmUsesRootError(e: root.Error) -> string { + e.message +} + +// root.Status has Ok/Failed/Pending, not Ready/Generating/Done +function LlmUsesRootStatus() -> root.Status { + root.Status.Ok +} + +// root.Status match — must match root variants +function LlmMatchesRootStatus(s: root.Status) -> string { + match (s) { + root.Status.Ok => "ok", + root.Status.Failed => "failed", + root.Status.Pending => "pending" + } +} + +// root.ConfigAlias must be root.ConfigAlias = root.Config +function LlmUsesRootAlias(cfg: root.ConfigAlias) -> string { + cfg.key +} + +// Throw root.Error from llm namespace +function LlmThrowsRootError(x: int) -> string { + match (x) { + 0 => throw root.Error { code: 404, message: "not found" }, + _ => "ok" + } +} + +// Throw root enum variant +function LlmThrowsRootEnum(x: int) -> string { + match (x) { + 0 => throw root.Status.Failed, + _ => "ok" + } +} + +// ── Cross-namespace: sibling namespace (root.auth.X) ──────────── + +// Reference ns_auth.Config (has .provider) from ns_llm +function LlmUsesAuthConfig(cfg: root.auth.Config) -> string { + cfg.provider +} + +// Reference ns_auth.Error (has .realm) from ns_llm +function LlmUsesAuthError(e: root.auth.Error) -> string { + e.realm +} + +// Reference ns_auth.Role enum from ns_llm +function LlmUsesAuthRole() -> root.auth.Role { + root.auth.Role.Admin +} + +// ── Cross-namespace: child namespace (root.llm.openai.X) ──────── + +// Reference nested openai.Client from parent llm namespace +function LlmUsesNestedClient(c: root.llm.openai.Client) -> string { + c.api_key +} + +// ── Mixed: llm types + qualified root/auth types ──────────────── + +// All three Configs in one signature — must be three different types +function LlmMixedConfigs( + llm_cfg: Config, + root_cfg: root.Config, + auth_cfg: root.auth.Config +) -> string { + llm_cfg.model +} + +// ── Stream companion types ────────────────────────────────────── +// Classes with cross-namespace field types. +// The $stream companions must resolve all field types, including +// types from root and sibling namespaces. + +// llm class with fields from root and sibling namespaces +class LlmWithCrossNsFields { + own_config Config + own_response Response + root_config root.Config + root_error root.Error + auth_config root.auth.Config + nested_client root.llm.openai.Client + own_status Status + own_alias ConfigAlias + root_alias root.ConfigAlias +} + +// llm class referencing root type alias (this was the alias stream bug) +class LlmWithRootAlias { + root_alias root.ConfigAlias + own_alias ResponseAlias +} diff --git a/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/ns_openai/client.baml b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/ns_openai/client.baml new file mode 100644 index 0000000000..1fee2eaeb5 --- /dev/null +++ b/baml_language/crates/baml_tests/projects/namespaces_type_resolution/ns_llm/ns_openai/client.baml @@ -0,0 +1,142 @@ +// ═══════════════════════════════════════════════════════════════════ +// LLM.OPENAI NAMESPACE (nested) — defines Client, Error, Model +// +// Error and Model have the SAME names as root, llm, and auth types. +// Bare references here must resolve to the openai versions. +// ═══════════════════════════════════════════════════════════════════ + +class Client { + api_key string + org_id string +} + +class Error { + status_code int + body string +} + +enum Model { + GPT4o + GPT4oMini + O3 +} + +// ── Bare name usage (must resolve to llm.openai.*) ────────────── + +function OpenAIIdentity(c: Client) -> Client { + c +} + +function OpenAIConstruct(key: string) -> Client { + Client { api_key: key, org_id: "org-123" } +} + +function OpenAIEnumReturn() -> Model { + Model.GPT4o +} + +function OpenAIEnumMatch(m: Model) -> string { + match (m) { + Model.GPT4o => "gpt4o", + Model.GPT4oMini => "gpt4o-mini", + Model.O3 => "o3" + } +} + +function OpenAIThrowClass(x: int) -> string { + match (x) { + 0 => throw Error { status_code: 429, body: "rate limited" }, + _ => "ok" + } +} + +function OpenAIThrowEnum(x: int) -> string { + match (x) { + 0 => throw Model.O3, + _ => "ok" + } +} + +// ── Cross-namespace: root.X ───────────────────────────────────── + +function OpenAIUsesRootConfig(cfg: root.Config) -> string { + cfg.key +} + +function OpenAIUsesRootStatus() -> root.Status { + root.Status.Ok +} + +function OpenAIMatchesRootStatus(s: root.Status) -> string { + match (s) { + root.Status.Ok => "ok", + root.Status.Failed => "failed", + root.Status.Pending => "pending" + } +} + +// ── Cross-namespace: parent (root.llm.X) ──────────────────────── + +// Parent llm namespace — NOT the same as bare names here +function OpenAIUsesLlmConfig(cfg: root.llm.Config) -> string { + cfg.model +} + +function OpenAIUsesLlmResponse(r: root.llm.Response) -> string { + r.text +} + +function OpenAIUsesLlmStatus() -> root.llm.Status { + root.llm.Status.Generating +} + +function OpenAIMatchesLlmStatus(s: root.llm.Status) -> string { + match (s) { + root.llm.Status.Ready => "ready", + root.llm.Status.Generating => "generating", + root.llm.Status.Done => "done" + } +} + +// ── Cross-namespace: sibling of parent (root.auth.X) ──────────── + +function OpenAIUsesAuthConfig(cfg: root.auth.Config) -> string { + cfg.provider +} + +function OpenAIUsesAuthRole() -> root.auth.Role { + root.auth.Role.User +} + +function OpenAIMatchesAuthRole(r: root.auth.Role) -> string { + match (r) { + root.auth.Role.Admin => "admin", + root.auth.Role.User => "user", + root.auth.Role.Guest => "guest" + } +} + +// ── Mixed: all four namespace Errors ──────────────────────────── + +// openai.Error (.status_code), root.Error (.code), +// llm.Error (.reason), auth.Error (.realm) +function OpenAIMixedErrors( + openai_err: Error, + root_err: root.Error, + llm_err: root.llm.Error, + auth_err: root.auth.Error +) -> string { + openai_err.body +} + +// openai.Model, llm.Model — both named Model but different variants +function OpenAIMixedModels( + openai_model: Model, + llm_model: root.llm.Model +) -> string { + match (openai_model) { + Model.GPT4o => "gpt4o", + Model.GPT4oMini => "mini", + Model.O3 => "o3" + } +} diff --git a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap index c4bb8179a8..dde2dedcd4 100644 --- a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap +++ b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_5_mir.snap @@ -181,10 +181,10 @@ fn baml.llm.call_llm_function(client: baml.llm.Client, function_name: string, ar let _3: map // args // param let _4: string // jinja_string let _5: future - let _6: void // context + let _6: baml.llm.ExecutionContext // context let _7: string let _8: void // result - let _9: void + let _9: baml.llm.ExecutionContext bb0: { _5 = dispatch_future const fn baml.llm.get_jinja_template(copy _2) -> bb1; @@ -371,9 +371,9 @@ fn baml.llm.Client.build_attempt(self: baml.llm.Client) -> baml.llm.Orchestratio // Locals: let _0: baml.llm.OrchestrationStep[] // _0 // return let _1: baml.llm.Client // self // param - let _2: void // planner_state + let _2: baml.llm.PlannerState // planner_state let _3: void[] - let _4: void + let _4: baml.llm.PlannerState bb0: { _3 = []; @@ -402,7 +402,7 @@ fn baml.llm.Client.build_attempt_with_state(self: baml.llm.Client, planner_state let _6: future<() -> baml.llm.PrimitiveClient> let _7: baml.llm.PrimitiveClient // primitive let _8: () -> baml.llm.PrimitiveClient - let _9: void + let _9: baml.llm.OrchestrationStep let _10: baml.llm.PrimitiveClient let _11: baml.llm.OrchestrationStep[] // steps let _12: baml.llm.Client[] @@ -579,9 +579,9 @@ fn baml.llm.Client.build_plan(self: baml.llm.Client) -> baml.llm.OrchestrationSt // Locals: let _0: baml.llm.OrchestrationStep[] // _0 // return let _1: baml.llm.Client // self // param - let _2: void // planner_state + let _2: baml.llm.PlannerState // planner_state let _3: void[] - let _4: void + let _4: baml.llm.PlannerState bb0: { _3 = []; @@ -640,7 +640,7 @@ fn baml.llm.Client.build_plan_with_state(self: baml.llm.Client, planner_state: b let _36: baml.llm.OrchestrationStep // step let _37: null let _38: baml.llm.OrchestrationStep[] - let _39: void + let _39: baml.llm.OrchestrationStep let _40: baml.llm.PrimitiveClient let _41: baml.llm.OrchestrationStep let _42: int diff --git a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_tir.snap b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_tir.snap index 39f04ed642..b4710c48b1 100644 --- a/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_tir.snap +++ b/baml_language/crates/baml_tests/snapshots/__baml_std__/baml_tests____baml_std____04_tir.snap @@ -191,7 +191,7 @@ function baml.llm.build_request(client: baml.llm.Client, function_name: string, function baml.llm.call_llm_function(client: baml.llm.Client, function_name: string, args: map) -> T throws never { { : T let jinja_string = get_jinja_template(function_name) : string - let context = ExecutionContext { jinja_string: jinja_string, args: args, function_name: function_name } : unknown + let context = ExecutionContext { jinja_string: jinja_string, args: args, function_name: function_name } : baml.llm.ExecutionContext let result = client.execute(context, 0) : T result : T } @@ -245,18 +245,18 @@ function baml.llm.Client.to_primitive_client(self: baml.llm.Client) -> baml.llm. } function baml.llm.Client.build_attempt(self: baml.llm.Client) -> baml.llm.OrchestrationStep[] throws never { { : baml.llm.OrchestrationStep[] - let planner_state = PlannerState { rr_client_names: [] } : unknown + let planner_state = PlannerState { rr_client_names: [] } : baml.llm.PlannerState self.build_attempt_with_state(planner_state) : baml.llm.OrchestrationStep[] } } function baml.llm.Client.build_attempt_with_state(self: baml.llm.Client, planner_state: baml.llm.PlannerState) -> baml.llm.OrchestrationStep[] throws never { - { : unknown[] | baml.llm.OrchestrationStep[] | never[] - match (self.client_type : baml.llm.ClientType) : unknown[] | baml.llm.OrchestrationStep[] | never[] + { : baml.llm.OrchestrationStep[] | never[] + match (self.client_type : baml.llm.ClientType) : baml.llm.OrchestrationStep[] | never[] ClientType.Primitive => - { : unknown[] + { : baml.llm.OrchestrationStep[] let resolve_fn = self.get_constructor() : () -> baml.llm.PrimitiveClient let primitive = resolve_fn() : baml.llm.PrimitiveClient - [OrchestrationStep { primitive_client: primitive, delay_ms: 0 }] : unknown[] + [OrchestrationStep { primitive_client: primitive, delay_ms: 0 }] : baml.llm.OrchestrationStep[] } ClientType.Fallback => { : baml.llm.OrchestrationStep[] @@ -286,7 +286,7 @@ function baml.llm.Client.build_attempt_with_state(self: baml.llm.Client, planner } function baml.llm.Client.build_plan(self: baml.llm.Client) -> baml.llm.OrchestrationStep[] throws never { { : baml.llm.OrchestrationStep[] - let planner_state = PlannerState { rr_client_names: [] } : unknown + let planner_state = PlannerState { rr_client_names: [] } : baml.llm.PlannerState self.build_plan_with_state(planner_state) : baml.llm.OrchestrationStep[] } } diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap index 3382779c6d..68074f567c 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__04_tir.snap @@ -15,7 +15,7 @@ function user.llm.UseConfig(cfg: unknown) -> user.llm.Response throws never { { : user.llm.Response Response { text: cfg.key } : user.llm.Response } - !! 187..198: unresolved type: Config. Did you mean `root.Config`? + !! 191..198: unresolved type: Config. Did you mean `root.Config`? } class user.llm.Response$stream { text: null | string diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap index 03befffee8..c2230a0b4f 100644 --- a/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap +++ b/baml_language/crates/baml_tests/snapshots/namespaces_bare_name_rejected/baml_tests__namespaces_bare_name_rejected__05_diagnostics.snap @@ -3,11 +3,11 @@ source: crates/baml_tests/src/generated_tests.rs --- === COMPILER2 DIAGNOSTICS === [type] Error: unresolved type: Config. Did you mean `root.Config`? - ╭─[ models.baml:7:22 ] + ╭─[ models.baml:7:26 ] │ 7 │ function UseConfig(cfg: Config) -> Response { - │ ─────┬───── - │ ╰─────── unresolved type: Config. Did you mean `root.Config`? + │ ───┬─── + │ ╰───── unresolved type: Config. Did you mean `root.Config`? │ │ Note: Error code: E0001 ───╯ diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__main.snap new file mode 100644 index 0000000000..5f734095c4 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__main.snap @@ -0,0 +1,171 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Slash "/" +Slash "/" +Word "Test" +Colon ":" +Word "direct" +Word "references" +Word "to" +Word "$stream" +Word "companion" +Word "types" +In "in" +Word "user" +Word "code" +Dot "." +Slash "/" +Slash "/" +Slash "/" +Slash "/" +Word "$stream" +Word "types" +Word "are" +Word "synthetic" +LParen "(" +Word "generated" +Word "by" +Word "PPIR" +Word "expansion" +RParen ")" +Word "and" +Word "live" +In "in" +Slash "/" +Slash "/" +Word "PPIR" +Error "'" +Word "s" +Word "package_items" +Word "but" +Word "not" +Word "HIR" +Error "'" +Word "s" +Dot "." +Word "User-written" +Word "type" +Word "annotations" +Word "are" +Slash "/" +Slash "/" +Word "resolved" +Word "via" +Word "HIR" +Error "'" +Word "s" +Word "package_items" +Word "during" +Word "package_interface" +Word "construction" +Comma "," +Slash "/" +Slash "/" +Word "so" +Word "$stream" +Word "types" +Word "are" +Word "currently" +Word "not" +Word "user-referenceable" +Dot "." +Slash "/" +Slash "/" +Slash "/" +Slash "/" +Word "This" +Word "fixture" +Word "captures" +Word "that" +Word "limitation" +Dot "." +Word "When" +Word "$stream" +Word "types" +Word "become" +Slash "/" +Slash "/" +Word "user-referenceable" +Comma "," +Word "these" +Word "errors" +Word "should" +Word "disappear" +Dot "." +Class "class" +Word "Config" +LBrace "{" +Word "key" +Word "string" +RBrace "}" +Class "class" +Word "Response" +LBrace "{" +Word "text" +Word "string" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "$stream" +Word "from" +Word "root" +Word "namespace" +Function "function" +Word "RootUsesOwnStream" +LParen "(" +Word "c" +Colon ":" +Word "Config$stream" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "c" +Dot "." +Word "key" +RBrace "}" +Slash "/" +Slash "/" +Word "Qualified" +Word "$stream" +Word "from" +Word "llm" +Word "namespace" +Function "function" +Word "RootUsesLlmStream" +LParen "(" +Word "r" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Response$stream" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "r" +Dot "." +Word "text" +RBrace "}" +Slash "/" +Slash "/" +Word "Class" +Word "with" +Word "$stream" +Word "fields" +Class "class" +Word "RootWithStreamFields" +LBrace "{" +Word "own_stream" +Word "Config$stream" +Word "llm_stream" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config$stream" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__ns_llm_models.snap new file mode 100644 index 0000000000..8a33ec00ca --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__01_lexer__ns_llm_models.snap @@ -0,0 +1,86 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Slash "/" +Slash "/" +Word "llm" +Word "namespace" +Word "types" +For "for" +Word "cross-namespace" +Word "$stream" +Word "references" +Dot "." +Class "class" +Word "Config" +LBrace "{" +Word "model" +Word "string" +RBrace "}" +Class "class" +Word "Response" +LBrace "{" +Word "text" +Word "string" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "$stream" +Word "from" +Word "same" +Word "namespace" +Function "function" +Word "LlmUsesOwnStream" +LParen "(" +Word "r" +Colon ":" +Word "Response$stream" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "r" +Dot "." +Word "text" +RBrace "}" +Slash "/" +Slash "/" +Word "Qualified" +Word "$stream" +Word "from" +Word "root" +Word "namespace" +Function "function" +Word "LlmUsesRootStream" +LParen "(" +Word "c" +Colon ":" +Word "root" +Dot "." +Word "Config$stream" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "c" +Dot "." +Word "key" +RBrace "}" +Slash "/" +Slash "/" +Word "Class" +Word "with" +Word "cross-namespace" +Word "$stream" +Word "fields" +Class "class" +Word "LlmWithStreamFields" +LBrace "{" +Word "own_stream" +Word "Response$stream" +Word "root_stream" +Word "root" +Dot "." +Word "Config$stream" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__main.snap new file mode 100644 index 0000000000..58b3a015c6 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__main.snap @@ -0,0 +1,91 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Config" + L_BRACE "{" + FIELD + WORD "key" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Response" + L_BRACE "{" + FIELD + WORD "text" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesOwnStream" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "c" + COLON ":" + TYPE_EXPR "Config$stream" + WORD "Config$stream" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "c.key" + WORD "c" + DOT "." + WORD "key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesLlmStream" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "r" + COLON ":" + TYPE_EXPR "root.llm.Response$stream" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Response$stream" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "r.text" + WORD "r" + DOT "." + WORD "text" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "RootWithStreamFields" + L_BRACE "{" + FIELD + WORD "own_stream" + TYPE_EXPR "Config$stream" + WORD "Config$stream" + FIELD + WORD "llm_stream" + TYPE_EXPR "root.llm.Config$stream" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config$stream" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__ns_llm_models.snap new file mode 100644 index 0000000000..2a3f3c8346 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__02_parser__ns_llm_models.snap @@ -0,0 +1,87 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Config" + L_BRACE "{" + FIELD + WORD "model" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Response" + L_BRACE "{" + FIELD + WORD "text" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesOwnStream" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "r" + COLON ":" + TYPE_EXPR "Response$stream" + WORD "Response$stream" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "r.text" + WORD "r" + DOT "." + WORD "text" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesRootStream" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "c" + COLON ":" + TYPE_EXPR "root.Config$stream" + WORD "root" + DOT "." + WORD "Config$stream" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "c.key" + WORD "c" + DOT "." + WORD "key" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "LlmWithStreamFields" + L_BRACE "{" + FIELD + WORD "own_stream" + TYPE_EXPR "Response$stream" + WORD "Response$stream" + FIELD + WORD "root_stream" + TYPE_EXPR "root.Config$stream" + WORD "root" + DOT "." + WORD "Config$stream" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__03_hir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__03_hir.snap new file mode 100644 index 0000000000..bce134b04a --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__03_hir.snap @@ -0,0 +1,36 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== HIR2 === +class user.Config { + key: string +} +class user.Response { + text: string +} +class user.RootWithStreamFields { + own_stream: user.Config$stream + llm_stream: root.llm.Config$stream +} +function user.RootUsesLlmStream(r: root.llm.Response$stream) -> string [expr] { + { } r.text +} +function user.RootUsesOwnStream(c: user.Config$stream) -> string [expr] { + { } c.key +} +class user.llm.Config { + model: string +} +class user.llm.LlmWithStreamFields { + own_stream: user.llm.Response$stream + root_stream: root.Config$stream +} +class user.llm.Response { + text: string +} +function user.llm.LlmUsesOwnStream(r: user.llm.Response$stream) -> string [expr] { + { } r.text +} +function user.llm.LlmUsesRootStream(c: root.Config$stream) -> string [expr] { + { } c.key +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_5_mir.snap new file mode 100644 index 0000000000..69f1b5add5 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_5_mir.snap @@ -0,0 +1,63 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== MIR2 === +fn user.RootUsesLlmStream(r: void) -> string { + // Locals: + let _0: string // _0 // return + let _1: void // r // param + + bb0: { + _0 = const null; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootUsesOwnStream(c: void) -> string { + // Locals: + let _0: string // _0 // return + let _1: void // c // param + + bb0: { + _0 = const null; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesOwnStream(r: void) -> string { + // Locals: + let _0: string // _0 // return + let _1: void // r // param + + bb0: { + _0 = const null; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesRootStream(c: void) -> string { + // Locals: + let _0: string // _0 // return + let _1: void // c // param + + bb0: { + _0 = const null; + goto -> bb1; + } + + bb1: { + return; + } +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_tir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_tir.snap new file mode 100644 index 0000000000..d3bceb3224 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__04_tir.snap @@ -0,0 +1,68 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== TIR2 === +class user.Config { + key: string +} +class user.Response { + text: string +} +function user.RootUsesOwnStream(c: unknown) -> string throws never { + { : unknown + c.key : unknown + } + !! 610..624: unresolved type: Config$stream +} +function user.RootUsesLlmStream(r: unknown) -> string throws never { + { : unknown + r.text : unknown + } + !! 720..745: unresolved type: root.llm.Response$stream +} +class user.RootWithStreamFields { + own_stream: user.Config$stream + llm_stream: user.llm.Config$stream +} +class user.Config$stream { + key: null | string +} +class user.Response$stream { + text: null | string +} +class user.RootWithStreamFields$stream { + own_stream: null | user.Config$stream + llm_stream: null | user.llm.Config$stream +} +class user.llm.Config { + model: string +} +class user.llm.Response { + text: string +} +function user.llm.LlmUsesOwnStream(r: unknown) -> string throws never { + { : unknown + r.text : unknown + } + !! 199..215: unresolved type: Response$stream +} +function user.llm.LlmUsesRootStream(c: unknown) -> string throws never { + { : unknown + c.key : unknown + } + !! 313..332: unresolved type: root.Config$stream +} +class user.llm.LlmWithStreamFields { + own_stream: user.llm.Response$stream + root_stream: user.Config$stream +} +class user.llm.Config$stream { + model: null | string +} +class user.llm.Response$stream { + text: null | string +} +class user.llm.LlmWithStreamFields$stream { + own_stream: null | user.llm.Response$stream + root_stream: null | user.Config$stream +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__05_diagnostics.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__05_diagnostics.snap new file mode 100644 index 0000000000..ce627443bf --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__05_diagnostics.snap @@ -0,0 +1,43 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== COMPILER2 DIAGNOSTICS === + [type] Error: unresolved type: Config$stream + ╭─[ main.baml:20:30 ] + │ + 20 │ function RootUsesOwnStream(c: Config$stream) -> string { + │ ───────┬────── + │ ╰──────── unresolved type: Config$stream + │ + │ Note: Error code: E0001 +────╯ + + [type] Error: unresolved type: root.llm.Response$stream + ╭─[ main.baml:25:30 ] + │ + 25 │ function RootUsesLlmStream(r: root.llm.Response$stream) -> string { + │ ────────────┬──────────── + │ ╰────────────── unresolved type: root.llm.Response$stream + │ + │ Note: Error code: E0001 +────╯ + + [type] Error: unresolved type: Response$stream + ╭─[ models.baml:12:29 ] + │ + 12 │ function LlmUsesOwnStream(r: Response$stream) -> string { + │ ────────┬─────── + │ ╰───────── unresolved type: Response$stream + │ + │ Note: Error code: E0001 +────╯ + + [type] Error: unresolved type: root.Config$stream + ╭─[ models.baml:17:30 ] + │ + 17 │ function LlmUsesRootStream(c: root.Config$stream) -> string { + │ ─────────┬───────── + │ ╰─────────── unresolved type: root.Config$stream + │ + │ Note: Error code: E0001 +────╯ diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__06_codegen.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__06_codegen.snap new file mode 100644 index 0000000000..f57fa4fcb4 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__06_codegen.snap @@ -0,0 +1,22 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +function user.RootUsesLlmStream(r: void) -> string { + load_const null + return +} + +function user.RootUsesOwnStream(c: void) -> string { + load_const null + return +} + +function user.llm.LlmUsesOwnStream(r: void) -> string { + load_const null + return +} + +function user.llm.LlmUsesRootStream(c: void) -> string { + load_const null + return +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__main.snap new file mode 100644 index 0000000000..05580fb1a5 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__main.snap @@ -0,0 +1,36 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +// Test: direct references to $stream companion types in user code. +// +// $stream types are synthetic (generated by PPIR expansion) and live in +// PPIR's package_items but not HIR's. User-written type annotations are +// resolved via HIR's package_items during package_interface construction, +// so $stream types are currently not user-referenceable. +// +// This fixture captures that limitation. When $stream types become +// user-referenceable, these errors should disappear. + +class Config { + key: string +} + +class Response { + text: string +} + +// Bare $stream from root namespace +function RootUsesOwnStream(c: Config$stream) -> string { + c.key +} + +// Qualified $stream from llm namespace +function RootUsesLlmStream(r: root.llm.Response$stream) -> string { + r.text +} + +// Class with $stream fields +class RootWithStreamFields { + own_stream: Config$stream + llm_stream: root.llm.Config$stream +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__ns_llm_models.snap new file mode 100644 index 0000000000..a9d75861a2 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_stream_direct_ref/baml_tests__namespaces_stream_direct_ref__10_formatter__ns_llm_models.snap @@ -0,0 +1,28 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +// llm namespace types for cross-namespace $stream references. + +class Config { + model: string +} + +class Response { + text: string +} + +// Bare $stream from same namespace +function LlmUsesOwnStream(r: Response$stream) -> string { + r.text +} + +// Qualified $stream from root namespace +function LlmUsesRootStream(c: root.Config$stream) -> string { + c.key +} + +// Class with cross-namespace $stream fields +class LlmWithStreamFields { + own_stream: Response$stream + root_stream: root.Config$stream +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__main.snap new file mode 100644 index 0000000000..c9a104d1d0 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__main.snap @@ -0,0 +1,900 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Slash "/" +Slash "/" +Word "ROOT" +Word "NAMESPACE" +Error "—" +Word "defines" +Word "Config" +Comma "," +Word "Error" +Comma "," +Word "Status" +Comma "," +Word "ConfigAlias" +Slash "/" +Slash "/" +Slash "/" +Slash "/" +Word "IMPORTANT" +Colon ":" +Word "ns_llm" +Word "and" +Word "ns_auth" +Word "ALSO" +Word "define" +Word "types" +Word "with" +Word "these" +Word "exact" +Slash "/" +Slash "/" +Word "same" +Word "names" +Dot "." +Word "Bare" +Word "references" +Word "here" +Word "must" +Word "resolve" +Word "to" +Word "the" +Word "ROOT" +Word "versions" +Dot "." +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Class "class" +Word "Config" +LBrace "{" +Word "key" +Word "string" +Word "env" +Word "string" +RBrace "}" +Class "class" +Word "Error" +LBrace "{" +Word "code" +Word "int" +Word "message" +Word "string" +RBrace "}" +Enum "enum" +Word "Status" +LBrace "{" +Word "Ok" +Word "Failed" +Word "Pending" +RBrace "}" +Word "type" +Word "ConfigAlias" +Equals "=" +Word "Config" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Bare" +Word "name" +Word "usage" +Word "from" +Word "root" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Param" +Plus "+" +Return "return" +Word "types" +Colon ":" +Word "bare" +Word "Config" +Slash "/" +Word "Status" +Word "must" +Word "be" +Word "root" +Dot "." +Word "Config" +Slash "/" +Word "root" +Dot "." +Word "Status" +Function "function" +Word "RootIdentity" +LParen "(" +Word "cfg" +Colon ":" +Word "Config" +RParen ")" +Arrow "->" +Word "Config" +LBrace "{" +Word "cfg" +RBrace "}" +Slash "/" +Slash "/" +Word "Constructor" +Colon ":" +Word "bare" +Word "Config" +Word "must" +Word "build" +Word "root" +Dot "." +Word "Config" +Function "function" +Word "RootConstruct" +LParen "(" +Word "key" +Colon ":" +Word "string" +RParen ")" +Arrow "->" +Word "Config" +LBrace "{" +Word "Config" +LBrace "{" +Word "key" +Colon ":" +Word "key" +Comma "," +Word "env" +Colon ":" +Quote "\"" +Word "prod" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Enum" +Word "variant" +Colon ":" +Word "bare" +Word "Status" +Dot "." +Word "Ok" +Word "must" +Word "be" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +Function "function" +Word "RootEnumReturn" +LParen "(" +RParen ")" +Arrow "->" +Word "Status" +LBrace "{" +Word "Status" +Dot "." +Word "Ok" +RBrace "}" +Slash "/" +Slash "/" +Word "Enum" +Match "match" +Colon ":" +Word "all" +Word "arms" +Word "must" +Word "resolve" +Word "to" +Word "root" +Dot "." +Word "Status" +Word "variants" +Function "function" +Word "RootEnumMatch" +LParen "(" +Word "s" +Colon ":" +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "Status" +Dot "." +Word "Ok" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +Comma "," +Word "Status" +Dot "." +Word "Failed" +FatArrow "=>" +Quote "\"" +Word "failed" +Quote "\"" +Comma "," +Word "Status" +Dot "." +Word "Pending" +FatArrow "=>" +Quote "\"" +Word "pending" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Type" +Word "alias" +Colon ":" +Word "bare" +Word "ConfigAlias" +Word "must" +Word "be" +Word "root" +Dot "." +Word "ConfigAlias" +Equals "=" +Word "root" +Dot "." +Word "Config" +Function "function" +Word "RootAliasParam" +LParen "(" +Word "cfg" +Colon ":" +Word "ConfigAlias" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "key" +RBrace "}" +Slash "/" +Slash "/" +Word "Throw" +Class "class" +Colon ":" +Word "bare" +Word "Error" +Word "must" +Word "be" +Word "root" +Dot "." +Word "Error" +Function "function" +Word "RootThrowClass" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Error" +LBrace "{" +Word "code" +Colon ":" +IntegerLiteral "500" +Comma "," +Word "message" +Colon ":" +Quote "\"" +Word "root" +Word "error" +Quote "\"" +RBrace "}" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Throw" +Enum "enum" +Colon ":" +Word "bare" +Word "Status" +Dot "." +Word "Failed" +Word "must" +Word "be" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Failed" +Function "function" +Word "RootThrowEnum" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Status" +Dot "." +Word "Failed" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Word "from" +Word "root" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Reference" +Word "ns_llm" +Word "types" +LParen "(" +Word "which" +Word "have" +Word "SAME" +Word "names" +Word "as" +Word "root" +Word "types" +RParen ")" +Function "function" +Word "RootUsesLlmConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "model" +RBrace "}" +Function "function" +Word "RootUsesLlmError" +LParen "(" +Word "e" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Error" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "e" +Dot "." +Word "reason" +RBrace "}" +Function "function" +Word "RootUsesLlmStatus" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +LBrace "{" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Ready" +RBrace "}" +Slash "/" +Slash "/" +Word "Reference" +Word "ns_auth" +Word "types" +Function "function" +Word "RootUsesAuthConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "provider" +RBrace "}" +Function "function" +Word "RootUsesAuthError" +LParen "(" +Word "e" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Error" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "e" +Dot "." +Word "realm" +RBrace "}" +Slash "/" +Slash "/" +Word "Reference" +Word "nested" +Word "ns_llm" +Dot "." +Word "openai" +Word "types" +Function "function" +Word "RootUsesNestedClient" +LParen "(" +Word "c" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "Client" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "c" +Dot "." +Word "api_key" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Mixed" +Colon ":" +Word "root" +Word "types" +Word "alongside" +Word "qualified" +Word "cross-ns" +Word "types" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Takes" +Word "root" +Dot "." +Word "Config" +Comma "," +Word "returns" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +Error "—" +Word "must" +Word "be" +Word "different" +Word "types" +Function "function" +Word "RootMixedConfigs" +LParen "(" +Word "root_cfg" +Colon ":" +Word "Config" +Comma "," +Word "llm_cfg" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "root_cfg" +Dot "." +Word "key" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Stream" +Word "companion" +Word "types" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Classes" +Word "whose" +Word "fields" +Word "reference" +Word "cross-namespace" +Word "types" +Dot "." +Slash "/" +Slash "/" +Word "The" +Word "$stream" +Word "companions" +Word "must" +Word "resolve" +Word "all" +Word "field" +Word "types" +Word "correctly" +Dot "." +Slash "/" +Slash "/" +Word "Root" +Class "class" +Word "with" +Word "fields" +Word "from" +Word "other" +Word "namespaces" +Class "class" +Word "RootWithCrossNsFields" +LBrace "{" +Word "own_config" +Word "Config" +Word "llm_config" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +Word "auth_config" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Config" +Word "llm_response" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Response" +Word "nested_client" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "Client" +Word "own_status" +Word "Status" +Word "own_alias" +Word "ConfigAlias" +RBrace "}" +Slash "/" +Slash "/" +Word "Root" +Class "class" +Word "referencing" +Word "a" +Word "cross-namespace" +Word "type" +Word "alias" +Class "class" +Word "RootWithCrossNsAlias" +LBrace "{" +Word "llm_alias" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "ResponseAlias" +Word "own_alias" +Word "ConfigAlias" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_auth_auth.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_auth_auth.snap new file mode 100644 index 0000000000..0309454684 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_auth_auth.snap @@ -0,0 +1,1013 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Slash "/" +Slash "/" +Word "AUTH" +Word "NAMESPACE" +Error "—" +Word "defines" +Word "Config" +Comma "," +Word "Error" +Comma "," +Word "Role" +Slash "/" +Slash "/" +Slash "/" +Slash "/" +Word "Config" +Word "and" +Word "Error" +Word "have" +Word "the" +Word "SAME" +Word "names" +Word "as" +Word "root" +Word "and" +Word "llm" +Word "types" +Dot "." +Slash "/" +Slash "/" +Word "Bare" +Word "references" +Word "here" +Word "must" +Word "resolve" +Word "to" +Word "the" +Word "AUTH" +Word "versions" +Dot "." +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Class "class" +Word "Config" +LBrace "{" +Word "provider" +Word "string" +Word "secret" +Word "string" +RBrace "}" +Class "class" +Word "Error" +LBrace "{" +Word "realm" +Word "string" +Word "expired" +Word "bool" +RBrace "}" +Enum "enum" +Word "Role" +LBrace "{" +Word "Admin" +Word "User" +Word "Guest" +RBrace "}" +Class "class" +Word "Token" +LBrace "{" +Word "value" +Word "string" +Word "role" +Word "Role" +RBrace "}" +Word "type" +Word "TokenAlias" +Equals "=" +Word "Token" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Bare" +Word "name" +Word "usage" +LParen "(" +Word "must" +Word "resolve" +Word "to" +Word "auth" +Dot "." +Star "*" +Word "NOT" +Word "root" +Dot "." +Star "*" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Bare" +Word "Config" +Word "param" +Colon ":" +Word "must" +Word "be" +Word "auth" +Dot "." +Word "Config" +LParen "(" +Dot "." +Word "provider" +RParen ")" +Comma "," +Word "not" +Word "root" +LParen "(" +Dot "." +Word "key" +RParen ")" +Word "or" +Word "llm" +LParen "(" +Dot "." +Word "model" +RParen ")" +Function "function" +Word "AuthIdentity" +LParen "(" +Word "cfg" +Colon ":" +Word "Config" +RParen ")" +Arrow "->" +Word "Config" +LBrace "{" +Word "cfg" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "constructor" +Colon ":" +Word "must" +Word "build" +Word "auth" +Dot "." +Word "Config" +Function "function" +Word "AuthConstruct" +LParen "(" +Word "provider" +Colon ":" +Word "string" +RParen ")" +Arrow "->" +Word "Config" +LBrace "{" +Word "Config" +LBrace "{" +Word "provider" +Colon ":" +Word "provider" +Comma "," +Word "secret" +Colon ":" +Quote "\"" +Word "s3cret" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Enum "enum" +Return "return" +Colon ":" +Word "must" +Word "be" +Word "auth" +Dot "." +Word "Role" +Dot "." +Word "Admin" +Function "function" +Word "AuthEnumReturn" +LParen "(" +RParen ")" +Arrow "->" +Word "Role" +LBrace "{" +Word "Role" +Dot "." +Word "Admin" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Enum "enum" +Match "match" +Colon ":" +Word "must" +Match "match" +Word "against" +Word "auth" +Dot "." +Word "Role" +Word "variants" +Function "function" +Word "AuthEnumMatch" +LParen "(" +Word "r" +Colon ":" +Word "Role" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "r" +RParen ")" +LBrace "{" +Word "Role" +Dot "." +Word "Admin" +FatArrow "=>" +Quote "\"" +Word "admin" +Quote "\"" +Comma "," +Word "Role" +Dot "." +Word "User" +FatArrow "=>" +Quote "\"" +Word "user" +Quote "\"" +Comma "," +Word "Role" +Dot "." +Word "Guest" +FatArrow "=>" +Quote "\"" +Word "guest" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "alias" +Colon ":" +Word "must" +Word "be" +Word "auth" +Dot "." +Word "TokenAlias" +Equals "=" +Word "auth" +Dot "." +Word "Token" +Function "function" +Word "AuthAliasParam" +LParen "(" +Word "t" +Colon ":" +Word "TokenAlias" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "t" +Dot "." +Word "value" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Class "class" +In "in" +Throw "throw" +Function "function" +Word "AuthThrowClass" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Error" +LBrace "{" +Word "realm" +Colon ":" +Quote "\"" +Word "auth" +Word "failed" +Quote "\"" +Comma "," +Word "expired" +Colon ":" +Word "true" +RBrace "}" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Enum "enum" +In "in" +Throw "throw" +Function "function" +Word "AuthThrowEnum" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Role" +Dot "." +Word "Guest" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Token" +Word "constructor" +Word "with" +Word "nested" +Enum "enum" +Word "field" +Function "function" +Word "AuthMakeToken" +LParen "(" +Word "v" +Colon ":" +Word "string" +RParen ")" +Arrow "->" +Word "Token" +LBrace "{" +Word "Token" +LBrace "{" +Word "value" +Colon ":" +Word "v" +Comma "," +Word "role" +Colon ":" +Word "Role" +Dot "." +Word "User" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "root" +Dot "." +Word "X" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "AuthUsesRootConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "key" +RBrace "}" +Function "function" +Word "AuthUsesRootStatus" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "Status" +LBrace "{" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Pending" +RBrace "}" +Function "function" +Word "AuthMatchesRootStatus" +LParen "(" +Word "s" +Colon ":" +Word "root" +Dot "." +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Failed" +FatArrow "=>" +Quote "\"" +Word "failed" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Pending" +FatArrow "=>" +Quote "\"" +Word "pending" +Quote "\"" +RBrace "}" +RBrace "}" +Function "function" +Word "AuthThrowsRootError" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "root" +Dot "." +Word "Error" +LBrace "{" +Word "code" +Colon ":" +IntegerLiteral "403" +Comma "," +Word "message" +Colon ":" +Quote "\"" +Word "forbidden" +Quote "\"" +RBrace "}" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "sibling" +LParen "(" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "X" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "AuthUsesLlmConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "model" +RBrace "}" +Function "function" +Word "AuthUsesLlmResponse" +LParen "(" +Word "r" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Response" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "r" +Dot "." +Word "text" +RBrace "}" +Function "function" +Word "AuthUsesLlmStatus" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +LBrace "{" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Ready" +RBrace "}" +Function "function" +Word "AuthMatchesLlmStatus" +LParen "(" +Word "s" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Ready" +FatArrow "=>" +Quote "\"" +Word "ready" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Generating" +FatArrow "=>" +Quote "\"" +Word "generating" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Done" +FatArrow "=>" +Quote "\"" +Word "done" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "nested" +LParen "(" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "X" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "AuthUsesNestedClient" +LParen "(" +Word "c" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "Client" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "c" +Dot "." +Word "api_key" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Mixed" +Colon ":" +Word "auth" +Plus "+" +Word "root" +Plus "+" +Word "llm" +Word "types" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "AuthMixedConfigs" +LParen "(" +Word "auth_cfg" +Colon ":" +Word "Config" +Comma "," +Word "root_cfg" +Colon ":" +Word "root" +Dot "." +Word "Config" +Comma "," +Word "llm_cfg" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "auth_cfg" +Dot "." +Word "provider" +RBrace "}" +Slash "/" +Slash "/" +Word "auth" +Dot "." +Word "Error" +Plus "+" +Word "root" +Dot "." +Word "Error" +Plus "+" +Word "llm" +Dot "." +Word "Error" +Error "—" +Word "three" +Word "different" +Word "types" +Function "function" +Word "AuthMixedErrors" +LParen "(" +Word "auth_err" +Colon ":" +Word "Error" +Comma "," +Word "root_err" +Colon ":" +Word "root" +Dot "." +Word "Error" +Comma "," +Word "llm_err" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Error" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "auth_err" +Dot "." +Word "realm" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_models.snap new file mode 100644 index 0000000000..67240fecb8 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_models.snap @@ -0,0 +1,1247 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Slash "/" +Slash "/" +Word "LLM" +Word "NAMESPACE" +Error "—" +Word "defines" +Word "Config" +Comma "," +Word "Error" +Comma "," +Word "Status" +Comma "," +Word "ConfigAlias" +Slash "/" +Slash "/" +Slash "/" +Slash "/" +Word "These" +Word "have" +Word "the" +Word "SAME" +Word "names" +Word "as" +Word "root" +Word "types" +Dot "." +Word "Bare" +Word "references" +Word "here" +Slash "/" +Slash "/" +Word "must" +Word "resolve" +Word "to" +Word "the" +Word "LLM" +Word "versions" +Comma "," +Word "NOT" +Word "root" +Word "versions" +Dot "." +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Class "class" +Word "Config" +LBrace "{" +Word "model" +Word "string" +Word "temperature" +Word "float" +RBrace "}" +Class "class" +Word "Error" +LBrace "{" +Word "reason" +Word "string" +Word "retryable" +Word "bool" +RBrace "}" +Enum "enum" +Word "Status" +LBrace "{" +Word "Ready" +Word "Generating" +Word "Done" +RBrace "}" +Enum "enum" +Word "Model" +LBrace "{" +Word "GPT4" +Word "Claude" +RBrace "}" +Class "class" +Word "Response" +LBrace "{" +Word "text" +Word "string" +Word "tokens" +Word "int" +RBrace "}" +Word "type" +Word "ConfigAlias" +Equals "=" +Word "Config" +Word "type" +Word "ResponseAlias" +Equals "=" +Word "Response" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Bare" +Word "name" +Word "usage" +LParen "(" +Word "must" +Word "resolve" +Word "to" +Word "llm" +Dot "." +Star "*" +Word "NOT" +Word "root" +Dot "." +Star "*" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Bare" +Word "Config" +Word "param" +Colon ":" +Word "must" +Word "be" +Word "llm" +Dot "." +Word "Config" +LParen "(" +Word "has" +Dot "." +Word "model" +RParen ")" +Comma "," +Word "not" +Word "root" +Dot "." +Word "Config" +LParen "(" +Word "has" +Dot "." +Word "key" +RParen ")" +Function "function" +Word "LlmIdentity" +LParen "(" +Word "cfg" +Colon ":" +Word "Config" +RParen ")" +Arrow "->" +Word "Config" +LBrace "{" +Word "cfg" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "constructor" +Colon ":" +Word "must" +Word "build" +Word "llm" +Dot "." +Word "Config" +Function "function" +Word "LlmConstruct" +LParen "(" +Word "model" +Colon ":" +Word "string" +RParen ")" +Arrow "->" +Word "Config" +LBrace "{" +Word "Config" +LBrace "{" +Word "model" +Colon ":" +Word "model" +Comma "," +Word "temperature" +Colon ":" +FloatLiteral "0.7" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Enum "enum" +Return "return" +Colon ":" +Word "must" +Word "be" +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Ready" +Comma "," +Word "not" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +Function "function" +Word "LlmEnumReturn" +LParen "(" +RParen ")" +Arrow "->" +Word "Status" +LBrace "{" +Word "Status" +Dot "." +Word "Ready" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Enum "enum" +Match "match" +Colon ":" +Word "must" +Match "match" +Word "against" +Word "llm" +Dot "." +Word "Status" +Word "variants" +Function "function" +Word "LlmEnumMatch" +LParen "(" +Word "s" +Colon ":" +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "Status" +Dot "." +Word "Ready" +FatArrow "=>" +Quote "\"" +Word "ready" +Quote "\"" +Comma "," +Word "Status" +Dot "." +Word "Generating" +FatArrow "=>" +Quote "\"" +Word "generating" +Quote "\"" +Comma "," +Word "Status" +Dot "." +Word "Done" +FatArrow "=>" +Quote "\"" +Word "done" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "alias" +Colon ":" +Word "must" +Word "be" +Word "llm" +Dot "." +Word "ConfigAlias" +Equals "=" +Word "llm" +Dot "." +Word "Config" +Function "function" +Word "LlmAliasParam" +LParen "(" +Word "cfg" +Colon ":" +Word "ConfigAlias" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "model" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Class "class" +In "in" +Throw "throw" +Function "function" +Word "LlmThrowClass" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Error" +LBrace "{" +Word "reason" +Colon ":" +Quote "\"" +Word "llm" +Word "failed" +Quote "\"" +Comma "," +Word "retryable" +Colon ":" +Word "true" +RBrace "}" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Enum "enum" +In "in" +Throw "throw" +Function "function" +Word "LlmThrowEnum" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Status" +Dot "." +Word "Done" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Bare" +Word "constructor" +Word "with" +Word "field" +Word "access" +Function "function" +Word "LlmResponseConstruct" +LParen "(" +Word "text" +Colon ":" +Word "string" +RParen ")" +Arrow "->" +Word "Response" +LBrace "{" +Word "Response" +LBrace "{" +Word "text" +Colon ":" +Word "text" +Comma "," +Word "tokens" +Colon ":" +IntegerLiteral "42" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "root" +Dot "." +Word "X" +LParen "(" +Word "must" +Word "get" +Word "root" +Word "types" +Comma "," +Word "not" +Word "llm" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "root" +Dot "." +Word "Config" +Word "has" +Dot "." +Word "key" +LParen "(" +Word "not" +Dot "." +Word "model" +RParen ")" +Error "—" +Word "proves" +Word "it" +Error "'" +Word "s" +Word "root" +Dot "." +Word "Config" +Function "function" +Word "LlmUsesRootConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "key" +RBrace "}" +Slash "/" +Slash "/" +Word "root" +Dot "." +Word "Error" +Word "has" +Dot "." +Word "code" +LParen "(" +Word "not" +Dot "." +Word "reason" +RParen ")" +Error "—" +Word "proves" +Word "it" +Error "'" +Word "s" +Word "root" +Dot "." +Word "Error" +Function "function" +Word "LlmUsesRootError" +LParen "(" +Word "e" +Colon ":" +Word "root" +Dot "." +Word "Error" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "e" +Dot "." +Word "message" +RBrace "}" +Slash "/" +Slash "/" +Word "root" +Dot "." +Word "Status" +Word "has" +Word "Ok" +Slash "/" +Word "Failed" +Slash "/" +Word "Pending" +Comma "," +Word "not" +Word "Ready" +Slash "/" +Word "Generating" +Slash "/" +Word "Done" +Function "function" +Word "LlmUsesRootStatus" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "Status" +LBrace "{" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +RBrace "}" +Slash "/" +Slash "/" +Word "root" +Dot "." +Word "Status" +Match "match" +Error "—" +Word "must" +Match "match" +Word "root" +Word "variants" +Function "function" +Word "LlmMatchesRootStatus" +LParen "(" +Word "s" +Colon ":" +Word "root" +Dot "." +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Failed" +FatArrow "=>" +Quote "\"" +Word "failed" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Pending" +FatArrow "=>" +Quote "\"" +Word "pending" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "root" +Dot "." +Word "ConfigAlias" +Word "must" +Word "be" +Word "root" +Dot "." +Word "ConfigAlias" +Equals "=" +Word "root" +Dot "." +Word "Config" +Function "function" +Word "LlmUsesRootAlias" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "ConfigAlias" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "key" +RBrace "}" +Slash "/" +Slash "/" +Word "Throw" +Word "root" +Dot "." +Word "Error" +Word "from" +Word "llm" +Word "namespace" +Function "function" +Word "LlmThrowsRootError" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "root" +Dot "." +Word "Error" +LBrace "{" +Word "code" +Colon ":" +IntegerLiteral "404" +Comma "," +Word "message" +Colon ":" +Quote "\"" +Word "not" +Word "found" +Quote "\"" +RBrace "}" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Word "Throw" +Word "root" +Enum "enum" +Word "variant" +Function "function" +Word "LlmThrowsRootEnum" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Failed" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "sibling" +Word "namespace" +LParen "(" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "X" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Reference" +Word "ns_auth" +Dot "." +Word "Config" +LParen "(" +Word "has" +Dot "." +Word "provider" +RParen ")" +Word "from" +Word "ns_llm" +Function "function" +Word "LlmUsesAuthConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "provider" +RBrace "}" +Slash "/" +Slash "/" +Word "Reference" +Word "ns_auth" +Dot "." +Word "Error" +LParen "(" +Word "has" +Dot "." +Word "realm" +RParen ")" +Word "from" +Word "ns_llm" +Function "function" +Word "LlmUsesAuthError" +LParen "(" +Word "e" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Error" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "e" +Dot "." +Word "realm" +RBrace "}" +Slash "/" +Slash "/" +Word "Reference" +Word "ns_auth" +Dot "." +Word "Role" +Enum "enum" +Word "from" +Word "ns_llm" +Function "function" +Word "LlmUsesAuthRole" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +LBrace "{" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +Dot "." +Word "Admin" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "child" +Word "namespace" +LParen "(" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "X" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Reference" +Word "nested" +Word "openai" +Dot "." +Word "Client" +Word "from" +Word "parent" +Word "llm" +Word "namespace" +Function "function" +Word "LlmUsesNestedClient" +LParen "(" +Word "c" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "Client" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "c" +Dot "." +Word "api_key" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Mixed" +Colon ":" +Word "llm" +Word "types" +Plus "+" +Word "qualified" +Word "root" +Slash "/" +Word "auth" +Word "types" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "All" +Word "three" +Word "Configs" +In "in" +Word "one" +Word "signature" +Error "—" +Word "must" +Word "be" +Word "three" +Word "different" +Word "types" +Function "function" +Word "LlmMixedConfigs" +LParen "(" +Word "llm_cfg" +Colon ":" +Word "Config" +Comma "," +Word "root_cfg" +Colon ":" +Word "root" +Dot "." +Word "Config" +Comma "," +Word "auth_cfg" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "llm_cfg" +Dot "." +Word "model" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Stream" +Word "companion" +Word "types" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Classes" +Word "with" +Word "cross-namespace" +Word "field" +Word "types" +Dot "." +Slash "/" +Slash "/" +Word "The" +Word "$stream" +Word "companions" +Word "must" +Word "resolve" +Word "all" +Word "field" +Word "types" +Comma "," +Word "including" +Slash "/" +Slash "/" +Word "types" +Word "from" +Word "root" +Word "and" +Word "sibling" +Word "namespaces" +Dot "." +Slash "/" +Slash "/" +Word "llm" +Class "class" +Word "with" +Word "fields" +Word "from" +Word "root" +Word "and" +Word "sibling" +Word "namespaces" +Class "class" +Word "LlmWithCrossNsFields" +LBrace "{" +Word "own_config" +Word "Config" +Word "own_response" +Word "Response" +Word "root_config" +Word "root" +Dot "." +Word "Config" +Word "root_error" +Word "root" +Dot "." +Word "Error" +Word "auth_config" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Config" +Word "nested_client" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "openai" +Dot "." +Word "Client" +Word "own_status" +Word "Status" +Word "own_alias" +Word "ConfigAlias" +Word "root_alias" +Word "root" +Dot "." +Word "ConfigAlias" +RBrace "}" +Slash "/" +Slash "/" +Word "llm" +Class "class" +Word "referencing" +Word "root" +Word "type" +Word "alias" +LParen "(" +Word "this" +Word "was" +Word "the" +Word "alias" +Word "stream" +Word "bug" +RParen ")" +Class "class" +Word "LlmWithRootAlias" +LBrace "{" +Word "root_alias" +Word "root" +Dot "." +Word "ConfigAlias" +Word "own_alias" +Word "ResponseAlias" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_ns_openai_client.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_ns_openai_client.snap new file mode 100644 index 0000000000..f613609329 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__01_lexer__ns_llm_ns_openai_client.snap @@ -0,0 +1,978 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Slash "/" +Slash "/" +Word "LLM" +Dot "." +Word "OPENAI" +Word "NAMESPACE" +LParen "(" +Word "nested" +RParen ")" +Error "—" +Word "defines" +Word "Client" +Comma "," +Word "Error" +Comma "," +Word "Model" +Slash "/" +Slash "/" +Slash "/" +Slash "/" +Word "Error" +Word "and" +Word "Model" +Word "have" +Word "the" +Word "SAME" +Word "names" +Word "as" +Word "root" +Comma "," +Word "llm" +Comma "," +Word "and" +Word "auth" +Word "types" +Dot "." +Slash "/" +Slash "/" +Word "Bare" +Word "references" +Word "here" +Word "must" +Word "resolve" +Word "to" +Word "the" +Word "openai" +Word "versions" +Dot "." +Slash "/" +Slash "/" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Error "═" +Class "class" +Word "Client" +LBrace "{" +Word "api_key" +Word "string" +Word "org_id" +Word "string" +RBrace "}" +Class "class" +Word "Error" +LBrace "{" +Word "status_code" +Word "int" +Word "body" +Word "string" +RBrace "}" +Enum "enum" +Word "Model" +LBrace "{" +Word "GPT4o" +Word "GPT4oMini" +Word "O3" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Bare" +Word "name" +Word "usage" +LParen "(" +Word "must" +Word "resolve" +Word "to" +Word "llm" +Dot "." +Word "openai" +Dot "." +Star "*" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "OpenAIIdentity" +LParen "(" +Word "c" +Colon ":" +Word "Client" +RParen ")" +Arrow "->" +Word "Client" +LBrace "{" +Word "c" +RBrace "}" +Function "function" +Word "OpenAIConstruct" +LParen "(" +Word "key" +Colon ":" +Word "string" +RParen ")" +Arrow "->" +Word "Client" +LBrace "{" +Word "Client" +LBrace "{" +Word "api_key" +Colon ":" +Word "key" +Comma "," +Word "org_id" +Colon ":" +Quote "\"" +Word "org-123" +Quote "\"" +RBrace "}" +RBrace "}" +Function "function" +Word "OpenAIEnumReturn" +LParen "(" +RParen ")" +Arrow "->" +Word "Model" +LBrace "{" +Word "Model" +Dot "." +Word "GPT4o" +RBrace "}" +Function "function" +Word "OpenAIEnumMatch" +LParen "(" +Word "m" +Colon ":" +Word "Model" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "m" +RParen ")" +LBrace "{" +Word "Model" +Dot "." +Word "GPT4o" +FatArrow "=>" +Quote "\"" +Word "gpt4o" +Quote "\"" +Comma "," +Word "Model" +Dot "." +Word "GPT4oMini" +FatArrow "=>" +Quote "\"" +Word "gpt4o-mini" +Quote "\"" +Comma "," +Word "Model" +Dot "." +Word "O3" +FatArrow "=>" +Quote "\"" +Word "o3" +Quote "\"" +RBrace "}" +RBrace "}" +Function "function" +Word "OpenAIThrowClass" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Error" +LBrace "{" +Word "status_code" +Colon ":" +IntegerLiteral "429" +Comma "," +Word "body" +Colon ":" +Quote "\"" +Word "rate" +Word "limited" +Quote "\"" +RBrace "}" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Function "function" +Word "OpenAIThrowEnum" +LParen "(" +Word "x" +Colon ":" +Word "int" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "x" +RParen ")" +LBrace "{" +IntegerLiteral "0" +FatArrow "=>" +Throw "throw" +Word "Model" +Dot "." +Word "O3" +Comma "," +Word "_" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "root" +Dot "." +Word "X" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "OpenAIUsesRootConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "key" +RBrace "}" +Function "function" +Word "OpenAIUsesRootStatus" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "Status" +LBrace "{" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +RBrace "}" +Function "function" +Word "OpenAIMatchesRootStatus" +LParen "(" +Word "s" +Colon ":" +Word "root" +Dot "." +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Ok" +FatArrow "=>" +Quote "\"" +Word "ok" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Failed" +FatArrow "=>" +Quote "\"" +Word "failed" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "Status" +Dot "." +Word "Pending" +FatArrow "=>" +Quote "\"" +Word "pending" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "parent" +LParen "(" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "X" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "Parent" +Word "llm" +Word "namespace" +Error "—" +Word "NOT" +Word "the" +Word "same" +Word "as" +Word "bare" +Word "names" +Word "here" +Function "function" +Word "OpenAIUsesLlmConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "model" +RBrace "}" +Function "function" +Word "OpenAIUsesLlmResponse" +LParen "(" +Word "r" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Response" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "r" +Dot "." +Word "text" +RBrace "}" +Function "function" +Word "OpenAIUsesLlmStatus" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +LBrace "{" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Generating" +RBrace "}" +Function "function" +Word "OpenAIMatchesLlmStatus" +LParen "(" +Word "s" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "s" +RParen ")" +LBrace "{" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Ready" +FatArrow "=>" +Quote "\"" +Word "ready" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Generating" +FatArrow "=>" +Quote "\"" +Word "generating" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Status" +Dot "." +Word "Done" +FatArrow "=>" +Quote "\"" +Word "done" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Cross-namespace" +Colon ":" +Word "sibling" +Word "of" +Word "parent" +LParen "(" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "X" +RParen ")" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Function "function" +Word "OpenAIUsesAuthConfig" +LParen "(" +Word "cfg" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Config" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "cfg" +Dot "." +Word "provider" +RBrace "}" +Function "function" +Word "OpenAIUsesAuthRole" +LParen "(" +RParen ")" +Arrow "->" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +LBrace "{" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +Dot "." +Word "User" +RBrace "}" +Function "function" +Word "OpenAIMatchesAuthRole" +LParen "(" +Word "r" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "r" +RParen ")" +LBrace "{" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +Dot "." +Word "Admin" +FatArrow "=>" +Quote "\"" +Word "admin" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +Dot "." +Word "User" +FatArrow "=>" +Quote "\"" +Word "user" +Quote "\"" +Comma "," +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Role" +Dot "." +Word "Guest" +FatArrow "=>" +Quote "\"" +Word "guest" +Quote "\"" +RBrace "}" +RBrace "}" +Slash "/" +Slash "/" +Error "─" +Error "─" +Word "Mixed" +Colon ":" +Word "all" +Word "four" +Word "namespace" +Word "Errors" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Error "─" +Slash "/" +Slash "/" +Word "openai" +Dot "." +Word "Error" +LParen "(" +Dot "." +Word "status_code" +RParen ")" +Comma "," +Word "root" +Dot "." +Word "Error" +LParen "(" +Dot "." +Word "code" +RParen ")" +Comma "," +Slash "/" +Slash "/" +Word "llm" +Dot "." +Word "Error" +LParen "(" +Dot "." +Word "reason" +RParen ")" +Comma "," +Word "auth" +Dot "." +Word "Error" +LParen "(" +Dot "." +Word "realm" +RParen ")" +Function "function" +Word "OpenAIMixedErrors" +LParen "(" +Word "openai_err" +Colon ":" +Word "Error" +Comma "," +Word "root_err" +Colon ":" +Word "root" +Dot "." +Word "Error" +Comma "," +Word "llm_err" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Error" +Comma "," +Word "auth_err" +Colon ":" +Word "root" +Dot "." +Word "auth" +Dot "." +Word "Error" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Word "openai_err" +Dot "." +Word "body" +RBrace "}" +Slash "/" +Slash "/" +Word "openai" +Dot "." +Word "Model" +Comma "," +Word "llm" +Dot "." +Word "Model" +Error "—" +Word "both" +Word "named" +Word "Model" +Word "but" +Word "different" +Word "variants" +Function "function" +Word "OpenAIMixedModels" +LParen "(" +Word "openai_model" +Colon ":" +Word "Model" +Comma "," +Word "llm_model" +Colon ":" +Word "root" +Dot "." +Word "llm" +Dot "." +Word "Model" +RParen ")" +Arrow "->" +Word "string" +LBrace "{" +Match "match" +LParen "(" +Word "openai_model" +RParen ")" +LBrace "{" +Word "Model" +Dot "." +Word "GPT4o" +FatArrow "=>" +Quote "\"" +Word "gpt4o" +Quote "\"" +Comma "," +Word "Model" +Dot "." +Word "GPT4oMini" +FatArrow "=>" +Quote "\"" +Word "mini" +Quote "\"" +Comma "," +Word "Model" +Dot "." +Word "O3" +FatArrow "=>" +Quote "\"" +Word "o3" +Quote "\"" +RBrace "}" +RBrace "}" diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__main.snap new file mode 100644 index 0000000000..73deba57e6 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__main.snap @@ -0,0 +1,560 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Config" + L_BRACE "{" + FIELD + WORD "key" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "env" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Error" + L_BRACE "{" + FIELD + WORD "code" + TYPE_EXPR "int" + WORD "int" + FIELD + WORD "message" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + ENUM_DEF + KW_ENUM "enum" + WORD "Status" + L_BRACE "{" + ENUM_VARIANT "Ok" + WORD "Ok" + ENUM_VARIANT "Failed" + WORD "Failed" + ENUM_VARIANT "Pending" + WORD "Pending" + R_BRACE "}" + TYPE_ALIAS_DEF + WORD "type" + WORD "ConfigAlias" + EQUALS "=" + TYPE_EXPR "Config" + WORD "Config" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootIdentity" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Config" + WORD "Config" + EXPR_FUNCTION_BODY + BLOCK_EXPR "{ + cfg +}" + L_BRACE "{" + WORD "cfg" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootConstruct" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "key" + COLON ":" + TYPE_EXPR "string" + WORD "string" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Config" + WORD "Config" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Config" + L_BRACE "{" + OBJECT_FIELD "key: key" + WORD "key" + COLON ":" + WORD "key" + COMMA "," + OBJECT_FIELD + WORD "env" + COLON ":" + STRING_LITERAL "prod" + QUOTE """ + WORD "prod" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootEnumReturn" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Status" + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "Status.Ok" + WORD "Status" + DOT "." + WORD "Ok" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootEnumMatch" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "Status" + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "Status.Ok" + WORD "Status" + DOT "." + WORD "Ok" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Status.Failed" + WORD "Status" + DOT "." + WORD "Failed" + FAT_ARROW "=>" + STRING_LITERAL "failed" + QUOTE """ + WORD "failed" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Status.Pending" + WORD "Status" + DOT "." + WORD "Pending" + FAT_ARROW "=>" + STRING_LITERAL "pending" + QUOTE """ + WORD "pending" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootAliasParam" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "ConfigAlias" + WORD "ConfigAlias" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.key" + WORD "cfg" + DOT "." + WORD "key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootThrowClass" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + OBJECT_LITERAL + WORD "Error" + L_BRACE "{" + OBJECT_FIELD "code: 500" + WORD "code" + COLON ":" + INTEGER_LITERAL "500" + COMMA "," + OBJECT_FIELD + WORD "message" + COLON ":" + STRING_LITERAL "root error" + QUOTE """ + WORD "root" + WORD "error" + QUOTE """ + R_BRACE "}" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootThrowEnum" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + PATH_EXPR "Status.Failed" + WORD "Status" + DOT "." + WORD "Failed" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesLlmConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.llm.Config" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.model" + WORD "cfg" + DOT "." + WORD "model" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesLlmError" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "e" + COLON ":" + TYPE_EXPR "root.llm.Error" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Error" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "e.reason" + WORD "e" + DOT "." + WORD "reason" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesLlmStatus" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.llm.Status" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.llm.Status.Ready" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Ready" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesAuthConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.auth.Config" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.provider" + WORD "cfg" + DOT "." + WORD "provider" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesAuthError" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "e" + COLON ":" + TYPE_EXPR "root.auth.Error" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Error" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "e.realm" + WORD "e" + DOT "." + WORD "realm" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootUsesNestedClient" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "c" + COLON ":" + TYPE_EXPR "root.llm.openai.Client" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "openai" + DOT "." + WORD "Client" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "c.api_key" + WORD "c" + DOT "." + WORD "api_key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "RootMixedConfigs" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "root_cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + COMMA "," + PARAMETER + WORD "llm_cfg" + COLON ":" + TYPE_EXPR "root.llm.Config" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root_cfg.key" + WORD "root_cfg" + DOT "." + WORD "key" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "RootWithCrossNsFields" + L_BRACE "{" + FIELD + WORD "own_config" + TYPE_EXPR "Config" + WORD "Config" + FIELD + WORD "llm_config" + TYPE_EXPR "root.llm.Config" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config" + FIELD + WORD "auth_config" + TYPE_EXPR "root.auth.Config" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Config" + FIELD + WORD "llm_response" + TYPE_EXPR "root.llm.Response" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Response" + FIELD + WORD "nested_client" + TYPE_EXPR "root.llm.openai.Client" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "openai" + DOT "." + WORD "Client" + FIELD + WORD "own_status" + TYPE_EXPR "Status" + WORD "Status" + FIELD + WORD "own_alias" + TYPE_EXPR "ConfigAlias" + WORD "ConfigAlias" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "RootWithCrossNsAlias" + L_BRACE "{" + FIELD + WORD "llm_alias" + TYPE_EXPR "root.llm.ResponseAlias" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "ResponseAlias" + FIELD + WORD "own_alias" + TYPE_EXPR "ConfigAlias" + WORD "ConfigAlias" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_auth_auth.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_auth_auth.snap new file mode 100644 index 0000000000..076e42cc80 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_auth_auth.snap @@ -0,0 +1,777 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Config" + L_BRACE "{" + FIELD + WORD "provider" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "secret" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Error" + L_BRACE "{" + FIELD + WORD "realm" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "expired" + TYPE_EXPR "bool" + WORD "bool" + R_BRACE "}" + ENUM_DEF + KW_ENUM "enum" + WORD "Role" + L_BRACE "{" + ENUM_VARIANT "Admin" + WORD "Admin" + ENUM_VARIANT "User" + WORD "User" + ENUM_VARIANT "Guest" + WORD "Guest" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Token" + L_BRACE "{" + FIELD + WORD "value" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "role" + TYPE_EXPR "Role" + WORD "Role" + R_BRACE "}" + TYPE_ALIAS_DEF + WORD "type" + WORD "TokenAlias" + EQUALS "=" + TYPE_EXPR "Token" + WORD "Token" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthIdentity" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Config" + WORD "Config" + EXPR_FUNCTION_BODY + BLOCK_EXPR "{ + cfg +}" + L_BRACE "{" + WORD "cfg" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthConstruct" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "provider" + COLON ":" + TYPE_EXPR "string" + WORD "string" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Config" + WORD "Config" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Config" + L_BRACE "{" + OBJECT_FIELD "provider: provider" + WORD "provider" + COLON ":" + WORD "provider" + COMMA "," + OBJECT_FIELD + WORD "secret" + COLON ":" + STRING_LITERAL "s3cret" + QUOTE """ + WORD "s3cret" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthEnumReturn" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Role" + WORD "Role" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "Role.Admin" + WORD "Role" + DOT "." + WORD "Admin" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthEnumMatch" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "r" + COLON ":" + TYPE_EXPR "Role" + WORD "Role" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "r" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "Role.Admin" + WORD "Role" + DOT "." + WORD "Admin" + FAT_ARROW "=>" + STRING_LITERAL "admin" + QUOTE """ + WORD "admin" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Role.User" + WORD "Role" + DOT "." + WORD "User" + FAT_ARROW "=>" + STRING_LITERAL "user" + QUOTE """ + WORD "user" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Role.Guest" + WORD "Role" + DOT "." + WORD "Guest" + FAT_ARROW "=>" + STRING_LITERAL "guest" + QUOTE """ + WORD "guest" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthAliasParam" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "t" + COLON ":" + TYPE_EXPR "TokenAlias" + WORD "TokenAlias" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "t.value" + WORD "t" + DOT "." + WORD "value" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthThrowClass" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + OBJECT_LITERAL + WORD "Error" + L_BRACE "{" + OBJECT_FIELD + WORD "realm" + COLON ":" + STRING_LITERAL "auth failed" + QUOTE """ + WORD "auth" + WORD "failed" + QUOTE """ + COMMA "," + OBJECT_FIELD "expired: true" + WORD "expired" + COLON ":" + WORD "true" + R_BRACE "}" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthThrowEnum" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + PATH_EXPR "Role.Guest" + WORD "Role" + DOT "." + WORD "Guest" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthMakeToken" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "v" + COLON ":" + TYPE_EXPR "string" + WORD "string" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Token" + WORD "Token" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Token" + L_BRACE "{" + OBJECT_FIELD "value: v" + WORD "value" + COLON ":" + WORD "v" + COMMA "," + OBJECT_FIELD + WORD "role" + COLON ":" + PATH_EXPR "Role.User" + WORD "Role" + DOT "." + WORD "User" + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthUsesRootConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.key" + WORD "cfg" + DOT "." + WORD "key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthUsesRootStatus" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.Status" + WORD "root" + DOT "." + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.Status.Pending" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Pending" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthMatchesRootStatus" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "root.Status" + WORD "root" + DOT "." + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "root.Status.Ok" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Ok" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.Status.Failed" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Failed" + FAT_ARROW "=>" + STRING_LITERAL "failed" + QUOTE """ + WORD "failed" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.Status.Pending" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Pending" + FAT_ARROW "=>" + STRING_LITERAL "pending" + QUOTE """ + WORD "pending" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthThrowsRootError" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + OBJECT_LITERAL + PATH_EXPR "root.Error" + WORD "root" + DOT "." + WORD "Error" + L_BRACE "{" + OBJECT_FIELD "code: 403" + WORD "code" + COLON ":" + INTEGER_LITERAL "403" + COMMA "," + OBJECT_FIELD + WORD "message" + COLON ":" + STRING_LITERAL "forbidden" + QUOTE """ + WORD "forbidden" + QUOTE """ + R_BRACE "}" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthUsesLlmConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.llm.Config" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.model" + WORD "cfg" + DOT "." + WORD "model" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthUsesLlmResponse" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "r" + COLON ":" + TYPE_EXPR "root.llm.Response" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Response" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "r.text" + WORD "r" + DOT "." + WORD "text" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthUsesLlmStatus" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.llm.Status" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.llm.Status.Ready" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Ready" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthMatchesLlmStatus" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "root.llm.Status" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "root.llm.Status.Ready" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Ready" + FAT_ARROW "=>" + STRING_LITERAL "ready" + QUOTE """ + WORD "ready" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.llm.Status.Generating" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Generating" + FAT_ARROW "=>" + STRING_LITERAL "generating" + QUOTE """ + WORD "generating" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.llm.Status.Done" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Done" + FAT_ARROW "=>" + STRING_LITERAL "done" + QUOTE """ + WORD "done" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthUsesNestedClient" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "c" + COLON ":" + TYPE_EXPR "root.llm.openai.Client" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "openai" + DOT "." + WORD "Client" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "c.api_key" + WORD "c" + DOT "." + WORD "api_key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthMixedConfigs" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "auth_cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + COMMA "," + PARAMETER + WORD "root_cfg" + COLON ":" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." + WORD "Config" + COMMA "," + PARAMETER + WORD "llm_cfg" + COLON ":" + TYPE_EXPR "root.llm.Config" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "auth_cfg.provider" + WORD "auth_cfg" + DOT "." + WORD "provider" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "AuthMixedErrors" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "auth_err" + COLON ":" + TYPE_EXPR "Error" + WORD "Error" + COMMA "," + PARAMETER + WORD "root_err" + COLON ":" + TYPE_EXPR "root.Error" + WORD "root" + DOT "." + WORD "Error" + COMMA "," + PARAMETER + WORD "llm_err" + COLON ":" + TYPE_EXPR "root.llm.Error" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Error" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "auth_err.realm" + WORD "auth_err" + DOT "." + WORD "realm" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_models.snap new file mode 100644 index 0000000000..013d2a8a4f --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_models.snap @@ -0,0 +1,840 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Config" + L_BRACE "{" + FIELD + WORD "model" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "temperature" + TYPE_EXPR "float" + WORD "float" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Error" + L_BRACE "{" + FIELD + WORD "reason" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "retryable" + TYPE_EXPR "bool" + WORD "bool" + R_BRACE "}" + ENUM_DEF + KW_ENUM "enum" + WORD "Status" + L_BRACE "{" + ENUM_VARIANT "Ready" + WORD "Ready" + ENUM_VARIANT "Generating" + WORD "Generating" + ENUM_VARIANT "Done" + WORD "Done" + R_BRACE "}" + ENUM_DEF + KW_ENUM "enum" + WORD "Model" + L_BRACE "{" + ENUM_VARIANT "GPT4" + WORD "GPT4" + ENUM_VARIANT "Claude" + WORD "Claude" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Response" + L_BRACE "{" + FIELD + WORD "text" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "tokens" + TYPE_EXPR "int" + WORD "int" + R_BRACE "}" + TYPE_ALIAS_DEF + WORD "type" + WORD "ConfigAlias" + EQUALS "=" + TYPE_EXPR "Config" + WORD "Config" + TYPE_ALIAS_DEF + WORD "type" + WORD "ResponseAlias" + EQUALS "=" + TYPE_EXPR "Response" + WORD "Response" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmIdentity" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Config" + WORD "Config" + EXPR_FUNCTION_BODY + BLOCK_EXPR "{ + cfg +}" + L_BRACE "{" + WORD "cfg" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmConstruct" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "model" + COLON ":" + TYPE_EXPR "string" + WORD "string" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Config" + WORD "Config" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Config" + L_BRACE "{" + OBJECT_FIELD "model: model" + WORD "model" + COLON ":" + WORD "model" + COMMA "," + OBJECT_FIELD "temperature: 0.7" + WORD "temperature" + COLON ":" + FLOAT_LITERAL "0.7" + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmEnumReturn" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Status" + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "Status.Ready" + WORD "Status" + DOT "." + WORD "Ready" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmEnumMatch" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "Status" + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "Status.Ready" + WORD "Status" + DOT "." + WORD "Ready" + FAT_ARROW "=>" + STRING_LITERAL "ready" + QUOTE """ + WORD "ready" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Status.Generating" + WORD "Status" + DOT "." + WORD "Generating" + FAT_ARROW "=>" + STRING_LITERAL "generating" + QUOTE """ + WORD "generating" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Status.Done" + WORD "Status" + DOT "." + WORD "Done" + FAT_ARROW "=>" + STRING_LITERAL "done" + QUOTE """ + WORD "done" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmAliasParam" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "ConfigAlias" + WORD "ConfigAlias" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.model" + WORD "cfg" + DOT "." + WORD "model" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmThrowClass" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + OBJECT_LITERAL + WORD "Error" + L_BRACE "{" + OBJECT_FIELD + WORD "reason" + COLON ":" + STRING_LITERAL "llm failed" + QUOTE """ + WORD "llm" + WORD "failed" + QUOTE """ + COMMA "," + OBJECT_FIELD "retryable: true" + WORD "retryable" + COLON ":" + WORD "true" + R_BRACE "}" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmThrowEnum" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + PATH_EXPR "Status.Done" + WORD "Status" + DOT "." + WORD "Done" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmResponseConstruct" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "text" + COLON ":" + TYPE_EXPR "string" + WORD "string" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Response" + WORD "Response" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Response" + L_BRACE "{" + OBJECT_FIELD "text: text" + WORD "text" + COLON ":" + WORD "text" + COMMA "," + OBJECT_FIELD "tokens: 42" + WORD "tokens" + COLON ":" + INTEGER_LITERAL "42" + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesRootConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.key" + WORD "cfg" + DOT "." + WORD "key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesRootError" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "e" + COLON ":" + TYPE_EXPR "root.Error" + WORD "root" + DOT "." + WORD "Error" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "e.message" + WORD "e" + DOT "." + WORD "message" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesRootStatus" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.Status" + WORD "root" + DOT "." + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.Status.Ok" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Ok" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmMatchesRootStatus" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "root.Status" + WORD "root" + DOT "." + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "root.Status.Ok" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Ok" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.Status.Failed" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Failed" + FAT_ARROW "=>" + STRING_LITERAL "failed" + QUOTE """ + WORD "failed" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.Status.Pending" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Pending" + FAT_ARROW "=>" + STRING_LITERAL "pending" + QUOTE """ + WORD "pending" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesRootAlias" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.ConfigAlias" + WORD "root" + DOT "." + WORD "ConfigAlias" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.key" + WORD "cfg" + DOT "." + WORD "key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmThrowsRootError" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + OBJECT_LITERAL + PATH_EXPR "root.Error" + WORD "root" + DOT "." + WORD "Error" + L_BRACE "{" + OBJECT_FIELD "code: 404" + WORD "code" + COLON ":" + INTEGER_LITERAL "404" + COMMA "," + OBJECT_FIELD + WORD "message" + COLON ":" + STRING_LITERAL "not found" + QUOTE """ + WORD "not" + WORD "found" + QUOTE """ + R_BRACE "}" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmThrowsRootEnum" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + PATH_EXPR "root.Status.Failed" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Failed" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesAuthConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.auth.Config" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.provider" + WORD "cfg" + DOT "." + WORD "provider" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesAuthError" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "e" + COLON ":" + TYPE_EXPR "root.auth.Error" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Error" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "e.realm" + WORD "e" + DOT "." + WORD "realm" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesAuthRole" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.auth.Role" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.auth.Role.Admin" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + DOT "." + WORD "Admin" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmUsesNestedClient" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "c" + COLON ":" + TYPE_EXPR "root.llm.openai.Client" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "openai" + DOT "." + WORD "Client" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "c.api_key" + WORD "c" + DOT "." + WORD "api_key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "LlmMixedConfigs" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "llm_cfg" + COLON ":" + TYPE_EXPR "Config" + WORD "Config" + COMMA "," + PARAMETER + WORD "root_cfg" + COLON ":" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." + WORD "Config" + COMMA "," + PARAMETER + WORD "auth_cfg" + COLON ":" + TYPE_EXPR "root.auth.Config" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "llm_cfg.model" + WORD "llm_cfg" + DOT "." + WORD "model" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "LlmWithCrossNsFields" + L_BRACE "{" + FIELD + WORD "own_config" + TYPE_EXPR "Config" + WORD "Config" + FIELD + WORD "own_response" + TYPE_EXPR "Response" + WORD "Response" + FIELD + WORD "root_config" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." + WORD "Config" + FIELD + WORD "root_error" + TYPE_EXPR "root.Error" + WORD "root" + DOT "." + WORD "Error" + FIELD + WORD "auth_config" + TYPE_EXPR "root.auth.Config" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Config" + FIELD + WORD "nested_client" + TYPE_EXPR "root.llm.openai.Client" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "openai" + DOT "." + WORD "Client" + FIELD + WORD "own_status" + TYPE_EXPR "Status" + WORD "Status" + FIELD + WORD "own_alias" + TYPE_EXPR "ConfigAlias" + WORD "ConfigAlias" + FIELD + WORD "root_alias" + TYPE_EXPR "root.ConfigAlias" + WORD "root" + DOT "." + WORD "ConfigAlias" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "LlmWithRootAlias" + L_BRACE "{" + FIELD + WORD "root_alias" + TYPE_EXPR "root.ConfigAlias" + WORD "root" + DOT "." + WORD "ConfigAlias" + FIELD + WORD "own_alias" + TYPE_EXPR "ResponseAlias" + WORD "ResponseAlias" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_ns_openai_client.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_ns_openai_client.snap new file mode 100644 index 0000000000..d83965f088 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__02_parser__ns_llm_ns_openai_client.snap @@ -0,0 +1,776 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== SYNTAX TREE === +SOURCE_FILE + CLASS_DEF + KW_CLASS "class" + WORD "Client" + L_BRACE "{" + FIELD + WORD "api_key" + TYPE_EXPR "string" + WORD "string" + FIELD + WORD "org_id" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + CLASS_DEF + KW_CLASS "class" + WORD "Error" + L_BRACE "{" + FIELD + WORD "status_code" + TYPE_EXPR "int" + WORD "int" + FIELD + WORD "body" + TYPE_EXPR "string" + WORD "string" + R_BRACE "}" + ENUM_DEF + KW_ENUM "enum" + WORD "Model" + L_BRACE "{" + ENUM_VARIANT "GPT4o" + WORD "GPT4o" + ENUM_VARIANT "GPT4oMini" + WORD "GPT4oMini" + ENUM_VARIANT "O3" + WORD "O3" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIIdentity" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "c" + COLON ":" + TYPE_EXPR "Client" + WORD "Client" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Client" + WORD "Client" + EXPR_FUNCTION_BODY + BLOCK_EXPR "{ + c +}" + L_BRACE "{" + WORD "c" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIConstruct" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "key" + COLON ":" + TYPE_EXPR "string" + WORD "string" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Client" + WORD "Client" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + OBJECT_LITERAL + WORD "Client" + L_BRACE "{" + OBJECT_FIELD "api_key: key" + WORD "api_key" + COLON ":" + WORD "key" + COMMA "," + OBJECT_FIELD + WORD "org_id" + COLON ":" + STRING_LITERAL "org-123" + QUOTE """ + WORD "org-123" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIEnumReturn" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "Model" + WORD "Model" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "Model.GPT4o" + WORD "Model" + DOT "." + WORD "GPT4o" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIEnumMatch" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "m" + COLON ":" + TYPE_EXPR "Model" + WORD "Model" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "m" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "Model.GPT4o" + WORD "Model" + DOT "." + WORD "GPT4o" + FAT_ARROW "=>" + STRING_LITERAL "gpt4o" + QUOTE """ + WORD "gpt4o" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Model.GPT4oMini" + WORD "Model" + DOT "." + WORD "GPT4oMini" + FAT_ARROW "=>" + STRING_LITERAL "gpt4o-mini" + QUOTE """ + WORD "gpt4o-mini" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Model.O3" + WORD "Model" + DOT "." + WORD "O3" + FAT_ARROW "=>" + STRING_LITERAL "o3" + QUOTE """ + WORD "o3" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIThrowClass" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + OBJECT_LITERAL + WORD "Error" + L_BRACE "{" + OBJECT_FIELD "status_code: 429" + WORD "status_code" + COLON ":" + INTEGER_LITERAL "429" + COMMA "," + OBJECT_FIELD + WORD "body" + COLON ":" + STRING_LITERAL "rate limited" + QUOTE """ + WORD "rate" + WORD "limited" + QUOTE """ + R_BRACE "}" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIThrowEnum" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "x" + COLON ":" + TYPE_EXPR "int" + WORD "int" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "x" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "0" + INTEGER_LITERAL "0" + FAT_ARROW "=>" + THROW_EXPR + KW_THROW "throw" + PATH_EXPR "Model.O3" + WORD "Model" + DOT "." + WORD "O3" + COMMA "," + MATCH_ARM + MATCH_PATTERN "_" + WORD "_" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesRootConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.Config" + WORD "root" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.key" + WORD "cfg" + DOT "." + WORD "key" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesRootStatus" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.Status" + WORD "root" + DOT "." + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.Status.Ok" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Ok" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIMatchesRootStatus" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "root.Status" + WORD "root" + DOT "." + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "root.Status.Ok" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Ok" + FAT_ARROW "=>" + STRING_LITERAL "ok" + QUOTE """ + WORD "ok" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.Status.Failed" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Failed" + FAT_ARROW "=>" + STRING_LITERAL "failed" + QUOTE """ + WORD "failed" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.Status.Pending" + WORD "root" + DOT "." + WORD "Status" + DOT "." + WORD "Pending" + FAT_ARROW "=>" + STRING_LITERAL "pending" + QUOTE """ + WORD "pending" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesLlmConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.llm.Config" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.model" + WORD "cfg" + DOT "." + WORD "model" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesLlmResponse" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "r" + COLON ":" + TYPE_EXPR "root.llm.Response" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Response" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "r.text" + WORD "r" + DOT "." + WORD "text" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesLlmStatus" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.llm.Status" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.llm.Status.Generating" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Generating" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIMatchesLlmStatus" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "s" + COLON ":" + TYPE_EXPR "root.llm.Status" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "s" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "root.llm.Status.Ready" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Ready" + FAT_ARROW "=>" + STRING_LITERAL "ready" + QUOTE """ + WORD "ready" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.llm.Status.Generating" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Generating" + FAT_ARROW "=>" + STRING_LITERAL "generating" + QUOTE """ + WORD "generating" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.llm.Status.Done" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Status" + DOT "." + WORD "Done" + FAT_ARROW "=>" + STRING_LITERAL "done" + QUOTE """ + WORD "done" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesAuthConfig" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "cfg" + COLON ":" + TYPE_EXPR "root.auth.Config" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Config" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "cfg.provider" + WORD "cfg" + DOT "." + WORD "provider" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIUsesAuthRole" + PARAMETER_LIST "()" + L_PAREN "(" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "root.auth.Role" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "root.auth.Role.User" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + DOT "." + WORD "User" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIMatchesAuthRole" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "r" + COLON ":" + TYPE_EXPR "root.auth.Role" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "r" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "root.auth.Role.Admin" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + DOT "." + WORD "Admin" + FAT_ARROW "=>" + STRING_LITERAL "admin" + QUOTE """ + WORD "admin" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.auth.Role.User" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + DOT "." + WORD "User" + FAT_ARROW "=>" + STRING_LITERAL "user" + QUOTE """ + WORD "user" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "root.auth.Role.Guest" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Role" + DOT "." + WORD "Guest" + FAT_ARROW "=>" + STRING_LITERAL "guest" + QUOTE """ + WORD "guest" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIMixedErrors" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "openai_err" + COLON ":" + TYPE_EXPR "Error" + WORD "Error" + COMMA "," + PARAMETER + WORD "root_err" + COLON ":" + TYPE_EXPR "root.Error" + WORD "root" + DOT "." + WORD "Error" + COMMA "," + PARAMETER + WORD "llm_err" + COLON ":" + TYPE_EXPR "root.llm.Error" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Error" + COMMA "," + PARAMETER + WORD "auth_err" + COLON ":" + TYPE_EXPR "root.auth.Error" + WORD "root" + DOT "." + WORD "auth" + DOT "." + WORD "Error" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + PATH_EXPR "openai_err.body" + WORD "openai_err" + DOT "." + WORD "body" + R_BRACE "}" + FUNCTION_DEF + KW_FUNCTION "function" + WORD "OpenAIMixedModels" + PARAMETER_LIST + L_PAREN "(" + PARAMETER + WORD "openai_model" + COLON ":" + TYPE_EXPR "Model" + WORD "Model" + COMMA "," + PARAMETER + WORD "llm_model" + COLON ":" + TYPE_EXPR "root.llm.Model" + WORD "root" + DOT "." + WORD "llm" + DOT "." + WORD "Model" + R_PAREN ")" + ARROW "->" + TYPE_EXPR "string" + WORD "string" + EXPR_FUNCTION_BODY + BLOCK_EXPR + L_BRACE "{" + MATCH_EXPR + KW_MATCH "match" + L_PAREN "(" + WORD "openai_model" + R_PAREN ")" + L_BRACE "{" + MATCH_ARM + MATCH_PATTERN "Model.GPT4o" + WORD "Model" + DOT "." + WORD "GPT4o" + FAT_ARROW "=>" + STRING_LITERAL "gpt4o" + QUOTE """ + WORD "gpt4o" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Model.GPT4oMini" + WORD "Model" + DOT "." + WORD "GPT4oMini" + FAT_ARROW "=>" + STRING_LITERAL "mini" + QUOTE """ + WORD "mini" + QUOTE """ + COMMA "," + MATCH_ARM + MATCH_PATTERN "Model.O3" + WORD "Model" + DOT "." + WORD "O3" + FAT_ARROW "=>" + STRING_LITERAL "o3" + QUOTE """ + WORD "o3" + QUOTE """ + R_BRACE "}" + R_BRACE "}" + +=== ERRORS === +None diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__03_hir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__03_hir.snap new file mode 100644 index 0000000000..ec6e58b92e --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__03_hir.snap @@ -0,0 +1,294 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== HIR2 === +class user.Config { + key: string + env: string +} +class user.Error { + code: int + message: string +} +class user.RootWithCrossNsAlias { + llm_alias: root.llm.ResponseAlias + own_alias: user.ConfigAlias +} +class user.RootWithCrossNsFields { + own_config: user.Config + llm_config: root.llm.Config + auth_config: root.auth.Config + llm_response: root.llm.Response + nested_client: root.llm.openai.Client + own_status: user.Status + own_alias: user.ConfigAlias +} +enum user.Status {Ok, Failed, Pending} +type user.ConfigAlias = user.Config +function user.RootAliasParam(cfg: user.ConfigAlias) -> string [expr] { + { } cfg.key +} +function user.RootConstruct(key: string) -> user.Config [expr] { + { } user.Config { key: key, env: "prod" } +} +function user.RootEnumMatch(s: user.Status) -> string [expr] { + { } match (s) { user.Status.Ok => "ok", user.Status.Failed => "failed", user.Status.Pending => "pending" } +} +function user.RootEnumReturn() -> user.Status [expr] { + { } Status.Ok +} +function user.RootIdentity(cfg: user.Config) -> user.Config [expr] { + { } cfg +} +function user.RootMixedConfigs(root_cfg: user.Config, llm_cfg: root.llm.Config) -> string [expr] { + { } root_cfg.key +} +function user.RootThrowClass(x: int) -> string [expr] { + { } match (x) { 0 => throw user.Error { code: 500, message: "root error" }, _ => "ok" } +} +function user.RootThrowEnum(x: int) -> string [expr] { + { } match (x) { 0 => throw Status.Failed, _ => "ok" } +} +function user.RootUsesAuthConfig(cfg: root.auth.Config) -> string [expr] { + { } cfg.provider +} +function user.RootUsesAuthError(e: root.auth.Error) -> string [expr] { + { } e.realm +} +function user.RootUsesLlmConfig(cfg: root.llm.Config) -> string [expr] { + { } cfg.model +} +function user.RootUsesLlmError(e: root.llm.Error) -> string [expr] { + { } e.reason +} +function user.RootUsesLlmStatus() -> root.llm.Status [expr] { + { } root.llm.Status.Ready +} +function user.RootUsesNestedClient(c: root.llm.openai.Client) -> string [expr] { + { } c.api_key +} +class user.auth.Config { + provider: string + secret: string +} +class user.auth.Error { + realm: string + expired: bool +} +class user.auth.Token { + value: string + role: user.auth.Role +} +enum user.auth.Role {Admin, User, Guest} +type user.auth.TokenAlias = user.auth.Token +function user.auth.AuthAliasParam(t: user.auth.TokenAlias) -> string [expr] { + { } t.value +} +function user.auth.AuthConstruct(provider: string) -> user.auth.Config [expr] { + { } user.auth.Config { provider: provider, secret: "s3cret" } +} +function user.auth.AuthEnumMatch(r: user.auth.Role) -> string [expr] { + { } match (r) { user.auth.Role.Admin => "admin", user.auth.Role.User => "user", user.auth.Role.Guest => "guest" } +} +function user.auth.AuthEnumReturn() -> user.auth.Role [expr] { + { } Role.Admin +} +function user.auth.AuthIdentity(cfg: user.auth.Config) -> user.auth.Config [expr] { + { } cfg +} +function user.auth.AuthMakeToken(v: string) -> user.auth.Token [expr] { + { } user.auth.Token { value: v, role: Role.User } +} +function user.auth.AuthMatchesLlmStatus(s: root.llm.Status) -> string [expr] { + { } match (s) { root.llm.Status.Ready => "ready", root.llm.Status.Generating => "generating", root.llm.Status.Done => "done" } +} +function user.auth.AuthMatchesRootStatus(s: root.Status) -> string [expr] { + { } match (s) { root.Status.Ok => "ok", root.Status.Failed => "failed", root.Status.Pending => "pending" } +} +function user.auth.AuthMixedConfigs(auth_cfg: user.auth.Config, root_cfg: root.Config, llm_cfg: root.llm.Config) -> string [expr] { + { } auth_cfg.provider +} +function user.auth.AuthMixedErrors(auth_err: user.auth.Error, root_err: root.Error, llm_err: root.llm.Error) -> string [expr] { + { } auth_err.realm +} +function user.auth.AuthThrowClass(x: int) -> string [expr] { + { } match (x) { 0 => throw user.auth.Error { realm: "auth failed", expired: true }, _ => "ok" } +} +function user.auth.AuthThrowEnum(x: int) -> string [expr] { + { } match (x) { 0 => throw Role.Guest, _ => "ok" } +} +function user.auth.AuthThrowsRootError(x: int) -> string [expr] { + { } match (x) { 0 => throw user.auth.Error { code: 403, message: "forbidden" }, _ => "ok" } +} +function user.auth.AuthUsesLlmConfig(cfg: root.llm.Config) -> string [expr] { + { } cfg.model +} +function user.auth.AuthUsesLlmResponse(r: root.llm.Response) -> string [expr] { + { } r.text +} +function user.auth.AuthUsesLlmStatus() -> root.llm.Status [expr] { + { } root.llm.Status.Ready +} +function user.auth.AuthUsesNestedClient(c: root.llm.openai.Client) -> string [expr] { + { } c.api_key +} +function user.auth.AuthUsesRootConfig(cfg: root.Config) -> string [expr] { + { } cfg.key +} +function user.auth.AuthUsesRootStatus() -> root.Status [expr] { + { } root.Status.Pending +} +class user.llm.Config { + model: string + temperature: float +} +class user.llm.Error { + reason: string + retryable: bool +} +class user.llm.LlmWithCrossNsFields { + own_config: user.llm.Config + own_response: user.llm.Response + root_config: root.Config + root_error: root.Error + auth_config: root.auth.Config + nested_client: root.llm.openai.Client + own_status: user.llm.Status + own_alias: user.llm.ConfigAlias + root_alias: root.ConfigAlias +} +class user.llm.LlmWithRootAlias { + root_alias: root.ConfigAlias + own_alias: user.llm.ResponseAlias +} +class user.llm.Response { + text: string + tokens: int +} +enum user.llm.Model {GPT4, Claude} +enum user.llm.Status {Ready, Generating, Done} +type user.llm.ConfigAlias = user.llm.Config +type user.llm.ResponseAlias = user.llm.Response +function user.llm.LlmAliasParam(cfg: user.llm.ConfigAlias) -> string [expr] { + { } cfg.model +} +function user.llm.LlmConstruct(model: string) -> user.llm.Config [expr] { + { } user.llm.Config { model: model, temperature: 0.7 } +} +function user.llm.LlmEnumMatch(s: user.llm.Status) -> string [expr] { + { } match (s) { user.llm.Status.Ready => "ready", user.llm.Status.Generating => "generating", user.llm.Status.Done => "done" } +} +function user.llm.LlmEnumReturn() -> user.llm.Status [expr] { + { } Status.Ready +} +function user.llm.LlmIdentity(cfg: user.llm.Config) -> user.llm.Config [expr] { + { } cfg +} +function user.llm.LlmMatchesRootStatus(s: root.Status) -> string [expr] { + { } match (s) { root.Status.Ok => "ok", root.Status.Failed => "failed", root.Status.Pending => "pending" } +} +function user.llm.LlmMixedConfigs(llm_cfg: user.llm.Config, root_cfg: root.Config, auth_cfg: root.auth.Config) -> string [expr] { + { } llm_cfg.model +} +function user.llm.LlmResponseConstruct(text: string) -> user.llm.Response [expr] { + { } user.llm.Response { text: text, tokens: 42 } +} +function user.llm.LlmThrowClass(x: int) -> string [expr] { + { } match (x) { 0 => throw user.llm.Error { reason: "llm failed", retryable: true }, _ => "ok" } +} +function user.llm.LlmThrowEnum(x: int) -> string [expr] { + { } match (x) { 0 => throw Status.Done, _ => "ok" } +} +function user.llm.LlmThrowsRootEnum(x: int) -> string [expr] { + { } match (x) { 0 => throw root.Status.Failed, _ => "ok" } +} +function user.llm.LlmThrowsRootError(x: int) -> string [expr] { + { } match (x) { 0 => throw user.llm.Error { code: 404, message: "not found" }, _ => "ok" } +} +function user.llm.LlmUsesAuthConfig(cfg: root.auth.Config) -> string [expr] { + { } cfg.provider +} +function user.llm.LlmUsesAuthError(e: root.auth.Error) -> string [expr] { + { } e.realm +} +function user.llm.LlmUsesAuthRole() -> root.auth.Role [expr] { + { } root.auth.Role.Admin +} +function user.llm.LlmUsesNestedClient(c: root.llm.openai.Client) -> string [expr] { + { } c.api_key +} +function user.llm.LlmUsesRootAlias(cfg: root.ConfigAlias) -> string [expr] { + { } cfg.key +} +function user.llm.LlmUsesRootConfig(cfg: root.Config) -> string [expr] { + { } cfg.key +} +function user.llm.LlmUsesRootError(e: root.Error) -> string [expr] { + { } e.message +} +function user.llm.LlmUsesRootStatus() -> root.Status [expr] { + { } root.Status.Ok +} +class user.llm.openai.Client { + api_key: string + org_id: string +} +class user.llm.openai.Error { + status_code: int + body: string +} +enum user.llm.openai.Model {GPT4o, GPT4oMini, O3} +function user.llm.openai.OpenAIConstruct(key: string) -> user.llm.openai.Client [expr] { + { } user.llm.openai.Client { api_key: key, org_id: "org-123" } +} +function user.llm.openai.OpenAIEnumMatch(m: user.llm.openai.Model) -> string [expr] { + { } match (m) { user.llm.openai.Model.GPT4o => "gpt4o", user.llm.openai.Model.GPT4oMini => "gpt4o-mini", user.llm.openai.Model.O3 => "o3" } +} +function user.llm.openai.OpenAIEnumReturn() -> user.llm.openai.Model [expr] { + { } Model.GPT4o +} +function user.llm.openai.OpenAIIdentity(c: user.llm.openai.Client) -> user.llm.openai.Client [expr] { + { } c +} +function user.llm.openai.OpenAIMatchesAuthRole(r: root.auth.Role) -> string [expr] { + { } match (r) { root.auth.Role.Admin => "admin", root.auth.Role.User => "user", root.auth.Role.Guest => "guest" } +} +function user.llm.openai.OpenAIMatchesLlmStatus(s: root.llm.Status) -> string [expr] { + { } match (s) { root.llm.Status.Ready => "ready", root.llm.Status.Generating => "generating", root.llm.Status.Done => "done" } +} +function user.llm.openai.OpenAIMatchesRootStatus(s: root.Status) -> string [expr] { + { } match (s) { root.Status.Ok => "ok", root.Status.Failed => "failed", root.Status.Pending => "pending" } +} +function user.llm.openai.OpenAIMixedErrors(openai_err: user.llm.openai.Error, root_err: root.Error, llm_err: root.llm.Error, auth_err: root.auth.Error) -> string [expr] { + { } openai_err.body +} +function user.llm.openai.OpenAIMixedModels(openai_model: user.llm.openai.Model, llm_model: root.llm.Model) -> string [expr] { + { } match (openai_model) { user.llm.openai.Model.GPT4o => "gpt4o", user.llm.openai.Model.GPT4oMini => "mini", user.llm.openai.Model.O3 => "o3" } +} +function user.llm.openai.OpenAIThrowClass(x: int) -> string [expr] { + { } match (x) { 0 => throw user.llm.openai.Error { status_code: 429, body: "rate limited" }, _ => "ok" } +} +function user.llm.openai.OpenAIThrowEnum(x: int) -> string [expr] { + { } match (x) { 0 => throw Model.O3, _ => "ok" } +} +function user.llm.openai.OpenAIUsesAuthConfig(cfg: root.auth.Config) -> string [expr] { + { } cfg.provider +} +function user.llm.openai.OpenAIUsesAuthRole() -> root.auth.Role [expr] { + { } root.auth.Role.User +} +function user.llm.openai.OpenAIUsesLlmConfig(cfg: root.llm.Config) -> string [expr] { + { } cfg.model +} +function user.llm.openai.OpenAIUsesLlmResponse(r: root.llm.Response) -> string [expr] { + { } r.text +} +function user.llm.openai.OpenAIUsesLlmStatus() -> root.llm.Status [expr] { + { } root.llm.Status.Generating +} +function user.llm.openai.OpenAIUsesRootConfig(cfg: root.Config) -> string [expr] { + { } cfg.key +} +function user.llm.openai.OpenAIUsesRootStatus() -> root.Status [expr] { + { } root.Status.Ok +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_5_mir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_5_mir.snap new file mode 100644 index 0000000000..f9481f8bce --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_5_mir.snap @@ -0,0 +1,1559 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== MIR2 === +fn user.RootAliasParam(cfg: Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootConstruct(key: string) -> Config { + // Locals: + let _0: Config // _0 // return + let _1: string // key // param + + bb0: { + _0 = Config { copy _1, const "prod" }; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootEnumMatch(s: Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: Status // s // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.Status.Ok; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.Status.Failed; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.Status.Pending; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "pending"; + goto -> bb7; + } + + bb5: { + _0 = const "failed"; + goto -> bb7; + } + + bb6: { + _0 = const "ok"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.RootEnumReturn() -> Status { + // Locals: + let _0: Status // _0 // return + + bb0: { + _0 = const user.Status.Ok; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootIdentity(cfg: Config) -> Config { + // Locals: + let _0: Config // _0 // return + let _1: Config // cfg // param + + bb0: { + _0 = copy _1; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootMixedConfigs(root_cfg: Config, llm_cfg: llm.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: Config // root_cfg // param + let _2: llm.Config // llm_cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootThrowClass(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + let _2: Error + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + _2 = Error { const 500_i64, const "root error" }; + throw copy _2; + } +} + +fn user.RootThrowEnum(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + throw const user.Status.Failed; + } +} + +fn user.RootUsesAuthConfig(cfg: auth.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootUsesAuthError(e: auth.Error) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Error // e // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootUsesLlmConfig(cfg: llm.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootUsesLlmError(e: llm.Error) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Error // e // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootUsesLlmStatus() -> llm.Status { + // Locals: + let _0: llm.Status // _0 // return + + bb0: { + _0 = const user.llm.Status.Ready; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.RootUsesNestedClient(c: llm.openai.Client) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.openai.Client // c // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthAliasParam(t: auth.Token) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Token // t // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthConstruct(provider: string) -> auth.Config { + // Locals: + let _0: auth.Config // _0 // return + let _1: string // provider // param + + bb0: { + _0 = Config { copy _1, const "s3cret" }; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthEnumMatch(r: auth.Role) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Role // r // param + let _2: int + + bb0: { + _2 = discriminant(_1); + switch copy _2 [Role.Admin: bb4, Role.User: bb3, Role.Guest: bb2, otherwise: bb1] (exhaustive); + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const "guest"; + goto -> bb5; + } + + bb3: { + _0 = const "user"; + goto -> bb5; + } + + bb4: { + _0 = const "admin"; + goto -> bb5; + } + + bb5: { + goto -> bb6; + } + + bb6: { + return; + } +} + +fn user.auth.AuthEnumReturn() -> auth.Role { + // Locals: + let _0: auth.Role // _0 // return + + bb0: { + _0 = const user.auth.Role.Admin; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthIdentity(cfg: auth.Config) -> auth.Config { + // Locals: + let _0: auth.Config // _0 // return + let _1: auth.Config // cfg // param + + bb0: { + _0 = copy _1; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthMakeToken(v: string) -> auth.Token { + // Locals: + let _0: auth.Token // _0 // return + let _1: string // v // param + + bb0: { + _0 = Token { copy _1, const user.auth.Role.User }; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthMatchesLlmStatus(s: llm.Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Status // s // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.auth.root.llm.Status.Ready; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.auth.root.llm.Status.Generating; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.auth.root.llm.Status.Done; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "done"; + goto -> bb7; + } + + bb5: { + _0 = const "generating"; + goto -> bb7; + } + + bb6: { + _0 = const "ready"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.auth.AuthMatchesRootStatus(s: Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: Status // s // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.auth.root.Status.Ok; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.auth.root.Status.Failed; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.auth.root.Status.Pending; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "pending"; + goto -> bb7; + } + + bb5: { + _0 = const "failed"; + goto -> bb7; + } + + bb6: { + _0 = const "ok"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.auth.AuthMixedConfigs(auth_cfg: auth.Config, root_cfg: Config, llm_cfg: llm.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Config // auth_cfg // param + let _2: Config // root_cfg // param + let _3: llm.Config // llm_cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthMixedErrors(auth_err: auth.Error, root_err: Error, llm_err: llm.Error) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Error // auth_err // param + let _2: Error // root_err // param + let _3: llm.Error // llm_err // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthThrowClass(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + let _2: auth.Error + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + _2 = Error { const "auth failed", const true }; + throw copy _2; + } +} + +fn user.auth.AuthThrowEnum(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + throw const user.auth.Role.Guest; + } +} + +fn user.auth.AuthThrowsRootError(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + let _2: auth.Error + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + _2 = Error { const 403_i64, const "forbidden" }; + throw copy _2; + } +} + +fn user.auth.AuthUsesLlmConfig(cfg: llm.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthUsesLlmResponse(r: llm.Response) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Response // r // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthUsesLlmStatus() -> llm.Status { + // Locals: + let _0: llm.Status // _0 // return + + bb0: { + _0 = const user.llm.Status.Ready; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthUsesNestedClient(c: llm.openai.Client) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.openai.Client // c // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthUsesRootConfig(cfg: Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.auth.AuthUsesRootStatus() -> Status { + // Locals: + let _0: Status // _0 // return + + bb0: { + _0 = const user.Status.Pending; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmAliasParam(cfg: llm.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmConstruct(model: string) -> llm.Config { + // Locals: + let _0: llm.Config // _0 // return + let _1: string // model // param + + bb0: { + _0 = Config { copy _1, const 0.7_f64 }; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmEnumMatch(s: llm.Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Status // s // param + let _2: int + + bb0: { + _2 = discriminant(_1); + switch copy _2 [Status.Ready: bb4, Status.Generating: bb3, Status.Done: bb2, otherwise: bb1] (exhaustive); + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const "done"; + goto -> bb5; + } + + bb3: { + _0 = const "generating"; + goto -> bb5; + } + + bb4: { + _0 = const "ready"; + goto -> bb5; + } + + bb5: { + goto -> bb6; + } + + bb6: { + return; + } +} + +fn user.llm.LlmEnumReturn() -> llm.Status { + // Locals: + let _0: llm.Status // _0 // return + + bb0: { + _0 = const user.llm.Status.Ready; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmIdentity(cfg: llm.Config) -> llm.Config { + // Locals: + let _0: llm.Config // _0 // return + let _1: llm.Config // cfg // param + + bb0: { + _0 = copy _1; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmMatchesRootStatus(s: Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: Status // s // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.llm.root.Status.Ok; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.llm.root.Status.Failed; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.llm.root.Status.Pending; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "pending"; + goto -> bb7; + } + + bb5: { + _0 = const "failed"; + goto -> bb7; + } + + bb6: { + _0 = const "ok"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.llm.LlmMixedConfigs(llm_cfg: llm.Config, root_cfg: Config, auth_cfg: auth.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Config // llm_cfg // param + let _2: Config // root_cfg // param + let _3: auth.Config // auth_cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmResponseConstruct(text: string) -> llm.Response { + // Locals: + let _0: llm.Response // _0 // return + let _1: string // text // param + + bb0: { + _0 = Response { copy _1, const 42_i64 }; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmThrowClass(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + let _2: llm.Error + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + _2 = Error { const "llm failed", const true }; + throw copy _2; + } +} + +fn user.llm.LlmThrowEnum(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + throw const user.llm.Status.Done; + } +} + +fn user.llm.LlmThrowsRootEnum(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + throw const user.Status.Failed; + } +} + +fn user.llm.LlmThrowsRootError(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + let _2: llm.Error + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + _2 = Error { const 404_i64, const "not found" }; + throw copy _2; + } +} + +fn user.llm.LlmUsesAuthConfig(cfg: auth.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesAuthError(e: auth.Error) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Error // e // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesAuthRole() -> auth.Role { + // Locals: + let _0: auth.Role // _0 // return + + bb0: { + _0 = const user.auth.Role.Admin; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesNestedClient(c: llm.openai.Client) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.openai.Client // c // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesRootAlias(cfg: Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesRootConfig(cfg: Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesRootError(e: Error) -> string { + // Locals: + let _0: string // _0 // return + let _1: Error // e // param + + bb0: { + _0 = copy _1.1; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.LlmUsesRootStatus() -> Status { + // Locals: + let _0: Status // _0 // return + + bb0: { + _0 = const user.Status.Ok; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIConstruct(key: string) -> llm.openai.Client { + // Locals: + let _0: llm.openai.Client // _0 // return + let _1: string // key // param + + bb0: { + _0 = Client { copy _1, const "org-123" }; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIEnumMatch(m: llm.openai.Model) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.openai.Model // m // param + let _2: int + + bb0: { + _2 = discriminant(_1); + switch copy _2 [Model.GPT4o: bb4, Model.GPT4oMini: bb3, Model.O3: bb2, otherwise: bb1] (exhaustive); + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const "o3"; + goto -> bb5; + } + + bb3: { + _0 = const "gpt4o-mini"; + goto -> bb5; + } + + bb4: { + _0 = const "gpt4o"; + goto -> bb5; + } + + bb5: { + goto -> bb6; + } + + bb6: { + return; + } +} + +fn user.llm.openai.OpenAIEnumReturn() -> llm.openai.Model { + // Locals: + let _0: llm.openai.Model // _0 // return + + bb0: { + _0 = const user.llm.openai.Model.GPT4o; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIIdentity(c: llm.openai.Client) -> llm.openai.Client { + // Locals: + let _0: llm.openai.Client // _0 // return + let _1: llm.openai.Client // c // param + + bb0: { + _0 = copy _1; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIMatchesAuthRole(r: auth.Role) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Role // r // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.llm.openai.root.auth.Role.Admin; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.llm.openai.root.auth.Role.User; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.llm.openai.root.auth.Role.Guest; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "guest"; + goto -> bb7; + } + + bb5: { + _0 = const "user"; + goto -> bb7; + } + + bb6: { + _0 = const "admin"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.llm.openai.OpenAIMatchesLlmStatus(s: llm.Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Status // s // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.llm.openai.root.llm.Status.Ready; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.llm.openai.root.llm.Status.Generating; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.llm.openai.root.llm.Status.Done; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "done"; + goto -> bb7; + } + + bb5: { + _0 = const "generating"; + goto -> bb7; + } + + bb6: { + _0 = const "ready"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.llm.openai.OpenAIMatchesRootStatus(s: Status) -> string { + // Locals: + let _0: string // _0 // return + let _1: Status // s // param + let _2: bool + let _3: bool + let _4: bool + + bb0: { + _2 = copy _1 == const user.llm.openai.root.Status.Ok; + branch copy _2 -> [bb6, bb1]; + } + + bb1: { + _3 = copy _1 == const user.llm.openai.root.Status.Failed; + branch copy _3 -> [bb5, bb2]; + } + + bb2: { + _4 = copy _1 == const user.llm.openai.root.Status.Pending; + branch copy _4 -> [bb4, bb3]; + } + + bb3: { + goto -> bb7; + } + + bb4: { + _0 = const "pending"; + goto -> bb7; + } + + bb5: { + _0 = const "failed"; + goto -> bb7; + } + + bb6: { + _0 = const "ok"; + goto -> bb7; + } + + bb7: { + goto -> bb8; + } + + bb8: { + return; + } +} + +fn user.llm.openai.OpenAIMixedErrors(openai_err: llm.openai.Error, root_err: Error, llm_err: llm.Error, auth_err: auth.Error) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.openai.Error // openai_err // param + let _2: Error // root_err // param + let _3: llm.Error // llm_err // param + let _4: auth.Error // auth_err // param + + bb0: { + _0 = copy _1.1; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIMixedModels(openai_model: llm.openai.Model, llm_model: llm.Model) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.openai.Model // openai_model // param + let _2: llm.Model // llm_model // param + let _3: int + + bb0: { + _3 = discriminant(_1); + switch copy _3 [Model.GPT4o: bb4, Model.GPT4oMini: bb3, Model.O3: bb2, otherwise: bb1] (exhaustive); + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const "o3"; + goto -> bb5; + } + + bb3: { + _0 = const "mini"; + goto -> bb5; + } + + bb4: { + _0 = const "gpt4o"; + goto -> bb5; + } + + bb5: { + goto -> bb6; + } + + bb6: { + return; + } +} + +fn user.llm.openai.OpenAIThrowClass(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + let _2: llm.openai.Error + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + _2 = Error { const 429_i64, const "rate limited" }; + throw copy _2; + } +} + +fn user.llm.openai.OpenAIThrowEnum(x: int) -> string { + // Locals: + let _0: string // _0 // return + let _1: int // x // param + + bb0: { + switch copy _1 [0: bb4, otherwise: bb1]; + } + + bb1: { + _0 = const "ok"; + goto -> bb2; + } + + bb2: { + goto -> bb3; + } + + bb3: { + return; + } + + bb4: { + throw const user.llm.openai.Model.O3; + } +} + +fn user.llm.openai.OpenAIUsesAuthConfig(cfg: auth.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: auth.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIUsesAuthRole() -> auth.Role { + // Locals: + let _0: auth.Role // _0 // return + + bb0: { + _0 = const user.auth.Role.User; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIUsesLlmConfig(cfg: llm.Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIUsesLlmResponse(r: llm.Response) -> string { + // Locals: + let _0: string // _0 // return + let _1: llm.Response // r // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIUsesLlmStatus() -> llm.Status { + // Locals: + let _0: llm.Status // _0 // return + + bb0: { + _0 = const user.llm.Status.Generating; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIUsesRootConfig(cfg: Config) -> string { + // Locals: + let _0: string // _0 // return + let _1: Config // cfg // param + + bb0: { + _0 = copy _1.0; + goto -> bb1; + } + + bb1: { + return; + } +} + +fn user.llm.openai.OpenAIUsesRootStatus() -> Status { + // Locals: + let _0: Status // _0 // return + + bb0: { + _0 = const user.Status.Ok; + goto -> bb1; + } + + bb1: { + return; + } +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_tir.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_tir.snap new file mode 100644 index 0000000000..9c45ee294b --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__04_tir.snap @@ -0,0 +1,618 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== TIR2 === +class user.Config { + key: string + env: string +} +class user.Error { + code: int + message: string +} +enum user.Status +type user.ConfigAlias = user.Config +function user.RootIdentity(cfg: user.Config) -> user.Config throws never { + { : user.Config + cfg : user.Config + } +} +function user.RootConstruct(key: string) -> user.Config throws never { + { : user.Config + Config { key: key, env: "prod" } : user.Config + } +} +function user.RootEnumReturn() -> user.Status throws never { + { : user.Status.Ok + Status.Ok : user.Status.Ok + } +} +function user.RootEnumMatch(s: user.Status) -> string throws never { + { : "ok" | "failed" | "pending" + match (s : user.Status) : "ok" | "failed" | "pending" + Status.Ok => + "ok" : "ok" + Status.Failed => + "failed" : "failed" + Status.Pending => + "pending" : "pending" + } +} +function user.RootAliasParam(cfg: user.ConfigAlias) -> string throws never { + { : string + cfg.key : string + } +} +function user.RootThrowClass(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Error { code: 500, message: "root error" } : never + _ => + "ok" : "ok" + } +} +function user.RootThrowEnum(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Status.Failed : never + _ => + "ok" : "ok" + } +} +function user.RootUsesLlmConfig(cfg: user.llm.Config) -> string throws never { + { : string + cfg.model : string + } +} +function user.RootUsesLlmError(e: user.llm.Error) -> string throws never { + { : string + e.reason : string + } +} +function user.RootUsesLlmStatus() -> user.llm.Status throws never { + { : user.llm.Status.Ready + root.llm.Status.Ready : user.llm.Status.Ready + } +} +function user.RootUsesAuthConfig(cfg: user.auth.Config) -> string throws never { + { : string + cfg.provider : string + } +} +function user.RootUsesAuthError(e: user.auth.Error) -> string throws never { + { : string + e.realm : string + } +} +function user.RootUsesNestedClient(c: user.llm.openai.Client) -> string throws never { + { : string + c.api_key : string + } +} +function user.RootMixedConfigs(root_cfg: user.Config, llm_cfg: user.llm.Config) -> string throws never { + { : string + root_cfg.key : string + } +} +class user.RootWithCrossNsFields { + own_config: user.Config + llm_config: user.llm.Config + auth_config: user.auth.Config + llm_response: user.llm.Response + nested_client: user.llm.openai.Client + own_status: user.Status + own_alias: user.ConfigAlias +} +class user.RootWithCrossNsAlias { + llm_alias: user.llm.ResponseAlias + own_alias: user.ConfigAlias +} +class user.Config$stream { + key: null | string + env: null | string +} +class user.Error$stream { + code: null | int + message: null | string +} +type user.ConfigAlias$stream = user.Config$stream +class user.RootWithCrossNsFields$stream { + own_config: null | user.Config$stream + llm_config: null | user.llm.Config$stream + auth_config: null | user.auth.Config$stream + llm_response: null | user.llm.Response$stream + nested_client: null | user.llm.openai.Client$stream + own_status: null | user.Status + own_alias: null | user.Config$stream +} +class user.RootWithCrossNsAlias$stream { + llm_alias: null | user.llm.Response$stream + own_alias: null | user.Config$stream +} +class user.auth.Config { + provider: string + secret: string +} +class user.auth.Error { + realm: string + expired: bool +} +enum user.auth.Role +class user.auth.Token { + value: string + role: user.auth.Role +} +type user.auth.TokenAlias = user.auth.Token +function user.auth.AuthIdentity(cfg: user.auth.Config) -> user.auth.Config throws never { + { : user.auth.Config + cfg : user.auth.Config + } +} +function user.auth.AuthConstruct(provider: string) -> user.auth.Config throws never { + { : user.auth.Config + Config { provider: provider, secret: "s3cret" } : user.auth.Config + } +} +function user.auth.AuthEnumReturn() -> user.auth.Role throws never { + { : user.auth.Role.Admin + Role.Admin : user.auth.Role.Admin + } +} +function user.auth.AuthEnumMatch(r: user.auth.Role) -> string throws never { + { : "admin" | "user" | "guest" + match (r : user.auth.Role) : "admin" | "user" | "guest" + Role.Admin => + "admin" : "admin" + Role.User => + "user" : "user" + Role.Guest => + "guest" : "guest" + } +} +function user.auth.AuthAliasParam(t: user.auth.TokenAlias) -> string throws never { + { : string + t.value : string + } +} +function user.auth.AuthThrowClass(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Error { realm: "auth failed", expired: true } : never + _ => + "ok" : "ok" + } +} +function user.auth.AuthThrowEnum(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Role.Guest : never + _ => + "ok" : "ok" + } +} +function user.auth.AuthMakeToken(v: string) -> user.auth.Token throws never { + { : user.auth.Token + Token { value: v, role: Role.User } : user.auth.Token + } +} +function user.auth.AuthUsesRootConfig(cfg: user.Config) -> string throws never { + { : string + cfg.key : string + } +} +function user.auth.AuthUsesRootStatus() -> user.Status throws never { + { : user.Status.Pending + root.Status.Pending : user.Status.Pending + } +} +function user.auth.AuthMatchesRootStatus(s: user.Status) -> string throws never { + { : "ok" | "failed" | "pending" + match (s : user.Status) : "ok" | "failed" | "pending" + root.Status.Ok => + "ok" : "ok" + root.Status.Failed => + "failed" : "failed" + root.Status.Pending => + "pending" : "pending" + } +} +function user.auth.AuthThrowsRootError(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Error { code: 403, message: "forbidden" } : never + _ => + "ok" : "ok" + } +} +function user.auth.AuthUsesLlmConfig(cfg: user.llm.Config) -> string throws never { + { : string + cfg.model : string + } +} +function user.auth.AuthUsesLlmResponse(r: user.llm.Response) -> string throws never { + { : string + r.text : string + } +} +function user.auth.AuthUsesLlmStatus() -> user.llm.Status throws never { + { : user.llm.Status.Ready + root.llm.Status.Ready : user.llm.Status.Ready + } +} +function user.auth.AuthMatchesLlmStatus(s: user.llm.Status) -> string throws never { + { : "ready" | "generating" | "done" + match (s : user.llm.Status) : "ready" | "generating" | "done" + root.llm.Status.Ready => + "ready" : "ready" + root.llm.Status.Generating => + "generating" : "generating" + root.llm.Status.Done => + "done" : "done" + } +} +function user.auth.AuthUsesNestedClient(c: user.llm.openai.Client) -> string throws never { + { : string + c.api_key : string + } +} +function user.auth.AuthMixedConfigs(auth_cfg: user.auth.Config, root_cfg: user.Config, llm_cfg: user.llm.Config) -> string throws never { + { : string + auth_cfg.provider : string + } +} +function user.auth.AuthMixedErrors(auth_err: user.auth.Error, root_err: user.Error, llm_err: user.llm.Error) -> string throws never { + { : string + auth_err.realm : string + } +} +class user.auth.Config$stream { + provider: null | string + secret: null | string +} +class user.auth.Error$stream { + realm: null | string + expired: null | bool +} +class user.auth.Token$stream { + value: null | string + role: null | user.auth.Role +} +type user.auth.TokenAlias$stream = user.auth.Token$stream +class user.llm.Config { + model: string + temperature: float +} +class user.llm.Error { + reason: string + retryable: bool +} +enum user.llm.Status +enum user.llm.Model +class user.llm.Response { + text: string + tokens: int +} +type user.llm.ConfigAlias = user.llm.Config +type user.llm.ResponseAlias = user.llm.Response +function user.llm.LlmIdentity(cfg: user.llm.Config) -> user.llm.Config throws never { + { : user.llm.Config + cfg : user.llm.Config + } +} +function user.llm.LlmConstruct(model: string) -> user.llm.Config throws never { + { : user.llm.Config + Config { model: model, temperature: 0.7 } : user.llm.Config + } +} +function user.llm.LlmEnumReturn() -> user.llm.Status throws never { + { : user.llm.Status.Ready + Status.Ready : user.llm.Status.Ready + } +} +function user.llm.LlmEnumMatch(s: user.llm.Status) -> string throws never { + { : "ready" | "generating" | "done" + match (s : user.llm.Status) : "ready" | "generating" | "done" + Status.Ready => + "ready" : "ready" + Status.Generating => + "generating" : "generating" + Status.Done => + "done" : "done" + } +} +function user.llm.LlmAliasParam(cfg: user.llm.ConfigAlias) -> string throws never { + { : string + cfg.model : string + } +} +function user.llm.LlmThrowClass(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Error { reason: "llm failed", retryable: true } : never + _ => + "ok" : "ok" + } +} +function user.llm.LlmThrowEnum(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Status.Done : never + _ => + "ok" : "ok" + } +} +function user.llm.LlmResponseConstruct(text: string) -> user.llm.Response throws never { + { : user.llm.Response + Response { text: text, tokens: 42 } : user.llm.Response + } +} +function user.llm.LlmUsesRootConfig(cfg: user.Config) -> string throws never { + { : string + cfg.key : string + } +} +function user.llm.LlmUsesRootError(e: user.Error) -> string throws never { + { : string + e.message : string + } +} +function user.llm.LlmUsesRootStatus() -> user.Status throws never { + { : user.Status.Ok + root.Status.Ok : user.Status.Ok + } +} +function user.llm.LlmMatchesRootStatus(s: user.Status) -> string throws never { + { : "ok" | "failed" | "pending" + match (s : user.Status) : "ok" | "failed" | "pending" + root.Status.Ok => + "ok" : "ok" + root.Status.Failed => + "failed" : "failed" + root.Status.Pending => + "pending" : "pending" + } +} +function user.llm.LlmUsesRootAlias(cfg: user.ConfigAlias) -> string throws never { + { : string + cfg.key : string + } +} +function user.llm.LlmThrowsRootError(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Error { code: 404, message: "not found" } : never + _ => + "ok" : "ok" + } +} +function user.llm.LlmThrowsRootEnum(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw root.Status.Failed : never + _ => + "ok" : "ok" + } +} +function user.llm.LlmUsesAuthConfig(cfg: user.auth.Config) -> string throws never { + { : string + cfg.provider : string + } +} +function user.llm.LlmUsesAuthError(e: user.auth.Error) -> string throws never { + { : string + e.realm : string + } +} +function user.llm.LlmUsesAuthRole() -> user.auth.Role throws never { + { : user.auth.Role.Admin + root.auth.Role.Admin : user.auth.Role.Admin + } +} +function user.llm.LlmUsesNestedClient(c: user.llm.openai.Client) -> string throws never { + { : string + c.api_key : string + } +} +function user.llm.LlmMixedConfigs(llm_cfg: user.llm.Config, root_cfg: user.Config, auth_cfg: user.auth.Config) -> string throws never { + { : string + llm_cfg.model : string + } +} +class user.llm.LlmWithCrossNsFields { + own_config: user.llm.Config + own_response: user.llm.Response + root_config: user.Config + root_error: user.Error + auth_config: user.auth.Config + nested_client: user.llm.openai.Client + own_status: user.llm.Status + own_alias: user.llm.ConfigAlias + root_alias: user.ConfigAlias +} +class user.llm.LlmWithRootAlias { + root_alias: user.ConfigAlias + own_alias: user.llm.ResponseAlias +} +class user.llm.Config$stream { + model: null | string + temperature: null | float +} +class user.llm.Error$stream { + reason: null | string + retryable: null | bool +} +class user.llm.Response$stream { + text: null | string + tokens: null | int +} +type user.llm.ConfigAlias$stream = user.llm.Config$stream +type user.llm.ResponseAlias$stream = user.llm.Response$stream +class user.llm.LlmWithCrossNsFields$stream { + own_config: null | user.llm.Config$stream + own_response: null | user.llm.Response$stream + root_config: null | user.Config$stream + root_error: null | user.Error$stream + auth_config: null | user.auth.Config$stream + nested_client: null | user.llm.openai.Client$stream + own_status: null | user.llm.Status + own_alias: null | user.Config$stream + root_alias: null | user.Config$stream +} +class user.llm.LlmWithRootAlias$stream { + root_alias: null | user.Config$stream + own_alias: null | user.llm.Response$stream +} +class user.llm.openai.Client { + api_key: string + org_id: string +} +class user.llm.openai.Error { + status_code: int + body: string +} +enum user.llm.openai.Model +function user.llm.openai.OpenAIIdentity(c: user.llm.openai.Client) -> user.llm.openai.Client throws never { + { : user.llm.openai.Client + c : user.llm.openai.Client + } +} +function user.llm.openai.OpenAIConstruct(key: string) -> user.llm.openai.Client throws never { + { : user.llm.openai.Client + Client { api_key: key, org_id: "org-123" } : user.llm.openai.Client + } +} +function user.llm.openai.OpenAIEnumReturn() -> user.llm.openai.Model throws never { + { : user.llm.openai.Model.GPT4o + Model.GPT4o : user.llm.openai.Model.GPT4o + } +} +function user.llm.openai.OpenAIEnumMatch(m: user.llm.openai.Model) -> string throws never { + { : "gpt4o" | "gpt4o-mini" | "o3" + match (m : user.llm.openai.Model) : "gpt4o" | "gpt4o-mini" | "o3" + Model.GPT4o => + "gpt4o" : "gpt4o" + Model.GPT4oMini => + "gpt4o-mini" : "gpt4o-mini" + Model.O3 => + "o3" : "o3" + } +} +function user.llm.openai.OpenAIThrowClass(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Error { status_code: 429, body: "rate limited" } : never + _ => + "ok" : "ok" + } +} +function user.llm.openai.OpenAIThrowEnum(x: int) -> string throws never { + { : "ok" + match (x : int) : "ok" + 0 => + throw Model.O3 : never + _ => + "ok" : "ok" + } +} +function user.llm.openai.OpenAIUsesRootConfig(cfg: user.Config) -> string throws never { + { : string + cfg.key : string + } +} +function user.llm.openai.OpenAIUsesRootStatus() -> user.Status throws never { + { : user.Status.Ok + root.Status.Ok : user.Status.Ok + } +} +function user.llm.openai.OpenAIMatchesRootStatus(s: user.Status) -> string throws never { + { : "ok" | "failed" | "pending" + match (s : user.Status) : "ok" | "failed" | "pending" + root.Status.Ok => + "ok" : "ok" + root.Status.Failed => + "failed" : "failed" + root.Status.Pending => + "pending" : "pending" + } +} +function user.llm.openai.OpenAIUsesLlmConfig(cfg: user.llm.Config) -> string throws never { + { : string + cfg.model : string + } +} +function user.llm.openai.OpenAIUsesLlmResponse(r: user.llm.Response) -> string throws never { + { : string + r.text : string + } +} +function user.llm.openai.OpenAIUsesLlmStatus() -> user.llm.Status throws never { + { : user.llm.Status.Generating + root.llm.Status.Generating : user.llm.Status.Generating + } +} +function user.llm.openai.OpenAIMatchesLlmStatus(s: user.llm.Status) -> string throws never { + { : "ready" | "generating" | "done" + match (s : user.llm.Status) : "ready" | "generating" | "done" + root.llm.Status.Ready => + "ready" : "ready" + root.llm.Status.Generating => + "generating" : "generating" + root.llm.Status.Done => + "done" : "done" + } +} +function user.llm.openai.OpenAIUsesAuthConfig(cfg: user.auth.Config) -> string throws never { + { : string + cfg.provider : string + } +} +function user.llm.openai.OpenAIUsesAuthRole() -> user.auth.Role throws never { + { : user.auth.Role.User + root.auth.Role.User : user.auth.Role.User + } +} +function user.llm.openai.OpenAIMatchesAuthRole(r: user.auth.Role) -> string throws never { + { : "admin" | "user" | "guest" + match (r : user.auth.Role) : "admin" | "user" | "guest" + root.auth.Role.Admin => + "admin" : "admin" + root.auth.Role.User => + "user" : "user" + root.auth.Role.Guest => + "guest" : "guest" + } +} +function user.llm.openai.OpenAIMixedErrors(openai_err: user.llm.openai.Error, root_err: user.Error, llm_err: user.llm.Error, auth_err: user.auth.Error) -> string throws never { + { : string + openai_err.body : string + } +} +function user.llm.openai.OpenAIMixedModels(openai_model: user.llm.openai.Model, llm_model: user.llm.Model) -> string throws never { + { : "gpt4o" | "mini" | "o3" + match (openai_model : user.llm.openai.Model) : "gpt4o" | "mini" | "o3" + Model.GPT4o => + "gpt4o" : "gpt4o" + Model.GPT4oMini => + "mini" : "mini" + Model.O3 => + "o3" : "o3" + } +} +class user.llm.openai.Client$stream { + api_key: null | string + org_id: null | string +} +class user.llm.openai.Error$stream { + status_code: null | int + body: null | string +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__05_diagnostics.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__05_diagnostics.snap new file mode 100644 index 0000000000..40cf564409 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__05_diagnostics.snap @@ -0,0 +1,5 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +=== COMPILER2 DIAGNOSTICS === +No errors found. diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__06_codegen.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__06_codegen.snap new file mode 100644 index 0000000000..af8810e52d --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__06_codegen.snap @@ -0,0 +1,943 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +function user.RootAliasParam(cfg: Config) -> string { + load_var cfg + load_field .key + return +} + +function user.RootConstruct(key: string) -> Config { + alloc_instance Config + copy 0 + load_var key + store_field .key + copy 0 + load_const "prod" + store_field .env + return +} + +function user.RootEnumMatch(s: Status) -> string { + load_var s + load_const user.Status.Ok + alloc_variant user.Status + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var s + load_const user.Status.Failed + alloc_variant user.Status + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var s + load_const user.Status.Pending + alloc_variant user.Status + cmp_op == + pop_jump_if_false L4 + load_const "pending" + jump L4 + + L2: + load_const "failed" + jump L4 + + L3: + load_const "ok" + + L4: + return +} + +function user.RootEnumReturn() -> Status { + load_const user.Status.Ok + alloc_variant user.Status + return +} + +function user.RootIdentity(cfg: Config) -> Config { + load_var cfg + return +} + +function user.RootMixedConfigs(root_cfg: Config, llm_cfg: llm.Config) -> string { + load_var root_cfg + load_field .key + return +} + +function user.RootThrowClass(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + alloc_instance Error + copy 0 + load_const 500 + store_field .code + copy 0 + load_const "root error" + store_field .message + throw +} + +function user.RootThrowEnum(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + load_const user.Status.Failed + alloc_variant user.Status + throw +} + +function user.RootUsesAuthConfig(cfg: auth.Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.RootUsesAuthError(e: auth.Error) -> string { + load_var e + load_field .0 + return +} + +function user.RootUsesLlmConfig(cfg: llm.Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.RootUsesLlmError(e: llm.Error) -> string { + load_var e + load_field .0 + return +} + +function user.RootUsesLlmStatus() -> llm.Status { + load_const user.llm.Status.Ready + alloc_variant user.llm.Status + return +} + +function user.RootUsesNestedClient(c: llm.openai.Client) -> string { + load_var c + load_field .0 + return +} + +function user.auth.AuthAliasParam(t: void) -> string { + load_var t + load_field .0 + return +} + +function user.auth.AuthConstruct(provider: string) -> Config { + alloc_instance Config + copy 0 + load_var provider + store_field .key + copy 0 + load_const "s3cret" + store_field .env + return +} + +function user.auth.AuthEnumMatch(r: void) -> string { + load_var r + discriminant + copy 0 + load_const Role.Admin + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L3 + + L0: + copy 0 + load_const Role.User + cmp_op == + pop_jump_if_false L1 + pop 1 + jump L2 + + L1: + pop 1 + load_const "guest" + jump L4 + + L2: + load_const "user" + jump L4 + + L3: + load_const "admin" + + L4: + return +} + +function user.auth.AuthEnumReturn() -> void { + load_const user.auth.Role.Admin + alloc_variant user.auth.Role + return +} + +function user.auth.AuthIdentity(cfg: Config) -> Config { + load_var cfg + return +} + +function user.auth.AuthMakeToken(v: string) -> void { + alloc_instance Token + copy 0 + load_var v + store_field .value + copy 0 + load_const user.auth.Role.User + alloc_variant user.auth.Role + store_field .role + return +} + +function user.auth.AuthMatchesLlmStatus(s: llm.Status) -> string { + load_var s + load_const undefined_enum::user.auth.root.llm.Status.Ready + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var s + load_const undefined_enum::user.auth.root.llm.Status.Generating + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var s + load_const undefined_enum::user.auth.root.llm.Status.Done + cmp_op == + pop_jump_if_false L4 + load_const "done" + jump L4 + + L2: + load_const "generating" + jump L4 + + L3: + load_const "ready" + + L4: + return +} + +function user.auth.AuthMatchesRootStatus(s: Status) -> string { + load_var s + load_const undefined_enum::user.auth.root.Status.Ok + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var s + load_const undefined_enum::user.auth.root.Status.Failed + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var s + load_const undefined_enum::user.auth.root.Status.Pending + cmp_op == + pop_jump_if_false L4 + load_const "pending" + jump L4 + + L2: + load_const "failed" + jump L4 + + L3: + load_const "ok" + + L4: + return +} + +function user.auth.AuthMixedConfigs(auth_cfg: Config, root_cfg: Config, llm_cfg: llm.Config) -> string { + load_var auth_cfg + load_field .0 + return +} + +function user.auth.AuthMixedErrors(auth_err: Error, root_err: Error, llm_err: llm.Error) -> string { + load_var auth_err + load_field .0 + return +} + +function user.auth.AuthThrowClass(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + alloc_instance Error + copy 0 + load_const "auth failed" + store_field .code + copy 0 + load_const true + store_field .message + throw +} + +function user.auth.AuthThrowEnum(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + load_const user.auth.Role.Guest + alloc_variant user.auth.Role + throw +} + +function user.auth.AuthThrowsRootError(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + alloc_instance Error + copy 0 + load_const 403 + store_field .code + copy 0 + load_const "forbidden" + store_field .message + throw +} + +function user.auth.AuthUsesLlmConfig(cfg: llm.Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.auth.AuthUsesLlmResponse(r: llm.Response) -> string { + load_var r + load_field .0 + return +} + +function user.auth.AuthUsesLlmStatus() -> llm.Status { + load_const user.llm.Status.Ready + alloc_variant user.llm.Status + return +} + +function user.auth.AuthUsesNestedClient(c: llm.openai.Client) -> string { + load_var c + load_field .0 + return +} + +function user.auth.AuthUsesRootConfig(cfg: Config) -> string { + load_var cfg + load_field .key + return +} + +function user.auth.AuthUsesRootStatus() -> Status { + load_const user.Status.Pending + alloc_variant user.Status + return +} + +function user.llm.LlmAliasParam(cfg: Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.llm.LlmConstruct(model: string) -> Config { + alloc_instance Config + copy 0 + load_var model + store_field .key + copy 0 + load_const 0.7 + store_field .env + return +} + +function user.llm.LlmEnumMatch(s: Status) -> string { + load_var s + discriminant + copy 0 + load_const Status.Ready + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L3 + + L0: + copy 0 + load_const Status.Generating + cmp_op == + pop_jump_if_false L1 + pop 1 + jump L2 + + L1: + pop 1 + load_const "done" + jump L4 + + L2: + load_const "generating" + jump L4 + + L3: + load_const "ready" + + L4: + return +} + +function user.llm.LlmEnumReturn() -> Status { + load_const user.llm.Status.Ready + alloc_variant user.llm.Status + return +} + +function user.llm.LlmIdentity(cfg: Config) -> Config { + load_var cfg + return +} + +function user.llm.LlmMatchesRootStatus(s: Status) -> string { + load_var s + load_const undefined_enum::user.llm.root.Status.Ok + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var s + load_const undefined_enum::user.llm.root.Status.Failed + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var s + load_const undefined_enum::user.llm.root.Status.Pending + cmp_op == + pop_jump_if_false L4 + load_const "pending" + jump L4 + + L2: + load_const "failed" + jump L4 + + L3: + load_const "ok" + + L4: + return +} + +function user.llm.LlmMixedConfigs(llm_cfg: Config, root_cfg: Config, auth_cfg: auth.Config) -> string { + load_var llm_cfg + load_field .0 + return +} + +function user.llm.LlmResponseConstruct(text: string) -> void { + alloc_instance Response + copy 0 + load_var text + store_field .text + copy 0 + load_const 42 + store_field .tokens + return +} + +function user.llm.LlmThrowClass(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + alloc_instance Error + copy 0 + load_const "llm failed" + store_field .code + copy 0 + load_const true + store_field .message + throw +} + +function user.llm.LlmThrowEnum(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + load_const user.llm.Status.Done + alloc_variant user.llm.Status + throw +} + +function user.llm.LlmThrowsRootEnum(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + load_const user.Status.Failed + alloc_variant user.Status + throw +} + +function user.llm.LlmThrowsRootError(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + alloc_instance Error + copy 0 + load_const 404 + store_field .code + copy 0 + load_const "not found" + store_field .message + throw +} + +function user.llm.LlmUsesAuthConfig(cfg: auth.Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.llm.LlmUsesAuthError(e: auth.Error) -> string { + load_var e + load_field .0 + return +} + +function user.llm.LlmUsesAuthRole() -> auth.Role { + load_const user.auth.Role.Admin + alloc_variant user.auth.Role + return +} + +function user.llm.LlmUsesNestedClient(c: llm.openai.Client) -> string { + load_var c + load_field .0 + return +} + +function user.llm.LlmUsesRootAlias(cfg: Config) -> string { + load_var cfg + load_field .key + return +} + +function user.llm.LlmUsesRootConfig(cfg: Config) -> string { + load_var cfg + load_field .key + return +} + +function user.llm.LlmUsesRootError(e: Error) -> string { + load_var e + load_field .message + return +} + +function user.llm.LlmUsesRootStatus() -> Status { + load_const user.Status.Ok + alloc_variant user.Status + return +} + +function user.llm.openai.OpenAIConstruct(key: string) -> void { + alloc_instance Client + copy 0 + load_var key + store_field .api_key + copy 0 + load_const "org-123" + store_field .org_id + return +} + +function user.llm.openai.OpenAIEnumMatch(m: void) -> string { + load_var m + discriminant + copy 0 + load_const Model.GPT4o + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L3 + + L0: + copy 0 + load_const Model.GPT4oMini + cmp_op == + pop_jump_if_false L1 + pop 1 + jump L2 + + L1: + pop 1 + load_const "o3" + jump L4 + + L2: + load_const "gpt4o-mini" + jump L4 + + L3: + load_const "gpt4o" + + L4: + return +} + +function user.llm.openai.OpenAIEnumReturn() -> void { + load_const user.llm.openai.Model.GPT4o + alloc_variant user.llm.openai.Model + return +} + +function user.llm.openai.OpenAIIdentity(c: void) -> void { + load_var c + return +} + +function user.llm.openai.OpenAIMatchesAuthRole(r: auth.Role) -> string { + load_var r + load_const undefined_enum::user.llm.openai.root.auth.Role.Admin + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var r + load_const undefined_enum::user.llm.openai.root.auth.Role.User + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var r + load_const undefined_enum::user.llm.openai.root.auth.Role.Guest + cmp_op == + pop_jump_if_false L4 + load_const "guest" + jump L4 + + L2: + load_const "user" + jump L4 + + L3: + load_const "admin" + + L4: + return +} + +function user.llm.openai.OpenAIMatchesLlmStatus(s: llm.Status) -> string { + load_var s + load_const undefined_enum::user.llm.openai.root.llm.Status.Ready + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var s + load_const undefined_enum::user.llm.openai.root.llm.Status.Generating + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var s + load_const undefined_enum::user.llm.openai.root.llm.Status.Done + cmp_op == + pop_jump_if_false L4 + load_const "done" + jump L4 + + L2: + load_const "generating" + jump L4 + + L3: + load_const "ready" + + L4: + return +} + +function user.llm.openai.OpenAIMatchesRootStatus(s: Status) -> string { + load_var s + load_const undefined_enum::user.llm.openai.root.Status.Ok + cmp_op == + pop_jump_if_false L0 + jump L3 + + L0: + load_var s + load_const undefined_enum::user.llm.openai.root.Status.Failed + cmp_op == + pop_jump_if_false L1 + jump L2 + + L1: + load_var s + load_const undefined_enum::user.llm.openai.root.Status.Pending + cmp_op == + pop_jump_if_false L4 + load_const "pending" + jump L4 + + L2: + load_const "failed" + jump L4 + + L3: + load_const "ok" + + L4: + return +} + +function user.llm.openai.OpenAIMixedErrors(openai_err: Error, root_err: Error, llm_err: llm.Error, auth_err: auth.Error) -> string { + load_var openai_err + load_field .1 + return +} + +function user.llm.openai.OpenAIMixedModels(openai_model: void, llm_model: llm.Model) -> string { + load_var openai_model + discriminant + copy 0 + load_const Model.GPT4o + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L3 + + L0: + copy 0 + load_const Model.GPT4oMini + cmp_op == + pop_jump_if_false L1 + pop 1 + jump L2 + + L1: + pop 1 + load_const "o3" + jump L4 + + L2: + load_const "mini" + jump L4 + + L3: + load_const "gpt4o" + + L4: + return +} + +function user.llm.openai.OpenAIThrowClass(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + alloc_instance Error + copy 0 + load_const 429 + store_field .code + copy 0 + load_const "rate limited" + store_field .message + throw +} + +function user.llm.openai.OpenAIThrowEnum(x: int) -> string { + load_var x + copy 0 + load_const 0 + cmp_op == + pop_jump_if_false L0 + pop 1 + jump L1 + + L0: + pop 1 + load_const "ok" + return + + L1: + load_const user.llm.openai.Model.O3 + alloc_variant user.llm.openai.Model + throw +} + +function user.llm.openai.OpenAIUsesAuthConfig(cfg: auth.Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.llm.openai.OpenAIUsesAuthRole() -> auth.Role { + load_const user.auth.Role.User + alloc_variant user.auth.Role + return +} + +function user.llm.openai.OpenAIUsesLlmConfig(cfg: llm.Config) -> string { + load_var cfg + load_field .0 + return +} + +function user.llm.openai.OpenAIUsesLlmResponse(r: llm.Response) -> string { + load_var r + load_field .0 + return +} + +function user.llm.openai.OpenAIUsesLlmStatus() -> llm.Status { + load_const user.llm.Status.Generating + alloc_variant user.llm.Status + return +} + +function user.llm.openai.OpenAIUsesRootConfig(cfg: Config) -> string { + load_var cfg + load_field .key + return +} + +function user.llm.openai.OpenAIUsesRootStatus() -> Status { + load_const user.Status.Ok + alloc_variant user.Status + return +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__main.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__main.snap new file mode 100644 index 0000000000..09a6532b1c --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__main.snap @@ -0,0 +1,135 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +// ═══════════════════════════════════════════════════════════════════ +// ROOT NAMESPACE — defines Config, Error, Status, ConfigAlias +// +// IMPORTANT: ns_llm and ns_auth ALSO define types with these exact +// same names. Bare references here must resolve to the ROOT versions. +// ═══════════════════════════════════════════════════════════════════ + +class Config { + key: string + env: string +} + +class Error { + code: int + message: string +} + +enum Status { + Ok, + Failed, + Pending, +} + +type ConfigAlias = Config; + +// ── Bare name usage from root ─────────────────────────────────── + +// Param + return types: bare Config/Status must be root.Config/root.Status +function RootIdentity(cfg: Config) -> Config { + cfg +} + +// Constructor: bare Config must build root.Config +function RootConstruct(key: string) -> Config { + Config { key: key, env: "prod" } +} + +// Enum variant: bare Status.Ok must be root.Status.Ok +function RootEnumReturn() -> Status { + Status.Ok +} + +// Enum match: all arms must resolve to root.Status variants +function RootEnumMatch(s: Status) -> string { + match (s) { + Status.Ok => "ok", + Status.Failed => "failed", + Status.Pending => "pending", + } +} + +// Type alias: bare ConfigAlias must be root.ConfigAlias = root.Config +function RootAliasParam(cfg: ConfigAlias) -> string { + cfg.key +} + +// Throw class: bare Error must be root.Error +function RootThrowClass(x: int) -> string { + match (x) { + 0 => { + throw Error { code: 500, message: "root error" } + }, + _ => "ok", + } +} + +// Throw enum: bare Status.Failed must be root.Status.Failed +function RootThrowEnum(x: int) -> string { + match (x) { + 0 => { + throw Status.Failed + }, + _ => "ok", + } +} + +// ── Cross-namespace from root ─────────────────────────────────── + +// Reference ns_llm types (which have SAME names as root types) +function RootUsesLlmConfig(cfg: root.llm.Config) -> string { + cfg.model +} + +function RootUsesLlmError(e: root.llm.Error) -> string { + e.reason +} + +function RootUsesLlmStatus() -> root.llm.Status { + root.llm.Status.Ready +} + +// Reference ns_auth types +function RootUsesAuthConfig(cfg: root.auth.Config) -> string { + cfg.provider +} + +function RootUsesAuthError(e: root.auth.Error) -> string { + e.realm +} + +// Reference nested ns_llm.openai types +function RootUsesNestedClient(c: root.llm.openai.Client) -> string { + c.api_key +} + +// ── Mixed: root types alongside qualified cross-ns types ──────── + +// Takes root.Config, returns root.llm.Config — must be different types +function RootMixedConfigs(root_cfg: Config, llm_cfg: root.llm.Config) -> string { + root_cfg.key +} + +// ── Stream companion types ────────────────────────────────────── +// Classes whose fields reference cross-namespace types. +// The $stream companions must resolve all field types correctly. + +// Root class with fields from other namespaces +class RootWithCrossNsFields { + own_config: Config + llm_config: root.llm.Config + auth_config: root.auth.Config + llm_response: root.llm.Response + nested_client: root.llm.openai.Client + own_status: Status + own_alias: ConfigAlias +} + +// Root class referencing a cross-namespace type alias +class RootWithCrossNsAlias { + llm_alias: root.llm.ResponseAlias + own_alias: ConfigAlias +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_auth_auth.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_auth_auth.snap new file mode 100644 index 0000000000..374112ec02 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_auth_auth.snap @@ -0,0 +1,158 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +// ═══════════════════════════════════════════════════════════════════ +// AUTH NAMESPACE — defines Config, Error, Role +// +// Config and Error have the SAME names as root and llm types. +// Bare references here must resolve to the AUTH versions. +// ═══════════════════════════════════════════════════════════════════ + +class Config { + provider: string + secret: string +} + +class Error { + realm: string + expired: bool +} + +enum Role { + Admin, + User, + Guest, +} + +class Token { + value: string + role: Role +} + +type TokenAlias = Token; + +// ── Bare name usage (must resolve to auth.* NOT root.*) ───────── + +// Bare Config param: must be auth.Config (.provider), not root (.key) or llm (.model) +function AuthIdentity(cfg: Config) -> Config { + cfg +} + +// Bare constructor: must build auth.Config +function AuthConstruct(provider: string) -> Config { + Config { provider: provider, secret: "s3cret" } +} + +// Bare enum return: must be auth.Role.Admin +function AuthEnumReturn() -> Role { + Role.Admin +} + +// Bare enum match: must match against auth.Role variants +function AuthEnumMatch(r: Role) -> string { + match (r) { + Role.Admin => "admin", + Role.User => "user", + Role.Guest => "guest", + } +} + +// Bare alias: must be auth.TokenAlias = auth.Token +function AuthAliasParam(t: TokenAlias) -> string { + t.value +} + +// Bare class in throw +function AuthThrowClass(x: int) -> string { + match (x) { + 0 => { + throw Error { realm: "auth failed", expired: true } + }, + _ => "ok", + } +} + +// Bare enum in throw +function AuthThrowEnum(x: int) -> string { + match (x) { + 0 => { + throw Role.Guest + }, + _ => "ok", + } +} + +// Token constructor with nested enum field +function AuthMakeToken(v: string) -> Token { + Token { value: v, role: Role.User } +} + +// ── Cross-namespace: root.X ───────────────────────────────────── + +function AuthUsesRootConfig(cfg: root.Config) -> string { + cfg.key +} + +function AuthUsesRootStatus() -> root.Status { + root.Status.Pending +} + +function AuthMatchesRootStatus(s: root.Status) -> string { + match (s) { + root.Status.Ok => "ok", + root.Status.Failed => "failed", + root.Status.Pending => "pending", + } +} + +function AuthThrowsRootError(x: int) -> string { + match (x) { + 0 => { + throw root.Error { code: 403, message: "forbidden" } + }, + _ => "ok", + } +} + +// ── Cross-namespace: sibling (root.llm.X) ─────────────────────── + +function AuthUsesLlmConfig(cfg: root.llm.Config) -> string { + cfg.model +} + +function AuthUsesLlmResponse(r: root.llm.Response) -> string { + r.text +} + +function AuthUsesLlmStatus() -> root.llm.Status { + root.llm.Status.Ready +} + +function AuthMatchesLlmStatus(s: root.llm.Status) -> string { + match (s) { + root.llm.Status.Ready => "ready", + root.llm.Status.Generating => "generating", + root.llm.Status.Done => "done", + } +} + +// ── Cross-namespace: nested (root.llm.openai.X) ──────────────── + +function AuthUsesNestedClient(c: root.llm.openai.Client) -> string { + c.api_key +} + +// ── Mixed: auth + root + llm types ────────────────────────────── + +function AuthMixedConfigs( + auth_cfg: Config, + root_cfg: root.Config, + llm_cfg: root.llm.Config, +) -> string { + auth_cfg.provider +} + +// auth.Error + root.Error + llm.Error — three different types +function AuthMixedErrors(auth_err: Error, root_err: root.Error, llm_err: root.llm.Error) -> string { + auth_err.realm +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_models.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_models.snap new file mode 100644 index 0000000000..6eef251d48 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_models.snap @@ -0,0 +1,205 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +// ═══════════════════════════════════════════════════════════════════ +// LLM NAMESPACE — defines Config, Error, Status, ConfigAlias +// +// These have the SAME names as root types. Bare references here +// must resolve to the LLM versions, NOT root versions. +// ═══════════════════════════════════════════════════════════════════ + +class Config { + model: string + temperature: float +} + +class Error { + reason: string + retryable: bool +} + +enum Status { + Ready, + Generating, + Done, +} + +enum Model { + GPT4, + Claude, +} + +class Response { + text: string + tokens: int +} + +type ConfigAlias = Config; + +type ResponseAlias = Response; + +// ── Bare name usage (must resolve to llm.* NOT root.*) ────────── + +// Bare Config param: must be llm.Config (has .model), not root.Config (has .key) +function LlmIdentity(cfg: Config) -> Config { + cfg +} + +// Bare constructor: must build llm.Config +function LlmConstruct(model: string) -> Config { + Config { model: model, temperature: 0.7 } +} + +// Bare enum return: must be llm.Status.Ready, not root.Status.Ok +function LlmEnumReturn() -> Status { + Status.Ready +} + +// Bare enum match: must match against llm.Status variants +function LlmEnumMatch(s: Status) -> string { + match (s) { + Status.Ready => "ready", + Status.Generating => "generating", + Status.Done => "done", + } +} + +// Bare alias: must be llm.ConfigAlias = llm.Config +function LlmAliasParam(cfg: ConfigAlias) -> string { + cfg.model +} + +// Bare class in throw +function LlmThrowClass(x: int) -> string { + match (x) { + 0 => { + throw Error { reason: "llm failed", retryable: true } + }, + _ => "ok", + } +} + +// Bare enum in throw +function LlmThrowEnum(x: int) -> string { + match (x) { + 0 => { + throw Status.Done + }, + _ => "ok", + } +} + +// Bare constructor with field access +function LlmResponseConstruct(text: string) -> Response { + Response { text: text, tokens: 42 } +} + +// ── Cross-namespace: root.X (must get root types, not llm) ────── + +// root.Config has .key (not .model) — proves it's root.Config +function LlmUsesRootConfig(cfg: root.Config) -> string { + cfg.key +} + +// root.Error has .code (not .reason) — proves it's root.Error +function LlmUsesRootError(e: root.Error) -> string { + e.message +} + +// root.Status has Ok/Failed/Pending, not Ready/Generating/Done +function LlmUsesRootStatus() -> root.Status { + root.Status.Ok +} + +// root.Status match — must match root variants +function LlmMatchesRootStatus(s: root.Status) -> string { + match (s) { + root.Status.Ok => "ok", + root.Status.Failed => "failed", + root.Status.Pending => "pending", + } +} + +// root.ConfigAlias must be root.ConfigAlias = root.Config +function LlmUsesRootAlias(cfg: root.ConfigAlias) -> string { + cfg.key +} + +// Throw root.Error from llm namespace +function LlmThrowsRootError(x: int) -> string { + match (x) { + 0 => { + throw root.Error { code: 404, message: "not found" } + }, + _ => "ok", + } +} + +// Throw root enum variant +function LlmThrowsRootEnum(x: int) -> string { + match (x) { + 0 => { + throw root.Status.Failed + }, + _ => "ok", + } +} + +// ── Cross-namespace: sibling namespace (root.auth.X) ──────────── + +// Reference ns_auth.Config (has .provider) from ns_llm +function LlmUsesAuthConfig(cfg: root.auth.Config) -> string { + cfg.provider +} + +// Reference ns_auth.Error (has .realm) from ns_llm +function LlmUsesAuthError(e: root.auth.Error) -> string { + e.realm +} + +// Reference ns_auth.Role enum from ns_llm +function LlmUsesAuthRole() -> root.auth.Role { + root.auth.Role.Admin +} + +// ── Cross-namespace: child namespace (root.llm.openai.X) ──────── + +// Reference nested openai.Client from parent llm namespace +function LlmUsesNestedClient(c: root.llm.openai.Client) -> string { + c.api_key +} + +// ── Mixed: llm types + qualified root/auth types ──────────────── + +// All three Configs in one signature — must be three different types +function LlmMixedConfigs( + llm_cfg: Config, + root_cfg: root.Config, + auth_cfg: root.auth.Config, +) -> string { + llm_cfg.model +} + +// ── Stream companion types ────────────────────────────────────── +// Classes with cross-namespace field types. +// The $stream companions must resolve all field types, including +// types from root and sibling namespaces. + +// llm class with fields from root and sibling namespaces +class LlmWithCrossNsFields { + own_config: Config + own_response: Response + root_config: root.Config + root_error: root.Error + auth_config: root.auth.Config + nested_client: root.llm.openai.Client + own_status: Status + own_alias: ConfigAlias + root_alias: root.ConfigAlias +} + +// llm class referencing root type alias (this was the alias stream bug) +class LlmWithRootAlias { + root_alias: root.ConfigAlias + own_alias: ResponseAlias +} diff --git a/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_ns_openai_client.snap b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_ns_openai_client.snap new file mode 100644 index 0000000000..e034d25012 --- /dev/null +++ b/baml_language/crates/baml_tests/snapshots/namespaces_type_resolution/baml_tests__namespaces_type_resolution__10_formatter__ns_llm_ns_openai_client.snap @@ -0,0 +1,146 @@ +--- +source: crates/baml_tests/src/generated_tests.rs +--- +// ═══════════════════════════════════════════════════════════════════ +// LLM.OPENAI NAMESPACE (nested) — defines Client, Error, Model +// +// Error and Model have the SAME names as root, llm, and auth types. +// Bare references here must resolve to the openai versions. +// ═══════════════════════════════════════════════════════════════════ + +class Client { + api_key: string + org_id: string +} + +class Error { + status_code: int + body: string +} + +enum Model { + GPT4o, + GPT4oMini, + O3, +} + +// ── Bare name usage (must resolve to llm.openai.*) ────────────── + +function OpenAIIdentity(c: Client) -> Client { + c +} + +function OpenAIConstruct(key: string) -> Client { + Client { api_key: key, org_id: "org-123" } +} + +function OpenAIEnumReturn() -> Model { + Model.GPT4o +} + +function OpenAIEnumMatch(m: Model) -> string { + match (m) { + Model.GPT4o => "gpt4o", + Model.GPT4oMini => "gpt4o-mini", + Model.O3 => "o3", + } +} + +function OpenAIThrowClass(x: int) -> string { + match (x) { + 0 => { + throw Error { status_code: 429, body: "rate limited" } + }, + _ => "ok", + } +} + +function OpenAIThrowEnum(x: int) -> string { + match (x) { + 0 => { + throw Model.O3 + }, + _ => "ok", + } +} + +// ── Cross-namespace: root.X ───────────────────────────────────── + +function OpenAIUsesRootConfig(cfg: root.Config) -> string { + cfg.key +} + +function OpenAIUsesRootStatus() -> root.Status { + root.Status.Ok +} + +function OpenAIMatchesRootStatus(s: root.Status) -> string { + match (s) { + root.Status.Ok => "ok", + root.Status.Failed => "failed", + root.Status.Pending => "pending", + } +} + +// ── Cross-namespace: parent (root.llm.X) ──────────────────────── + +// Parent llm namespace — NOT the same as bare names here +function OpenAIUsesLlmConfig(cfg: root.llm.Config) -> string { + cfg.model +} + +function OpenAIUsesLlmResponse(r: root.llm.Response) -> string { + r.text +} + +function OpenAIUsesLlmStatus() -> root.llm.Status { + root.llm.Status.Generating +} + +function OpenAIMatchesLlmStatus(s: root.llm.Status) -> string { + match (s) { + root.llm.Status.Ready => "ready", + root.llm.Status.Generating => "generating", + root.llm.Status.Done => "done", + } +} + +// ── Cross-namespace: sibling of parent (root.auth.X) ──────────── + +function OpenAIUsesAuthConfig(cfg: root.auth.Config) -> string { + cfg.provider +} + +function OpenAIUsesAuthRole() -> root.auth.Role { + root.auth.Role.User +} + +function OpenAIMatchesAuthRole(r: root.auth.Role) -> string { + match (r) { + root.auth.Role.Admin => "admin", + root.auth.Role.User => "user", + root.auth.Role.Guest => "guest", + } +} + +// ── Mixed: all four namespace Errors ──────────────────────────── + +// openai.Error (.status_code), root.Error (.code), +// llm.Error (.reason), auth.Error (.realm) +function OpenAIMixedErrors( + openai_err: Error, + root_err: root.Error, + llm_err: root.llm.Error, + auth_err: root.auth.Error, +) -> string { + openai_err.body +} + +// openai.Model, llm.Model — both named Model but different variants +function OpenAIMixedModels(openai_model: Model, llm_model: root.llm.Model) -> string { + match (openai_model) { + Model.GPT4o => "gpt4o", + Model.GPT4oMini => "mini", + Model.O3 => "o3", + } +} diff --git a/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap b/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap index 5e8fc9f05b..b8c6460aac 100644 --- a/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap +++ b/baml_language/crates/baml_tests/snapshots/stream_types/baml_tests__stream_types__04_tir.snap @@ -385,7 +385,7 @@ class user.foo.NsRefToTop$stream { inner: null | user.Inner$stream status: null | user.Status items: user.Inner$stream[] - alias_ref: null | unknown + alias_ref: null | user.Inner$stream } class user.TopRefToNs { ns_class: user.foo.NsClass diff --git a/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__04_tir.snap b/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__04_tir.snap index 527c8e658f..74a98f6de1 100644 --- a/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__04_tir.snap +++ b/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__04_tir.snap @@ -12,7 +12,7 @@ function user.Bar(x: unknown) -> int throws never { { : 1 1 : 1 } - !! 208..229: unresolved type: unknown_param_type + !! 210..229: unresolved type: unknown_param_type } function user.Baz() -> unknown? throws never { { : null diff --git a/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__05_diagnostics.snap b/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__05_diagnostics.snap index c45af65edf..8e1fcafcf3 100644 --- a/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__05_diagnostics.snap +++ b/baml_language/crates/baml_tests/snapshots/unknown_type_error/baml_tests__unknown_type_error__05_diagnostics.snap @@ -13,11 +13,11 @@ source: crates/baml_tests/src/generated_tests.rs ───╯ [type] Error: unresolved type: unknown_param_type - ╭─[ unknown_type_error.baml:8:14 ] + ╭─[ unknown_type_error.baml:8:16 ] │ 8 │ function Bar(x: unknown_param_type) -> int { - │ ──────────┬────────── - │ ╰──────────── unresolved type: unknown_param_type + │ ─────────┬───────── + │ ╰─────────── unresolved type: unknown_param_type │ │ Note: Error code: E0001 ───╯ diff --git a/baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs b/baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs index 04bee0c961..960eb03175 100644 --- a/baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs +++ b/baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs @@ -54,7 +54,7 @@ fn unknown_type_in_param() { { : never return 0 : 0 } - !! 11..25: unresolved type: Nonexistent + !! 13..25: unresolved type: Nonexistent } "); } From cdee8ecb3069ee5e856c15ac6477d1165f67f679 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 18:06:06 -0700 Subject: [PATCH 09/10] Address review: requalify map keys, assert suggestion text in unit tests - expand.rs: recursively requalify map key types in requalify_for_caller - phase5.rs: assert "root.Config" suggestion text in bare_name_cross_namespace_rejected, assert "unresolved type: ns2.MyClass" in multi_segment_bare_path_rejected Co-Authored-By: Claude Opus 4.6 (1M context) --- .../crates/baml_compiler2_ppir/src/expand.rs | 2 +- .../baml_tests/src/compiler2_tir/phase5.rs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/baml_language/crates/baml_compiler2_ppir/src/expand.rs b/baml_language/crates/baml_compiler2_ppir/src/expand.rs index 6c098f005c..5b3b4e4252 100644 --- a/baml_language/crates/baml_compiler2_ppir/src/expand.rs +++ b/baml_language/crates/baml_compiler2_ppir/src/expand.rs @@ -166,7 +166,7 @@ fn requalify_for_caller(ty: PpirTy, alias_ns: &[Name], caller_ns: &[Name]) -> Pp attrs, }, PpirTy::Map { key, value, attrs } => PpirTy::Map { - key, + key: Box::new(requalify_for_caller(*key, alias_ns, caller_ns)), value: Box::new(requalify_for_caller(*value, alias_ns, caller_ns)), attrs, }, diff --git a/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs b/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs index 12409e6b28..d6707ac771 100644 --- a/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs +++ b/baml_language/crates/baml_tests/src/compiler2_tir/phase5.rs @@ -721,7 +721,16 @@ fn bare_name_cross_namespace_rejected() { matches!(ty, baml_compiler2_tir::ty::Ty::Unknown { .. }), "bare Config from ns_llm should not resolve" ); - assert!(!diags.is_empty(), "should emit UnresolvedType diagnostic"); + assert!( + diags.len() == 1, + "should emit exactly one diagnostic, got: {:?}", + diags + ); + let msg = diags[0].to_string(); + assert!( + msg.contains("root.Config"), + "diagnostic should suggest `root.Config`, got: {msg}" + ); } #[test] @@ -754,4 +763,10 @@ fn multi_segment_bare_path_rejected() { matches!(ty, baml_compiler2_tir::ty::Ty::Unknown { .. }), "ns2.MyClass from ns1 should not resolve without root. prefix" ); + assert!(!diags.is_empty(), "should emit UnresolvedType diagnostic"); + let msg = diags[0].to_string(); + assert!( + msg.contains("unresolved type: ns2.MyClass"), + "diagnostic should mention ns2.MyClass, got: {msg}" + ); } From 1c6e27623725bfc6398262106df5e914c0068ff9 Mon Sep 17 00:00:00 2001 From: hellovai Date: Sat, 28 Mar 2026 20:17:00 -0700 Subject: [PATCH 10/10] Update throws LSP tests: use enum type instead of unsupported enum variants Enum variants in throws type position (e.g. throws Errors.AuthError) are not yet supported in the type system. Update 4 LSP action tests to use the enum type directly (throws Errors) and document the known limitation. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../throw/throws_caller_variant_contract.baml | 46 ++++++++----------- .../throw/throws_enum_variant_precise.baml | 43 +++++++++-------- .../throw/throws_enum_variant_violation.baml | 41 +++++++++-------- .../test_files/syntax/throw/throws_mixed.baml | 25 +++++----- 4 files changed, 76 insertions(+), 79 deletions(-) diff --git a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_caller_variant_contract.baml b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_caller_variant_contract.baml index 1e01965b3c..4932e3c7d4 100644 --- a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_caller_variant_contract.baml +++ b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_caller_variant_contract.baml @@ -1,4 +1,5 @@ -// Caller sees variant-precise contract from callee +// Caller sees enum-type contract from callee +// NOTE: enum variants in throws type position are not yet supported. enum Errors { AuthError @@ -6,7 +7,7 @@ enum Errors { InternalError } -function MayFail(x: int) -> string throws Errors.AuthError | Errors.NotFoundError { +function MayFail(x: int) -> string throws Errors { match (x) { 0 => throw Errors.AuthError, _ => throw Errors.NotFoundError @@ -22,37 +23,28 @@ function CallerGood(x: int) -> string { //---- //- diagnostics -// Error: throws contract violation: `user.AuthError | user.NotFoundError` is missing user.Errors.AuthError, user.Errors.NotFoundError -// ╭─[ throw_throws_caller_variant_contract.baml:9:42 ] -// │ -// 9 │ function MayFail(x: int) -> string throws Errors.AuthError | Errors.NotFoundError { -// │ ────────────────────┬─────────────────── -// │ ╰───────────────────── throws contract violation: `user.AuthError | user.NotFoundError` is missing user.Errors.AuthError, user.Errors.NotFoundError -// │ -// │ Note: Error code: E0001 -// ───╯ -// Error: extraneous throws declaration: user.AuthError, user.NotFoundError -// ╭─[ throw_throws_caller_variant_contract.baml:9:42 ] -// │ -// 9 │ function MayFail(x: int) -> string throws Errors.AuthError | Errors.NotFoundError { -// │ ────────────────────┬─────────────────── -// │ ╰───────────────────── extraneous throws declaration: user.AuthError, user.NotFoundError -// │ -// │ Note: Error code: E0001 -// ───╯ -// Error: unreachable arm -// ╭─[ throw_throws_caller_variant_contract.baml:18:25 ] +// Error: throws contract violation: `user.Errors` is missing user.Errors.AuthError, user.Errors.NotFoundError +// ╭─[ throw_throws_caller_variant_contract.baml:10:42 ] +// │ +// 10 │ function MayFail(x: int) -> string throws Errors { +// │ ───┬─── +// │ ╰───── throws contract violation: `user.Errors` is missing user.Errors.AuthError, user.Errors.NotFoundError +// │ +// │ Note: Error code: E0001 +// ────╯ +// Error: extraneous throws declaration: user.Errors +// ╭─[ throw_throws_caller_variant_contract.baml:10:42 ] // │ -// 18 │ Errors.AuthError => "auth", -// │ ───┬── -// │ ╰──── unreachable arm +// 10 │ function MayFail(x: int) -> string throws Errors { +// │ ───┬─── +// │ ╰───── extraneous throws declaration: user.Errors // │ // │ Note: Error code: E0001 // ────╯ // Error: unreachable arm -// ╭─[ throw_throws_caller_variant_contract.baml:19:29 ] +// ╭─[ throw_throws_caller_variant_contract.baml:20:29 ] // │ -// 19 │ Errors.NotFoundError => "notfound" +// 20 │ Errors.NotFoundError => "notfound" // │ ─────┬──── // │ ╰────── unreachable arm // │ diff --git a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_precise.baml b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_precise.baml index 857db62360..9cf02b4af1 100644 --- a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_precise.baml +++ b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_precise.baml @@ -1,4 +1,7 @@ -// throws with specific enum variants — exact match, no diagnostic +// throws with enum type — exact match +// NOTE: enum variants in throws type position are not yet supported; +// using the enum type directly still produces contract mismatch because +// the throws checker compares Ty::Enum vs Ty::EnumVariant. enum Errors { AuthError @@ -6,7 +9,7 @@ enum Errors { InternalError } -function ThrowsVariantExact(x: int) -> string throws Errors.AuthError | Errors.NotFoundError { +function ThrowsVariantExact(x: int) -> string throws Errors { match (x) { 0 => throw Errors.AuthError, _ => throw Errors.NotFoundError @@ -15,21 +18,21 @@ function ThrowsVariantExact(x: int) -> string throws Errors.AuthError | Errors.N //---- //- diagnostics -// Error: throws contract violation: `user.AuthError | user.NotFoundError` is missing user.Errors.AuthError, user.Errors.NotFoundError -// ╭─[ throw_throws_enum_variant_precise.baml:9:55 ] -// │ -// 9 │ function ThrowsVariantExact(x: int) -> string throws Errors.AuthError | Errors.NotFoundError { -// │ ────────────────────┬─────────────────── -// │ ╰───────────────────── throws contract violation: `user.AuthError | user.NotFoundError` is missing user.Errors.AuthError, user.Errors.NotFoundError -// │ -// │ Note: Error code: E0001 -// ───╯ -// Error: extraneous throws declaration: user.AuthError, user.NotFoundError -// ╭─[ throw_throws_enum_variant_precise.baml:9:55 ] -// │ -// 9 │ function ThrowsVariantExact(x: int) -> string throws Errors.AuthError | Errors.NotFoundError { -// │ ────────────────────┬─────────────────── -// │ ╰───────────────────── extraneous throws declaration: user.AuthError, user.NotFoundError -// │ -// │ Note: Error code: E0001 -// ───╯ +// Error: throws contract violation: `user.Errors` is missing user.Errors.AuthError, user.Errors.NotFoundError +// ╭─[ throw_throws_enum_variant_precise.baml:12:55 ] +// │ +// 12 │ function ThrowsVariantExact(x: int) -> string throws Errors { +// │ ───┬─── +// │ ╰───── throws contract violation: `user.Errors` is missing user.Errors.AuthError, user.Errors.NotFoundError +// │ +// │ Note: Error code: E0001 +// ────╯ +// Error: extraneous throws declaration: user.Errors +// ╭─[ throw_throws_enum_variant_precise.baml:12:55 ] +// │ +// 12 │ function ThrowsVariantExact(x: int) -> string throws Errors { +// │ ───┬─── +// │ ╰───── extraneous throws declaration: user.Errors +// │ +// │ Note: Error code: E0001 +// ────╯ diff --git a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_violation.baml b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_violation.baml index 99eb712d41..07de9da021 100644 --- a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_violation.baml +++ b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_enum_variant_violation.baml @@ -1,4 +1,5 @@ -// throws specific variant, but body throws an extra variant — E0096 +// throws enum type, but body throws variants — contract mismatch +// NOTE: enum variants in throws type position are not yet supported. enum Errors { AuthError @@ -6,7 +7,7 @@ enum Errors { InternalError } -function ThrowsVariantViolation(x: int) -> string throws Errors.AuthError { +function ThrowsVariantViolation(x: int) -> string throws Errors { match (x) { 0 => throw Errors.AuthError, _ => throw Errors.NotFoundError @@ -15,21 +16,21 @@ function ThrowsVariantViolation(x: int) -> string throws Errors.AuthError { //---- //- diagnostics -// Error: throws contract violation: `user.AuthError` is missing user.Errors.AuthError, user.Errors.NotFoundError -// ╭─[ throw_throws_enum_variant_violation.baml:9:59 ] -// │ -// 9 │ function ThrowsVariantViolation(x: int) -> string throws Errors.AuthError { -// │ ────────┬──────── -// │ ╰────────── throws contract violation: `user.AuthError` is missing user.Errors.AuthError, user.Errors.NotFoundError -// │ -// │ Note: Error code: E0001 -// ───╯ -// Error: extraneous throws declaration: user.AuthError -// ╭─[ throw_throws_enum_variant_violation.baml:9:59 ] -// │ -// 9 │ function ThrowsVariantViolation(x: int) -> string throws Errors.AuthError { -// │ ────────┬──────── -// │ ╰────────── extraneous throws declaration: user.AuthError -// │ -// │ Note: Error code: E0001 -// ───╯ +// Error: throws contract violation: `user.Errors` is missing user.Errors.AuthError, user.Errors.NotFoundError +// ╭─[ throw_throws_enum_variant_violation.baml:10:59 ] +// │ +// 10 │ function ThrowsVariantViolation(x: int) -> string throws Errors { +// │ ───┬─── +// │ ╰───── throws contract violation: `user.Errors` is missing user.Errors.AuthError, user.Errors.NotFoundError +// │ +// │ Note: Error code: E0001 +// ────╯ +// Error: extraneous throws declaration: user.Errors +// ╭─[ throw_throws_enum_variant_violation.baml:10:59 ] +// │ +// 10 │ function ThrowsVariantViolation(x: int) -> string throws Errors { +// │ ───┬─── +// │ ╰───── extraneous throws declaration: user.Errors +// │ +// │ Note: Error code: E0001 +// ────╯ diff --git a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_mixed.baml b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_mixed.baml index e544cb828b..d3b18ddad0 100644 --- a/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_mixed.baml +++ b/baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/throw/throws_mixed.baml @@ -1,11 +1,12 @@ -// throws mix of primitive + enum variant — no diagnostic when body matches +// throws mix of primitive + enum type +// NOTE: enum variants in throws type position are not yet supported. enum Errors { AuthError NotFoundError } -function ThrowsMixed(x: int) -> string throws string | Errors.AuthError { +function ThrowsMixed(x: int) -> string throws string | Errors { match (x) { 0 => throw "oops", _ => throw Errors.AuthError @@ -14,21 +15,21 @@ function ThrowsMixed(x: int) -> string throws string | Errors.AuthError { //---- //- diagnostics -// Error: throws contract violation: `string | user.AuthError` is missing user.Errors.AuthError -// ╭─[ throw_throws_mixed.baml:8:48 ] +// Error: throws contract violation: `string | user.Errors` is missing user.Errors.AuthError +// ╭─[ throw_throws_mixed.baml:9:46 ] // │ -// 8 │ function ThrowsMixed(x: int) -> string throws string | Errors.AuthError { -// │ ─────────────┬──────────── -// │ ╰────────────── throws contract violation: `string | user.AuthError` is missing user.Errors.AuthError +// 9 │ function ThrowsMixed(x: int) -> string throws string | Errors { +// │ ────────┬─────── +// │ ╰───────── throws contract violation: `string | user.Errors` is missing user.Errors.AuthError // │ // │ Note: Error code: E0001 // ───╯ -// Error: extraneous throws declaration: user.AuthError -// ╭─[ throw_throws_mixed.baml:8:48 ] +// Error: extraneous throws declaration: user.Errors +// ╭─[ throw_throws_mixed.baml:9:46 ] // │ -// 8 │ function ThrowsMixed(x: int) -> string throws string | Errors.AuthError { -// │ ─────────────┬──────────── -// │ ╰────────────── extraneous throws declaration: user.AuthError +// 9 │ function ThrowsMixed(x: int) -> string throws string | Errors { +// │ ────────┬─────── +// │ ╰───────── extraneous throws declaration: user.Errors // │ // │ Note: Error code: E0001 // ───╯