Repository: nushell/nushell
File: crates/nu-parser/src/parse_keywords.rs (Rust)

Code before:
                    let (lvalue, explicit_type) =
                        parse_var_with_opt_type(working_set, &spans[1..(span.0)], &mut idx, false);
                    // check for extra tokens after the identifier
                    if idx + 1 < span.0 - 1 {
                        working_set.error(ParseError::ExtraTokens(spans[idx + 2]));
                    }

                    let var_name =
                        String::from_utf8_lossy(working_set.get_span_contents(lvalue.span))
                            .trim_start_matches('$')
                            .to_string();

                    if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
                        working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
                    }

                    let var_id = lvalue.as_var();
                    let rhs_type = rvalue.ty.clone();

                    if let Some(explicit_type) = &explicit_type {
                        // see `parse_let`
                        let compatible = if let Type::Any = rhs_type {
                            true
                        } else {
                            type_compatible(explicit_type, &rhs_type)
                        };

                        if !compatible {
                            working_set.error(ParseError::TypeMismatch(
                                explicit_type.clone(),
                                rhs_type.clone(),
                                Span::concat(&spans[(span.0 + 1)..]),
                            ));
                        }
                    }

                    if let Some(var_id) = var_id {
                        if explicit_type.is_none() {
                            working_set.set_variable_type(var_id, rhs_type);
                        }

                        match eval_constant(working_set, &rvalue) {
                            Ok(mut value) => {
                                // In case rhs is parsed as 'any' but is evaluated to a concrete
                                // type:
                                let mut const_type = value.get_type();

                                if let Some(explicit_type) = &explicit_type {
                                    if !type_compatible(explicit_type, &const_type) {
                                        working_set.error(ParseError::TypeMismatch(
                                            explicit_type.clone(),

Review comment (suggestion):
this probably needs to be removed unless a `const` can do runtime coercion which would make it not const :).

Code after:
    //     return Pipeline::from_vec(vec![garbage(working_set, *span)]);
    // }

    if let Some(decl_id) = working_set.find_decl(b"mut") {
        if spans.len() >= 4 {
            // This is a bit of by-hand parsing to get around the issue where we want to parse in the reverse order
            // so that the var-id created by the variable isn't visible in the expression that init it
            for span in spans.iter().enumerate() {
                let item = working_set.get_span_contents(*span.1);
                // mut x = 'f', = at least start from index 2
                if item == b"=" && spans.len() > (span.0 + 1) && span.0 > 1 {
                    let (tokens, parse_error) = lex(
                        working_set.get_span_contents(Span::concat(&spans[(span.0 + 1)..])),
                        spans[span.0 + 1].start,
                        &[],
                        &[],
                        false,
                    );

                    if let Some(parse_error) = parse_error {
                        working_set.error(parse_error);
                    }

                    let rvalue_span = Span::concat(&spans[(span.0 + 1)..]);
                    let rvalue_block = parse_block(working_set, &tokens, rvalue_span, false, true);

                    let output_type = rvalue_block.output_type();

                    let block_id = working_set.add_block(Arc::new(rvalue_block));

                    let rvalue = Expression::new(
                        working_set,
                        Expr::Block(block_id),
                        rvalue_span,
                        output_type,
                    );

                    let mut idx = 0;

                    let (lvalue, explicit_type) =
                        parse_var_with_opt_type(working_set, &spans[1..(span.0)], &mut idx, true);
                    // check for extra tokens after the identifier
                    if idx + 1 < span.0 - 1 {
                        working_set.error(ParseError::ExtraTokens(spans[idx + 2]));
                    }

                    let var_name =
                        String::from_utf8_lossy(working_set.get_span_contents(lvalue.span))
                            .trim_start_matches('$')
                            .to_string();