From 4878d7250f743152e2300378bea1cf7261f5ccfd Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Mon, 8 Jul 2024 19:54:40 -0700 Subject: [PATCH] fix let: glob cast from string --- crates/nu-engine/src/compile/keyword.rs | 15 ++++++++++++++- crates/nu-engine/src/eval_ir.rs | 10 ++++++++-- crates/nu-protocol/src/ir/mod.rs | 3 ++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/nu-engine/src/compile/keyword.rs b/crates/nu-engine/src/compile/keyword.rs index 93bfb3e9bc..a51fb02885 100644 --- a/crates/nu-engine/src/compile/keyword.rs +++ b/crates/nu-engine/src/compile/keyword.rs @@ -2,7 +2,7 @@ use nu_protocol::{ ast::{Block, Call, Expr, Expression}, engine::StateWorkingSet, ir::Instruction, - IntoSpanned, RegId, VarId, + IntoSpanned, RegId, Type, VarId, }; use super::{compile_block, compile_expression, BlockBuilder, CompileError, RedirectModes}; @@ -302,6 +302,8 @@ pub(crate) fn compile_let( let block_id = block_arg.as_block().ok_or_else(invalid)?; let block = working_set.get_block(block_id); + let variable = working_set.get_variable(var_id); + compile_block( working_set, builder, @@ -311,6 +313,17 @@ pub(crate) fn compile_let( io_reg, )?; + // If the variable is a glob type variable, we should cast it with GlobFrom + if variable.ty == Type::Glob { + builder.push( + Instruction::GlobFrom { + src_dst: io_reg, + no_expand: true, + } + .into_spanned(call.head), + )?; + } + builder.push( Instruction::StoreVariable { var_id, diff --git a/crates/nu-engine/src/eval_ir.rs b/crates/nu-engine/src/eval_ir.rs index a2d3acc96f..f4ee59686b 100644 --- a/crates/nu-engine/src/eval_ir.rs +++ b/crates/nu-engine/src/eval_ir.rs @@ -503,8 +503,14 @@ fn eval_instruction( } Instruction::GlobFrom { src_dst, no_expand } => { let string_value = ctx.collect_reg(*src_dst, *span)?; - let string = string_value.into_string()?; - let glob_value = Value::glob(string, *no_expand, *span); + let glob_value = if matches!(string_value, Value::Glob { .. }) { + // It already is a glob, so don't touch it. + string_value + } else { + // Treat it as a string, then cast + let string = string_value.into_string()?; + Value::glob(string, *no_expand, *span) + }; ctx.put_reg(*src_dst, glob_value.into_pipeline_data()); Ok(Continue) } diff --git a/crates/nu-protocol/src/ir/mod.rs b/crates/nu-protocol/src/ir/mod.rs index 4913e1d809..38e1bce7dc 100644 --- a/crates/nu-protocol/src/ir/mod.rs +++ b/crates/nu-protocol/src/ir/mod.rs @@ -169,7 +169,8 @@ pub enum Instruction { /// Append a value onto the end of a string. Uses `to_expanded_string(", ", ...)` on the value. /// Used for string interpolation literals. Not the same thing as the `++` operator. StringAppend { src_dst: RegId, val: RegId }, - /// Convert a string into a glob. Used for glob interpolation. + /// Convert a string into a glob. Used for glob interpolation and setting glob variables. If the + /// value is already a glob, it won't be modified (`no_expand` will have no effect). GlobFrom { src_dst: RegId, no_expand: bool }, /// Push a value onto the end of a list. Used to construct list literals. ListPush { src_dst: RegId, item: RegId },