@@ -4,7 +4,7 @@ use crate::{
44 parser:: { compile_block, parse_attribute, parse_redirection, redirecting_builtin_error} ,
55 type_check:: { check_block_input_output, type_compatible} ,
66} ;
7- use itertools :: Itertools ;
7+
88use log:: trace;
99use nu_path:: canonicalize_with;
1010use nu_protocol:: {
@@ -533,7 +533,7 @@ fn parse_def_inner(
533533 ( spans[ 0 ] , 1 )
534534 } ;
535535
536- let def_call = working_set. get_span_contents ( name_span) . to_vec ( ) ;
536+ let def_call = working_set. get_span_contents ( name_span) ;
537537 if def_call != b"def" {
538538 working_set. error ( ParseError :: UnknownState (
539539 "internal error: Wrong call name for def function" . into ( ) ,
@@ -549,7 +549,11 @@ fn parse_def_inner(
549549 // Parsing the spans and checking that they match the register signature
550550 // Using a parsed call makes more sense than checking for how many spans are in the call
551551 // Also, by creating a call, it can be checked if it matches the declaration signature
552- let ( call, call_span) = match working_set. find_decl ( & def_call) {
552+ //
553+ // NOTE: Here we only search for `def` in the permanent state,
554+ // since recursively redefining `def` is dangerous,
555+ // see https://github.com/nushell/nushell/issues/16586
556+ let ( call, call_span) = match working_set. permanent_state . find_decl ( def_call, & [ ] ) {
553557 None => {
554558 working_set. error ( ParseError :: UnknownState (
555559 "internal error: def declaration not found" . into ( ) ,
@@ -573,11 +577,7 @@ fn parse_def_inner(
573577
574578 if let Some ( name_span) = decl_name_span {
575579 // Check whether name contains [] or () -- possible missing space error
576- if let Some ( err) = detect_params_in_name (
577- working_set,
578- name_span,
579- String :: from_utf8_lossy ( & def_call) . as_ref ( ) ,
580- ) {
580+ if let Some ( err) = detect_params_in_name ( working_set, name_span, decl_id) {
581581 working_set. error ( err) ;
582582 return ( garbage ( working_set, Span :: concat ( spans) ) , None ) ;
583583 }
@@ -827,11 +827,7 @@ fn parse_extern_inner(
827827 let ( command_spans, rest_spans) = spans. split_at ( split_id) ;
828828
829829 if let Some ( name_span) = rest_spans. first ( ) {
830- if let Some ( err) = detect_params_in_name (
831- working_set,
832- * name_span,
833- String :: from_utf8_lossy ( & extern_call) . as_ref ( ) ,
834- ) {
830+ if let Some ( err) = detect_params_in_name ( working_set, * name_span, decl_id) {
835831 working_set. error ( err) ;
836832 return garbage ( working_set, concat_span) ;
837833 }
@@ -4216,35 +4212,24 @@ pub fn find_in_dirs(
42164212fn detect_params_in_name (
42174213 working_set : & StateWorkingSet ,
42184214 name_span : Span ,
4219- decl_name : & str ,
4215+ decl_id : DeclId ,
42204216) -> Option < ParseError > {
42214217 let name = working_set. get_span_contents ( name_span) ;
4222-
4223- let extract_span = |delim : u8 | {
4224- // it is okay to unwrap because we know the slice contains the byte
4225- let ( idx, _) = name
4226- . iter ( )
4227- . find_position ( |c| * * c == delim)
4228- . unwrap_or ( ( name. len ( ) , & b' ' ) ) ;
4229- let param_span = Span :: new ( name_span. start + idx - 1 , name_span. start + idx - 1 ) ;
4230- let error = ParseError :: LabeledErrorWithHelp {
4231- error : "no space between name and parameters" . into ( ) ,
4232- label : "expected space" . into ( ) ,
4233- help : format ! (
4234- "consider adding a space between the `{decl_name}` command's name and its parameters"
4235- ) ,
4236- span : param_span,
4237- } ;
4238- Some ( error)
4239- } ;
4240-
4241- if name. contains ( & b'[' ) {
4242- extract_span ( b'[' )
4243- } else if name. contains ( & b'(' ) {
4244- extract_span ( b'(' )
4245- } else {
4246- None
4218+ for ( offset, char) in name. iter ( ) . enumerate ( ) {
4219+ if * char == b'[' || * char == b'(' {
4220+ return Some ( ParseError :: LabeledErrorWithHelp {
4221+ error : "no space between name and parameters" . into ( ) ,
4222+ label : "expected space" . into ( ) ,
4223+ help : format ! (
4224+ "consider adding a space between the `{}` command's name and its parameters" ,
4225+ working_set. get_decl( decl_id) . name( )
4226+ ) ,
4227+ span : Span :: new ( offset + name_span. start - 1 , offset + name_span. start - 1 ) ,
4228+ } ) ;
4229+ }
42474230 }
4231+
4232+ None
42484233}
42494234
42504235/// Run has_flag_const and push possible error to working_set
0 commit comments