
Size: a a a
func main() {В спеке Go указано, что присваивание x типа V к переменной типа T валидно в случае, если V и T основаны на одинаковых типах и T — не именованный тип ("x's type V and T have identical underlying types and at least one of V or T is not a defined type."). Псевдонимы типов не считются именованными типами, так что мы можем принимать в аргумент n любую кастуемую структуру.
printName(Cat{"Whiskey"})
printName(Dog{"Chappie"})
}
type Cat struct { Name string }
type Dog struct { Name string }
type named = struct { Name string }
func printName(n named) {
fmt.Println(n.Name)
}
fn f() -> i32 {
unsafe { core::hint::unreachable_unchecked() }
}
задача:/* */
. В рабочем чате коллеги предлагали и аналогичные пути решения проблемы, вроде #[cfg(some_defintely_non_existent_feature_name)]
или #[cfg(all(x, not(x)))]
. Есть, однако и более тонкие пути разрешения проблемы.fn f(_:
::core::convert::Infallible) -> i32 {
unsafe { core::hint::unreachable_unchecked() }
}
Однако, как показал Илья, эту красивую вещь можно обойти при помощи unsafe:unsafe { f(core::mem::transmute::<_, core::convert::Infallible>(())); }
transmute
проверяет, что оба типы — входной и возвращаемый — имеют один и тот же размер (из-за чего её в общем случае нельзя использовать в обобщенных контекстах), однако компилятор Rust считает, что ненаселённые типы имеют размер 0 байт — практическая полезная аппроксимация, но не совсем верная.fn f<T: Copy + Drop>() -> i32 {
unsafe { core::hint::unreachable_unchecked() }
}
Дело в том, что ни один тип в Rust не может одновременно реализовывать Drop и Copy. Вызов этой функции потребует инстанцировать T
неким типом, а его нет и быть не может. Более того, использовать transmute
для обхода не получится, поскольку для этого нужно, опять-таки, конкретизировать тип f
, что невозможно сделать. Вот она, сила типов!Self
.'_
).