Repository: nushell/nushell
File: crates/nu-engine/src/eval_ir.rs (Rust)

Code before:
    Ok(())
}

/// Type check helper. Produces `CantConvert` error if `val` is not compatible with `ty`.
fn check_type(val: &Value, ty: &Type) -> Result<(), ShellError> {
    match val {
        Value::Error { error, .. } => Err(*error.clone()),
        _ if val.is_subtype_of(ty) => Ok(()),
        _ => Err(ShellError::CantConvert {
            to_type: ty.to_string(),
            from_type: val.get_type().to_string(),
            span: val.span(),
            help: None,
        }),
    }
}

/// Type check and convert value for assignment.
/// Performs implicit conversions like record to table when appropriate.
fn convert_value_for_assignment(val: Value, target_ty: &Type) -> Result<Value, ShellError> {
    if let Value::Error { error, .. } = val {
        return Err(*error);
    }

    // Check if we need to perform implicit conversion for Record -> Table or Table -> Record
    if matches!((&val, target_ty), (Value::Record { .. }, Type::Table(_))) {
        // Convert record to table by wrapping it in a list
        let span = val.span();
        let table_value = Value::list(vec![val], span);

        // Verify the conversion is valid
        if table_value.is_subtype_of(target_ty) {
            Ok(table_value)
        } else {
            // Create error with proper type information
            let from_type = table_value.get_type().to_string();
            Err(ShellError::CantConvert {
                to_type: target_ty.to_string(),
                from_type,
                span,
                help: None,
            })
        }
    } else if val.is_subtype_of(target_ty) {
        Ok(val) // No conversion needed, but compatible
    } else {
        Err(ShellError::CantConvert {
            to_type: target_ty.to_string(),
            from_type: val.get_type().to_string(),
            span: val.span(),
            help: None,

Review comment (suggestion):
I don't think records should be implicitly converted to tables? Is there some existing behavior that would suggest that you should be able to do this? If not, this should be emphasized in the PR description as a new behavior or ideally this should be a separate PR

And tables especially shouldn't be converted into records, but it doesn't look like you actually have code to do this here

Code after:
                        check_type(&val, &variable.ty)?;
                    }
                    callee_stack.add_var(var_id, val);
                } else {
                    rest_span = Some(rest_span.map_or(val.span(), |s| s.append(val.span())));
                    rest.push(val);
                }
            }
            Argument::Spread {
                vals,
                span: spread_span,
                ..
            } => match vals {
                Value::List { vals, .. } => {
                    rest.extend(vals);
                    rest_span = Some(rest_span.map_or(spread_span, |s| s.append(spread_span)));
                    always_spread = true;
                }
                Value::Nothing { .. } => {
                    rest_span = Some(rest_span.map_or(spread_span, |s| s.append(spread_span)));
                    always_spread = true;
                }
                Value::Error { error, .. } => return Err(*error),
                _ => return Err(ShellError::CannotSpreadAsList { span: vals.span() }),
            },
            Argument::Flag {
                data,
                name,
                short,
                span,
            } => {
                let var_id = find_named_var_id(&block.signature, &data[name], &data[short], span)?;
                callee_stack.add_var(var_id, Value::bool(true, span))
            }
            Argument::Named {
                data,
                name,
                short,
                span,
                val,
                ..
            } => {
                let var_id = find_named_var_id(&block.signature, &data[name], &data[short], span)?;
                callee_stack.add_var(var_id, val)
            }
            Argument::ParserInfo { .. } => (),
        }
    }

    // Add the collected rest of the arguments if a spread argument exists
    if let Some(rest_arg) = &block.signature.rest_positional {