refactor: clear clippy code lints across the workspace

Machine-applicable clippy fixes plus three by-hand cleanups; all
semantics-preserving (full workspace test suite green).

Auto-applied (cargo clippy --fix):
- dropped `.clone()` on the Copy type ParamMode (ret_mode/param_mode)
- map_or(false, p) -> is_some_and(p)
- removed redundant closures and an explicit .into_iter()
- useless format!, a needless deref, an as_bytes-after-slice

By hand:
- ailang-codegen: named the loop-frame tuple types (LoopFrame /
  LoopBinderSlot) instead of the bare nested
  Vec<(String, Vec<(String, String, String, Type)>)>, clearing the
  type-complexity lint and documenting what each slot holds.
- ailang-check: collapsed the two identical pass-through arms of the
  Type-Con qualifier (already-dotted / primitive) into one `||` guard.
- ailang-core: converted a stale `///` block (it described a test that
  was relocated, documenting nothing) back to a plain `//` comment.

Remaining clippy output is 16 markdown list-indentation nits in prose
doc comments — doc formatting, not code, left for a docs pass.
This commit is contained in:
2026-06-02 02:14:15 +02:00
parent d5e69148c6
commit e5534d1532
10 changed files with 35 additions and 28 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ fn emit_ir(fixture: &str) -> String {
/// call sites (which also mention `@ail_prelude_<sym>(`) don't
/// match.
fn extract_fn_body(ir: &str, sym: &str) -> (String, String) {
let needle = format!("define ");
let needle = "define ".to_string();
let mut cursor = 0;
let sym_marker = format!("@ail_prelude_{sym}(");
loop {
+9 -10
View File
@@ -128,7 +128,7 @@ impl Subst {
ret: Box::new(self.apply(ret)),
effects: effects.clone(),
param_modes: param_modes.clone(),
ret_mode: ret_mode.clone(),
ret_mode: *ret_mode,
},
Type::Forall { vars, constraints, body } => Type::Forall {
vars: vars.clone(),
@@ -4727,7 +4727,7 @@ fn strip_own_module_qual(t: &Type, module: &str) -> Type {
params: params.iter().map(|p| strip_own_module_qual(p, module)).collect(),
param_modes: param_modes.clone(),
ret: Box::new(strip_own_module_qual(ret, module)),
ret_mode: ret_mode.clone(),
ret_mode: *ret_mode,
effects: effects.clone(),
},
Type::Var { .. } => t.clone(),
@@ -4756,13 +4756,12 @@ fn strip_own_module_qual(t: &Type, module: &str) -> Type {
fn rewrite_type_cons(t: &Type, rewrite_bare: &dyn Fn(&str) -> Option<String>) -> Type {
match t {
Type::Con { name, args } => {
// The first two guards both pass the name through unchanged
// but express semantically distinct reasons (already
// qualified; primitive needs no qualification). Only a bare,
// non-primitive name is offered to `rewrite_bare`.
let qualified_name = if name.contains('.') {
name.clone()
} else if ailang_core::primitives::is_primitive_name(name) {
// Pass a name through unchanged if it is already qualified
// (contains a dot) or primitive — neither needs qualifying.
// Only a bare, non-primitive name is offered to `rewrite_bare`.
let qualified_name = if name.contains('.')
|| ailang_core::primitives::is_primitive_name(name)
{
name.clone()
} else {
rewrite_bare(name).unwrap_or_else(|| name.clone())
@@ -4784,7 +4783,7 @@ fn rewrite_type_cons(t: &Type, rewrite_bare: &dyn Fn(&str) -> Option<String>) ->
.collect(),
param_modes: param_modes.clone(),
ret: Box::new(rewrite_type_cons(ret, rewrite_bare)),
ret_mode: ret_mode.clone(),
ret_mode: *ret_mode,
effects: effects.clone(),
},
Type::Forall { vars, constraints, body } => Type::Forall {
+3 -3
View File
@@ -405,7 +405,7 @@ fn check_fn(
ParamMode::Own => 0,
},
is_value: param_tys.get(i).map(type_is_value).unwrap_or(false),
fn_param_modes: param_tys.get(i).and_then(|t| fn_modes_of(t)),
fn_param_modes: param_tys.get(i).and_then(fn_modes_of),
};
checker.binders.insert(name.clone(), initial);
}
@@ -582,7 +582,7 @@ impl<'a> Checker<'a> {
.let_binder_types
.get(&(self.def_name.to_string(), name.clone()));
let is_value = teed.map(type_is_value).unwrap_or(false);
let fn_param_modes = teed.and_then(|t| fn_modes_of(t));
let fn_param_modes = teed.and_then(fn_modes_of);
self.with_binder(
name,
BinderState { is_value, fn_param_modes, ..BinderState::default() },
@@ -684,7 +684,7 @@ impl<'a> Checker<'a> {
saved_for_params.insert(p.clone(), self.binders.remove(p));
let st = BinderState {
is_value: param_tys.get(i).map(type_is_value).unwrap_or(false),
fn_param_modes: param_tys.get(i).and_then(|t| fn_modes_of(t)),
fn_param_modes: param_tys.get(i).and_then(fn_modes_of),
..BinderState::default()
};
self.binders.insert(p.clone(), st);
+2 -2
View File
@@ -90,7 +90,7 @@ fn wildcard_residual_metavars(t: &Type) -> Type {
params: params.iter().map(wildcard_residual_metavars).collect(),
param_modes: param_modes.clone(),
ret: Box::new(wildcard_residual_metavars(ret)),
ret_mode: ret_mode.clone(),
ret_mode: *ret_mode,
effects: effects.clone(),
},
Type::Forall { vars, constraints, body } => Type::Forall {
@@ -486,7 +486,7 @@ fn lower_term(ctx: &mut Ctx, t: &Term) -> Result<MTerm> {
.enumerate()
.map(|(i, a)| {
let mut m = lower_term(ctx, a)?;
if binder_tys.get(i).map_or(false, is_str_ty) {
if binder_tys.get(i).is_some_and(is_str_ty) {
if let MTerm::Str { rep, .. } = &mut m {
*rep = StrRep::Heap;
}
+1 -1
View File
@@ -1122,7 +1122,7 @@ fn localize_own_types(t: &Type, defining_module: &str, own_type_names: &BTreeSet
ret: Box::new(localize_own_types(ret, defining_module, own_type_names)),
effects: effects.clone(),
param_modes: param_modes.clone(),
ret_mode: ret_mode.clone(),
ret_mode: *ret_mode,
},
Type::Forall { vars, constraints, body } => Type::Forall {
vars: vars.clone(),
+1 -1
View File
@@ -1005,7 +1005,7 @@ impl<'a> Emitter<'a> {
(vars, Type::Con { args, .. })
if !vars.is_empty() && vars.len() == args.len() =>
{
vars.iter().cloned().zip(args.into_iter()).collect()
vars.iter().cloned().zip(args).collect()
}
_ => BTreeMap::new(),
};
+10 -1
View File
@@ -741,6 +741,15 @@ fn main_is_void(t: &Type) -> bool {
}
}
/// One loop binder's storage on the recur stack: `(binder name, its
/// alloca SSA, the LLVM type string, the AILang type)`.
type LoopBinderSlot = (String, String, String, Type);
/// A loop frame: `(loop header block label, the binder slots active in
/// that loop)`. Pushed on entry to a `Term::Loop`, popped on exit, and
/// read by `Term::Recur` to store back into the right allocas.
type LoopFrame = (String, Vec<LoopBinderSlot>);
struct Emitter<'a> {
module: &'a Module,
/// Typed fn bodies for this module (the post-mono `MTerm` per
@@ -917,7 +926,7 @@ struct Emitter<'a> {
/// it. Saved/reset/restored at the lambda-lowering boundary
/// alongside `binder_allocas` (a `recur` cannot cross a lambda
/// boundary).
loop_frames: Vec<(String, Vec<(String, String, String, Type)>)>,
loop_frames: Vec<LoopFrame>,
/// Side buffer for `alloca` instructions emitted during body
/// lowering but hoisted to the fn's entry block. Flushed once
/// into `self.body` at `entry_block_end_marker` after
+1 -1
View File
@@ -826,7 +826,7 @@ impl Desugarer {
free_vars_in_term(&desugared_body, &local_bound, &mut frees);
let captures: Vec<String> = frees
.iter()
.filter(|f| scope.contains_key(*f))
.filter(|f| scope.contains_key(f))
.cloned()
.collect();
+5 -6
View File
@@ -2387,12 +2387,11 @@ mod tests {
.expect("qualified Constraint.class in ClassDef-method Forall is the canonical form post-canonical-class-form");
}
/// on-disk fixture for `BareCrossModuleTypeRef`. Bare
/// `Ordering` Term::Ctor with no imports; the validator catches it
/// after prelude injection (so the candidate list contains
/// `prelude.Ordering`).
// `ct1_fixture_bare_xmod_rejected` relocated to
// `crates/ailang-core/tests/workspace_pin.rs` in iter pd.2.
// on-disk fixture for `BareCrossModuleTypeRef`. Bare `Ordering`
// Term::Ctor with no imports; the validator catches it after
// prelude injection (so the candidate list contains
// `prelude.Ordering`). `ct1_fixture_bare_xmod_rejected` relocated
// to `crates/ailang-core/tests/workspace_pin.rs` in iter pd.2.
/// on-disk fixture for `BadCrossModuleTypeRef`. Qualified
/// `Mystery.Type` with `Mystery` not a known module.
+2 -2
View File
@@ -216,7 +216,7 @@ fn contracts_carry_no_decision_record_prose() {
let mut from = 0;
while let Some(i) = line[from..].find(kw) {
let p = from + i + kw.len();
if line[p..].chars().next().map_or(false, |c| c.is_ascii_digit()) {
if line[p..].chars().next().is_some_and(|c| c.is_ascii_digit()) {
return true;
}
from = p;
@@ -230,7 +230,7 @@ fn contracts_carry_no_decision_record_prose() {
if line.contains("21.g") { return Some("21.g"); }
if let Some(s) = line.find(" sketch") {
let pre = line[..s].as_bytes();
if pre.last().map_or(false, u8::is_ascii_alphanumeric)
if pre.last().is_some_and(u8::is_ascii_alphanumeric)
&& pre.iter().rev()
.take_while(|c| c.is_ascii_alphanumeric())
.any(u8::is_ascii_digit)