diff --git a/crates/nu-command/tests/commands/source_env.rs b/crates/nu-command/tests/commands/source_env.rs index a293c6ed92..7a40c80cb8 100644 --- a/crates/nu-command/tests/commands/source_env.rs +++ b/crates/nu-command/tests/commands/source_env.rs @@ -1,4 +1,4 @@ -use nu_test_support::fs::Stub::{FileWithContent, FileWithContentToBeTrimmed}; +use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed}; use nu_test_support::nu; use nu_test_support::pipeline; use nu_test_support::playground::Playground; @@ -334,3 +334,25 @@ fn source_respects_early_return() { assert!(actual.err.is_empty()); } + +#[test] +fn source_after_use_should_not_error() { + Playground::setup("source_after_use", |dirs, sandbox| { + sandbox.with_files(&[EmptyFile("spam.nu")]); + + let inp = &[r#"use spam.nu"#, r#"source spam.nu"#]; + let actual = nu!(cwd: dirs.test(), &inp.join("; ")); + assert!(actual.err.is_empty()); + }) +} + +#[test] +fn use_after_source_should_not_error() { + Playground::setup("use_after_source", |dirs, sandbox| { + sandbox.with_files(&[EmptyFile("spam.nu")]); + + let inp = &[r#"source spam.nu"#, r#"use spam.nu"#]; + let actual = nu!(cwd: dirs.test(), &inp.join("; ")); + assert!(actual.err.is_empty()); + }) +} diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index 42cf330b6b..7f8416cbd3 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -1,7 +1,7 @@ use crate::{ exportable::Exportable, parse_block, - parser::{parse_attribute, parse_redirection, redirecting_builtin_error}, + parser::{compile_block, parse_attribute, parse_redirection, redirecting_builtin_error}, type_check::{check_block_input_output, type_compatible}, }; use itertools::Itertools; @@ -3805,12 +3805,16 @@ pub fn parse_source(working_set: &mut StateWorkingSet, lite_command: &LiteComman // This will load the defs from the file into the // working set, if it was a successful parse. - let block = parse( + let mut block = parse( working_set, Some(&path.path().to_string_lossy()), &contents, scoped, ); + if block.ir_block.is_none() { + let block_mut = Arc::make_mut(&mut block); + compile_block(working_set, block_mut); + } // Remove the file from the stack of files being processed. working_set.files.pop(); diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 49fcdfb445..ef72e8a104 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -6496,7 +6496,7 @@ pub fn parse_block( } /// Compile an IR block for the `Block`, adding a compile error on failure -fn compile_block(working_set: &mut StateWorkingSet<'_>, block: &mut Block) { +pub fn compile_block(working_set: &mut StateWorkingSet<'_>, block: &mut Block) { match nu_engine::compile(working_set, block) { Ok(ir_block) => { block.ir_block = Some(ir_block);