Refine types display.

This commit is contained in:
Stephen Chung 2022-01-17 21:51:04 +08:00
parent 58e1094b79
commit 86fc2f7bf1
8 changed files with 162 additions and 52 deletions

View File

@ -60,12 +60,12 @@ impl Engine {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let mut param_type_names: crate::StaticVec<_> = F::param_names() let mut param_type_names: crate::StaticVec<_> = F::param_names()
.iter() .iter()
.map(|ty| format!("_: {}", self.map_type_name(ty))) .map(|ty| format!("_: {}", self.format_type_name(ty)))
.collect(); .collect();
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
if F::return_type() != TypeId::of::<()>() { if F::return_type() != TypeId::of::<()>() {
param_type_names.push(self.map_type_name(F::return_type_name()).into()); param_type_names.push(self.format_type_name(F::return_type_name()).into());
} }
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
@ -122,9 +122,9 @@ impl Engine {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let param_type_names: crate::StaticVec<_> = F::param_names() let param_type_names: crate::StaticVec<_> = F::param_names()
.iter() .iter()
.map(|ty| format!("_: {}", self.map_type_name(ty))) .map(|ty| format!("_: {}", self.format_type_name(ty)))
.chain(std::iter::once( .chain(std::iter::once(
self.map_type_name(F::return_type_name()).into(), self.format_type_name(F::return_type_name()).into(),
)) ))
.collect(); .collect();

View File

@ -329,13 +329,47 @@ impl Engine {
/// ///
/// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name], /// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name],
/// the type name provided for the registration will be used. /// the type name provided for the registration will be used.
///
/// # Panics
///
/// Panics if the type name is `&mut`.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str { pub fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str {
self.type_names self.type_names
.get(name) .get(name)
.map(|s| s.as_str()) .map(|s| s.as_str())
.unwrap_or_else(|| map_std_type_name(name)) .unwrap_or_else(|| map_std_type_name(name, true))
}
/// Format a type name.
///
/// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name],
/// the type name provided for the registration will be used.
#[cfg(feature = "metadata")]
#[inline]
#[must_use]
pub(crate) fn format_type_name<'a>(&'a self, name: &'a str) -> std::borrow::Cow<'a, str> {
if name.starts_with("&mut ") {
let x = &name[5..];
let r = self.format_type_name(x);
return if x != r {
format!("&mut {}", r).into()
} else {
name.into()
};
}
self.type_names
.get(name)
.map(|s| s.as_str())
.unwrap_or_else(|| match name {
"INT" => return type_name::<crate::INT>(),
#[cfg(not(feature = "no_float"))]
"FLOAT" => return type_name::<crate::FLOAT>(),
_ => map_std_type_name(name, false),
})
.into()
} }
/// Make a `Box<`[`EvalAltResult<ErrorMismatchDataType>`][ERR::ErrorMismatchDataType]`>`. /// Make a `Box<`[`EvalAltResult<ErrorMismatchDataType>`][ERR::ErrorMismatchDataType]`>`.

View File

@ -968,18 +968,11 @@ impl Engine {
_ if use_indexers => { _ if use_indexers => {
let args = &mut [target, &mut idx]; let args = &mut [target, &mut idx];
let hash_get = crate::ast::FnCallHashes::from_native(global.hash_idx_get()); let hash_get = crate::ast::FnCallHashes::from_native(global.hash_idx_get());
let fn_name = crate::engine::FN_IDX_GET;
let pos = Position::NONE;
self.exec_fn_call( self.exec_fn_call(
global, global, state, lib, fn_name, hash_get, args, true, true, pos, None, level,
state,
lib,
crate::engine::FN_IDX_GET,
hash_get,
args,
true,
true,
Position::NONE,
None,
level,
) )
.map(|(v, _)| v.into()) .map(|(v, _)| v.into())
} }

View File

@ -107,8 +107,8 @@ macro_rules! def_register {
// ^ function ABI type // ^ function ABI type
// ^ function parameter generic type name (A, B, C etc.) // ^ function parameter generic type name (A, B, C etc.)
// ^ call argument(like A, *B, &mut C etc) // ^ call argument(like A, *B, &mut C etc)
// ^ function parameter marker type (T, Ref<T> or Mut<T>) // ^ function parameter marker type (A, Ref<B> or Mut<C>)
// ^ function parameter actual type (T, &T or &mut T) // ^ function parameter actual type (A, &B or &mut C)
// ^ argument let statement // ^ argument let statement
impl< impl<
@ -117,7 +117,7 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), ()> for FN { > RegisterNativeFunction<($($mark,)*), ()> for FN {
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() } #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
@ -145,7 +145,7 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN { > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN {
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() } #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
@ -173,7 +173,7 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<($($mark,)*), RhaiResultOf<RET>> for FN { > RegisterNativeFunction<($($mark,)*), RhaiResultOf<RET>> for FN {
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() } #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {
@ -198,7 +198,7 @@ macro_rules! def_register {
RET: Variant + Clone RET: Variant + Clone
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), RhaiResultOf<RET>> for FN { > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), RhaiResultOf<RET>> for FN {
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() } #[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() } #[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() }
#[inline(always)] fn into_callable_function(self) -> CallableFunction { #[inline(always)] fn into_callable_function(self) -> CallableFunction {

View File

@ -92,18 +92,60 @@ impl FuncInfo {
/// `()` is cleared. /// `()` is cleared.
/// [`RhaiResult`][crate::RhaiResult] and [`RhaiResultOf<T>`] are expanded. /// [`RhaiResult`][crate::RhaiResult] and [`RhaiResultOf<T>`] are expanded.
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
pub fn format_return_type(typ: &str) -> std::borrow::Cow<str> { pub fn format_type(typ: &str, is_return_type: bool) -> std::borrow::Cow<str> {
const RHAI_RESULT_TYPE: &str = "RhaiResult"; const RHAI_RESULT_TYPE: &str = "RhaiResult";
const RHAI_RESULT_TYPE_EXPAND: &str = "Result<Dynamic, Box<EvalAltResult>>"; const RHAI_RESULT_TYPE_EXPAND: &str = "Result<Dynamic, Box<EvalAltResult>>";
const RHAI_RESULT_OF_TYPE: &str = "RhaiResultOf<"; const RHAI_RESULT_OF_TYPE: &str = "RhaiResultOf<";
const RHAI_RESULT_OF_TYPE_EXPAND: &str = "Result<{}, Box<EvalAltResult>>"; const RHAI_RESULT_OF_TYPE_EXPAND: &str = "Result<{}, Box<EvalAltResult>>";
const RHAI_RANGE: &str = "ExclusiveRange";
const RHAI_RANGE_TYPE: &str = "Range<";
const RHAI_RANGE_EXPAND: &str = "Range<{}>";
const RHAI_INCLUSIVE_RANGE: &str = "InclusiveRange";
const RHAI_INCLUSIVE_RANGE_TYPE: &str = "RangeInclusive<";
const RHAI_INCLUSIVE_RANGE_EXPAND: &str = "RangeInclusive<{}>";
let typ = typ.trim();
if typ.starts_with("rhai::") {
return Self::format_type(&typ[6..], is_return_type);
} else if typ.starts_with("&mut ") {
let x = &typ[5..];
let r = Self::format_type(x, false);
return if r == x {
typ.into()
} else {
format!("&mut {}", r).into()
};
}
match typ { match typ {
"" | "()" => "".into(), "" | "()" if is_return_type => "".into(),
"INT" => std::any::type_name::<crate::INT>().into(),
#[cfg(not(feature = "no_float"))]
"FLOAT" => std::any::type_name::<crate::FLOAT>().into(),
RHAI_RANGE => RHAI_RANGE_EXPAND
.replace("{}", std::any::type_name::<crate::INT>())
.into(),
RHAI_INCLUSIVE_RANGE => RHAI_INCLUSIVE_RANGE_EXPAND
.replace("{}", std::any::type_name::<crate::INT>())
.into(),
RHAI_RESULT_TYPE => RHAI_RESULT_TYPE_EXPAND.into(), RHAI_RESULT_TYPE => RHAI_RESULT_TYPE_EXPAND.into(),
ty if ty.starts_with(RHAI_RANGE_TYPE) && ty.ends_with('>') => {
let inner = &ty[RHAI_RANGE_TYPE.len()..ty.len() - 1];
RHAI_RANGE_EXPAND
.replace("{}", Self::format_type(inner, false).trim())
.into()
}
ty if ty.starts_with(RHAI_INCLUSIVE_RANGE_TYPE) && ty.ends_with('>') => {
let inner = &ty[RHAI_INCLUSIVE_RANGE_TYPE.len()..ty.len() - 1];
RHAI_INCLUSIVE_RANGE_EXPAND
.replace("{}", Self::format_type(inner, false).trim())
.into()
}
ty if ty.starts_with(RHAI_RESULT_OF_TYPE) && ty.ends_with('>') => { ty if ty.starts_with(RHAI_RESULT_OF_TYPE) && ty.ends_with('>') => {
let inner = &ty[RHAI_RESULT_OF_TYPE.len()..ty.len() - 1];
RHAI_RESULT_OF_TYPE_EXPAND RHAI_RESULT_OF_TYPE_EXPAND
.replace("{}", ty[RHAI_RESULT_OF_TYPE.len()..ty.len() - 1].trim()) .replace("{}", Self::format_type(inner, false).trim())
.into() .into()
} }
ty => ty.into(), ty => ty.into(),
@ -116,14 +158,27 @@ impl FuncInfo {
pub fn gen_signature(&self) -> String { pub fn gen_signature(&self) -> String {
let mut sig = format!("{}(", self.metadata.name); let mut sig = format!("{}(", self.metadata.name);
let return_type = Self::format_return_type(&self.metadata.return_type); let return_type = Self::format_type(&self.metadata.return_type, true);
if !self.metadata.params_info.is_empty() { if !self.metadata.params_info.is_empty() {
let params: StaticVec<_> = self let params: StaticVec<_> = self
.metadata .metadata
.params_info .params_info
.iter() .iter()
.map(|s| s.as_str()) .map(|s| {
let mut seg = s.splitn(2, ':');
let name = match seg.next().unwrap().trim() {
"" => "_",
s => s,
};
let result: std::borrow::Cow<str> = match seg.next() {
Some(typ) => {
format!("{}: {}", name, FuncInfo::format_type(typ, false)).into()
}
None => name.into(),
};
result
})
.collect(); .collect();
sig.push_str(&params.join(", ")); sig.push_str(&params.join(", "));
sig.push(')'); sig.push(')');

View File

@ -481,6 +481,12 @@ def_package! {
// Register string iterator // Register string iterator
lib.set_iterator::<CharsStream>(); lib.set_iterator::<CharsStream>();
#[cfg(feature = "metadata")]
let (range_type, range_inclusive_type) = (
format!("range: Range<{}>", std::any::type_name::<INT>()),
format!("range: RangeInclusive<{}>", std::any::type_name::<INT>()),
);
let _hash = lib.set_native_fn("chars", |string, range: ExclusiveRange| { let _hash = lib.set_native_fn("chars", |string, range: ExclusiveRange| {
let from = INT::max(range.start, 0); let from = INT::max(range.start, 0);
let to = INT::max(range.end, from); let to = INT::max(range.end, from);
@ -489,7 +495,7 @@ def_package! {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
lib.update_fn_metadata_with_comments( lib.update_fn_metadata_with_comments(
_hash, _hash,
["string: &str", "range: Range<INT>", "Iterator<Item=char>"], ["string: &str", &range_type, "Iterator<Item=char>"],
[ [
"/// Return an iterator over an exclusive range of characters in the string.", "/// Return an iterator over an exclusive range of characters in the string.",
"///", "///",
@ -511,7 +517,7 @@ def_package! {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
lib.update_fn_metadata_with_comments( lib.update_fn_metadata_with_comments(
_hash, _hash,
["string: &str", "range: RangeInclusive<INT>", "Iterator<Item=char>"], ["string: &str", &range_inclusive_type, "Iterator<Item=char>"],
[ [
"/// Return an iterator over an inclusive range of characters in the string.", "/// Return an iterator over an inclusive range of characters in the string.",
"///", "///",
@ -621,7 +627,7 @@ def_package! {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
lib.update_fn_metadata_with_comments( lib.update_fn_metadata_with_comments(
_hash, _hash,
["value: INT", "range: Range<INT>", "Iterator<Item=bool>"], ["value: INT", &range_type, "Iterator<Item=bool>"],
[ [
"/// Return an iterator over an exclusive range of bits in the number.", "/// Return an iterator over an exclusive range of bits in the number.",
"///", "///",
@ -645,7 +651,7 @@ def_package! {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
lib.update_fn_metadata_with_comments( lib.update_fn_metadata_with_comments(
_hash, _hash,
["value: INT", "range: RangeInclusive<INT>", "Iterator<Item=bool>"], ["value: INT", &range_inclusive_type, "Iterator<Item=bool>"],
[ [
"/// Return an iterator over an inclusive range of bits in the number.", "/// Return an iterator over an inclusive range of bits in the number.",
"///", "///",
@ -733,7 +739,7 @@ def_package! {
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
lib.update_fn_metadata_with_comments( lib.update_fn_metadata_with_comments(
_hash, _hash,
["value: &mut INT", "range: Range<INT>", "Iterator<Item=bool>"], ["value: &mut INT", "Iterator<Item=bool>"],
[ [
"/// Return an iterator over all the bits in the number.", "/// Return an iterator over all the bits in the number.",
"///", "///",

View File

@ -7,7 +7,7 @@ use crate::{calc_fn_hash, Engine, AST};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{cmp::Ordering, collections::BTreeMap, iter::empty}; use std::{borrow::Cow, cmp::Ordering, collections::BTreeMap, iter::empty};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -54,7 +54,7 @@ struct FnParam<'a> {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<&'a str>, pub name: Option<&'a str>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")] #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub typ: Option<&'a str>, pub typ: Option<Cow<'a, str>>,
} }
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
@ -125,12 +125,12 @@ impl<'a> From<&'a FuncInfo> for FnMetadata<'a> {
"_" => None, "_" => None,
s => Some(s), s => Some(s),
}; };
let typ = seg.next().map(&str::trim); let typ = seg.next().map(|s| FuncInfo::format_type(s, false));
FnParam { name, typ } FnParam { name, typ }
}) })
.collect(), .collect(),
_dummy: None, _dummy: None,
return_type: FuncInfo::format_return_type(&info.metadata.return_type).into_owned(), return_type: FuncInfo::format_type(&info.metadata.return_type, true).into_owned(),
signature: info.gen_signature(), signature: info.gen_signature(),
doc_comments: if info.func.is_script() { doc_comments: if info.func.is_script() {
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]

View File

@ -546,44 +546,66 @@ impl Hash for Dynamic {
/// Map the name of a standard type into a friendly form. /// Map the name of a standard type into a friendly form.
#[inline] #[inline]
#[must_use] #[must_use]
pub(crate) fn map_std_type_name(name: &str) -> &str { pub(crate) fn map_std_type_name(name: &str, shorthands: bool) -> &str {
let name = name.trim();
if name.starts_with("rhai::") {
return map_std_type_name(&name[6..], shorthands);
}
if name == type_name::<String>() { if name == type_name::<String>() {
return "string"; return if shorthands { "string" } else { "String" };
} }
if name == type_name::<ImmutableString>() { if name == type_name::<ImmutableString>() {
return "string"; return if shorthands {
"string"
} else {
"ImmutableString"
};
} }
if name == type_name::<&str>() { if name == type_name::<&str>() {
return "string"; return if shorthands { "string" } else { "&str" };
}
if name == type_name::<FnPtr>() {
return "Fn";
} }
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
if name == type_name::<rust_decimal::Decimal>() { if name == type_name::<rust_decimal::Decimal>() {
return "decimal"; return if shorthands { "decimal" } else { "Decimal" };
}
if name == type_name::<FnPtr>() {
return if shorthands { "Fn" } else { "FnPtr" };
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if name == type_name::<crate::Array>() { if name == type_name::<crate::Array>() {
return "array"; return if shorthands { "array" } else { "Array" };
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if name == type_name::<crate::Blob>() { if name == type_name::<crate::Blob>() {
return "blob"; return if shorthands { "blob" } else { "Blob" };
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if name == type_name::<crate::Map>() { if name == type_name::<crate::Map>() {
return "map"; return if shorthands { "map" } else { "Map" };
} }
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
if name == type_name::<Instant>() { if name == type_name::<Instant>() {
return "timestamp"; return if shorthands { "timestamp" } else { "Instant" };
} }
if name == type_name::<ExclusiveRange>() { if name == type_name::<ExclusiveRange>() || name == "ExclusiveRange" {
return "range"; return if shorthands {
"range"
} else if cfg!(feature = "only_i32") {
"Range<i32>"
} else {
"Range<i64>"
};
} }
if name == type_name::<InclusiveRange>() { if name == type_name::<InclusiveRange>() || name == "InclusiveRange" {
return "range="; return if shorthands {
"range="
} else if cfg!(feature = "only_i32") {
"RangeInclusive<i32>"
} else {
"RangeInclusive<i64>"
};
} }
name name