#![allow(deprecated)]
use std::vec;
use crate::migrations::{visit_all_modules_mut, MutProgramInfo, Occurrence};
use anyhow::{Ok, Result};
use itertools::Itertools;
use sway_ast::{
keywords::{AmpersandToken, Keyword, MutToken, Token},
Module,
};
use sway_core::{language::ty::TyModule, Engines};
use sway_types::{Span, Spanned};
use super::{ContinueMigrationProcess, DryRun, MigrationStep, MigrationStepKind};
#[allow(dead_code)]
pub(super) const REPLACE_REF_MUT_FN_PARAMETERS_STEP: MigrationStep = MigrationStep {
title: "Replace `ref mut` function parameters with `&mut`",
duration: 5,
kind: MigrationStepKind::CodeModification(
replace_ref_mut_fn_parameters_step,
&[
"change function callers, by adding `&mut` to passed parameters.",
"change function bodies, by dereferencing (`*`) parameters where needed.",
],
ContinueMigrationProcess::IfNoManualMigrationActionsNeeded,
),
help: &[
"Migration will replace `ref mut` function parameters with `&mut`.",
"E.g., `ref mut x: u64` will become `x: &mut u64`.",
],
};
fn replace_ref_mut_fn_parameters_step(
program_info: &mut MutProgramInfo,
dry_run: DryRun,
) -> Result<Vec<Occurrence>> {
fn replace_ref_mut_fn_parameters_step_impl(
_engines: &Engines,
module: &mut Module,
_ty_module: &TyModule,
dry_run: DryRun,
) -> Result<Vec<Occurrence>> {
let mut result = vec![];
for module_fn in module
.items
.iter_mut()
.map(|annotated| &mut annotated.value)
.filter_map(|decl| match decl {
sway_ast::ItemKind::Fn(module_fn) => Some(module_fn),
_ => None,
})
{
let fn_args = &mut module_fn.fn_signature.arguments.inner;
let fn_args = match fn_args {
sway_ast::FnArgs::Static(punctuated) => punctuated,
sway_ast::FnArgs::NonStatic { .. } => unreachable!(
"Module functions are always static and cannot have the `self` argument."
),
};
let mut fn_args = fn_args.iter_mut().collect_vec();
if fn_args.is_empty() {
continue;
}
for fn_arg in fn_args.iter_mut() {
match &mut fn_arg.pattern {
sway_ast::Pattern::Var {
reference: ref_opt @ Some(_),
mutable: mut_opt @ Some(_),
name,
} => {
let result_span = Span::join(
ref_opt
.as_ref()
.expect("`ref_opt` is `Some` in the match arm pattern")
.span(),
&name.span(),
);
result.push(result_span.into());
if dry_run == DryRun::No {
*ref_opt = None;
*mut_opt = None;
let insert_span = Span::empty_at_start(&fn_arg.ty.span());
fn_arg.ty = sway_ast::Ty::Ref {
ampersand_token: AmpersandToken::new(insert_span.clone()),
mut_token: Some(MutToken::new(insert_span)),
ty: Box::new(fn_arg.ty.clone()),
};
}
}
_ => continue,
}
}
}
Ok(result)
}
let res = visit_all_modules_mut(
program_info,
dry_run,
replace_ref_mut_fn_parameters_step_impl,
)?;
Ok(res.into_iter().flatten().collect())
}