It's strange that they sometimes use [] to specify a type, other times they use (). That doesn't look very consistent to me.

I like the use of [] though, it reminds me of Scala, which I liked before they did the scala 3 fork.

[] here can be read as similar to <> in Rust, C#, Java, or C++ templates (but move the content after the `template` into the function declaration). It's not weird if you're familiar with generic programming (and C++ programmers, the target audience of Carbon right now, will all be familiar with it, they use it with their STL algorithms and collections if nothing else). The () is the ordinary "here is the parameter list" used in pretty much every C-syntax language. C doesn't have generics, so there are several ways people have extended that base C-ish syntax to support generics: <>, [], template<>, and a few others have all been done in the past.

https://en.wikipedia.org/wiki/Generic_programming - Worth studying up on if you're unfamiliar with it.

`fn partition[T: ...]` uses `[]` to define T. `s: Slice(T)` uses `(T)` to invoke the type constructor `Slice` with the type argument T. So you could say that's fine because these are different operations.

But then defining a type constructor itself still uses `()`, like `class UnsafeAllowDelete(T:! Concrete) { ... }`. It does seem somewhat inconsistent.

How is it inconsistent? The square brackets always mean "this was deduced" and the parens always indicate "this was passed in explicitly"

Square brackets do not indicate "this is a type". Instead they indicate "these things were deduced from their context"