1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Things that fail to compile.
//!
//! Nothing to import here; this module exists for its documentation.
//! Every snippet is a `compile_fail` doctest pinned to its error code, so
//! `cargo test` fails if any of them starts compiling.
//!
//! # Adding different dimensions
//!
//! ```compile_fail,E0308
//! use danwi::prelude::*;
//!
//! let _ = 1.0.m() + 1.0.s();
//! ```
//!
//! # Converting to a unit of another dimension
//!
//! [`to`](crate::Quantity::to) requires a unit of the same dimension; the
//! same holds for [`display_as`](crate::Quantity::display_as) and
//! [`new`](crate::Quantity::new).
//!
//! ```compile_fail,E0271
//! use danwi::prelude::*;
//!
//! let _ = 5.0.V().to(mA);
//! ```
//!
//! # Assigning across dimensions
//!
//! ```compile_fail,E0308
//! use danwi::prelude::*;
//!
//! let _v: Volt = 5.0.A();
//! ```
//!
//! # Comparing a dimensioned quantity to a raw float
//!
//! Only dimensionless quantities (e.g. `t / 2.0.s()`) compare against bare
//! scalars.
//!
//! ```compile_fail,E0277
//! use danwi::prelude::*;
//!
//! let _ = 5.0.V() == 5.0;
//! ```
//!
//! # Non-float scalars
//!
//! [`Scalar`](crate::Scalar) is sealed to the enabled float types.
//!
//! ```compile_fail,E0277
//! use danwi::{Quantity, dimension::Length};
//!
//! let _q: Quantity<i32, Length> = Quantity::from_base(1);
//! ```
//!
//! # Prefixing an affine unit
//!
//! "millicelsius" has no coherent meaning; [`units!`](crate::units) rejects
//! the declaration.
//!
//! ```compile_fail,E0080
//! mod bad {
//! danwi::units! {
//! weird: danwi::dimension::ThermodynamicTemperature {
//! symbol: wx,
//! offset: 100 / 1,
//! prefixes: all,
//! },
//! }
//! }
//!
//! fn main() {}
//! ```
//!
//! # Hand-written unit definitions with a broken scale
//!
//! A zero scale denominator would make every conversion inf; constructing
//! the unit's handle fails instead.
//!
//! ```compile_fail,E0080
//! use danwi::{Unit, UnitDef, dimension::Length};
//!
//! enum Bogus {}
//!
//! impl UnitDef for Bogus {
//! type Dim = Length;
//! const SCALE_NUM: i128 = 1;
//! const SCALE_DEN: i128 = 0;
//! const OFFSET_NUM: i128 = 0;
//! const OFFSET_DEN: i128 = 1;
//! const SYMBOL: &'static str = "bogus";
//! }
//!
//! const BOGUS: Unit<Bogus> = Unit::new();
//!
//! fn main() {}
//! ```
/// Mixing scalar types: `f32` and `f64` quantities never combine, checked
/// here when both features are enabled.
///
/// ```compile_fail,E0308
/// use danwi::{F32QuantityExt, F64QuantityExt};
///
/// let _ = 1.0_f32.V() + 1.0_f64.V();
/// ```
/// Mixing kinds: torque and energy share a dimension but do not add.
///
/// ```compile_fail,E0277
/// use danwi::{kind::Torque, prelude::*};
///
/// let torque = (50.0.N() * 0.4.m()).cast_kind::<Torque>();
/// let _ = torque + 5.0.J();
/// ```
///
/// Named kinds do not multiply either; erase first.
///
/// ```compile_fail,E0277
/// use danwi::{kind::Torque, prelude::*};
///
/// let torque = (50.0.N() * 0.4.m()).cast_kind::<Torque>();
/// let _ = torque / 2.0.s();
/// ```