I think it's important to accept that no matter how "precise" you want to be, you're going to be too imprecise to some (e.g., type theorists) and too precise to others. Even when dealing with something rigorous like homotopy type theory, there is going to be some need to define terms due to a lack of consensus of what certain terms mean; so it's always nice to just define what certain terms mean a priori and not have to worry that much about ambiguity.
For example during my math education, I encountered different professors and textbooks that would define the set of natural numbers to include 0 and almost as many that wouldn't include 0. This was never a problem because the textbook or professor would simply define what the natural numbers were for them, and there was never any issue since you knew the context you were in.
Additionally, you're inevitably going to be communicating in English (or whatever your natural tongue is) which is unavoidably inconsistent; so you must accept who your target audience is and adjust accordingly.
For me as a math person I prefer unifying theories and terminology; thus I would call all of the below type constructors:
struct Foo;
struct Bar<>;
struct Fizz<T>(T);
The first two are nullary type constructors just like foo is a nullary function in fn foo() -> u32 { 0 }. I'd call all of the below "constructed types":
impl Foo {}
impl Foo<>{}
impl Bar{}
impl Bar<> {}
impl Fizz<u32> {}
impl<T> Fizz<T> {}
fn example() {
// The discarded variable has constructed type `Foo`/`Foo<>`.
_ = Foo;
// The discarded variable has constructed type `Foo`/`Foo<>`.
_ = Foo::<>;
// The discarded variable has constructed type `Bar`/`Bar<>`.
_ = Bar;
// The discarded variable has constructed type `Bar`/`Bar<>`.
_ = Bar::<>;
// The discarded variable has constructed type `Fizz<u32>`.
_ = Fizz(0u32);
// The discarded variable has constructed type `Fizz<u32>`.
_ = Fizz::<u32>(0);
}
fn example2<T>(x: T) {
// The discarded variable has constructed type `Fizz<T>`.
_ = Fizz(x);
// The discarded variable has constructed type `Fizz<T>`.
_ = Fizz::<T>(x);
}
Normally I don't care about distinguishing between Fizz<T> and Fizz<u32> for the same reason I don't care about using different terminology for x and y in:
fn foo(a: u32) {
let x = 10u32;
let y = a;
}
Both x and y are simply "u32 variables" (in Rust terms not math terms) even though x has the property that the value is known before runtime or even compilation time. Fortunately in a higher-level context like this, type parameters/variables are truly variables in the math sense (i.e., unknown constants) since things like "interior mutability" don't make sense allowing for simpler/consistent algebraic reasoning. I'd first ask what terminology you'd use to describe x and y above and use that to guide the terminology for something like Fizz<u32> and Fizz<T>.
Things do become more complex when a proper subset of the type arguments are known a priori (e.g., Buzz<T, u32, S>); and it would seem you would need to rely on some notion of partial functions/evaluation.
Similar questions have been asked like this one on "trait constructors". I think in the end though that you shouldn't worry too much about this as you're going to confuse a lot of your audience if you expect them to have finished homotoypy type theory in order to understand your "precise" terms. By all means use some terms that are fairly common in the Rust community, but there will inevitably be some level of "imprecision" and "inconsistency"; and hopefully any confusion that arises from your chosen terminology will be clarified upon additional communication, context, and examples.