let foo = "..."; let foo = parse(foo); let foo = escaped(foo);
I would consider this shadowing (something you can do in OcaML):
let foo = "..." in let foo = parse(foo) in let foo = escaped(foo) in dosomething(foo);;
https://reasonml.github.io/docs/en/let-binding
Although in practice I found that it's common to not indent adjacent nested let..in blocks in OCaml, either, so you'd often see something like:
let foo = "..." in let foo = parse(foo) in let foo = escaped(foo) in ...
is shadowing
let foo = bar; foo = bat;
is a compilation-time error because foo isn't mutable.
let mut foo = bar; foo = bat;
is reassignment.
in working code, either foo is declared as mutable or it's not, and it's pretty obvious from the code what's happening.
I would consider this shadowing (something you can do in OcaML):