回答編集履歴

2

std::opsで定義されているMulとNegを使うように変更しました

2021/08/18 23:21

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- ご質問のコードに、省略されている`Neg`トレイトなど適当に追加してみましたが、エラーは再現できませんでした。そこで、質問の追記依頼の欄にあるコメントを頼りに、以下のようにコードを変更したところ、それらしいエラーが出ました。
5
+ ご質問のコードに、省略されている`Decimal`構造体や`use`文を追加してみましたが、エラーは再現できませんでした。そこで、質問の追記依頼の欄にあるコメントを頼りに、以下のようにコードを変更したところ、それらしいエラーが出ました。
6
6
 
7
7
 
8
8
 
@@ -26,6 +26,8 @@
26
26
 
27
27
 
28
28
 
29
+ use std::ops::{Mul, Neg};
30
+
29
31
  use num_traits::{AsPrimitive, ToPrimitive, Unsigned, WrappingMul};
30
32
 
31
33
 
@@ -34,32 +36,6 @@
34
36
 
35
37
 
36
38
 
37
- trait Neg {
38
-
39
- type Output;
40
-
41
- }
42
-
43
-
44
-
45
- impl Neg for i32 {
46
-
47
- type Output = Self;
48
-
49
- }
50
-
51
-
52
-
53
- trait Mul<T> {
54
-
55
- type Output;
56
-
57
- fn mul(self, rhs: T) -> Self::Output;
58
-
59
- }
60
-
61
-
62
-
63
39
  impl Mul<i32> for Decimal<i32> {
64
40
 
65
41
  type Output = Self;
@@ -196,6 +172,8 @@
196
172
 
197
173
  ```rust
198
174
 
175
+ use std::ops::{Mul, Neg};
176
+
199
177
  use num_traits::{AsPrimitive, Signed, ToPrimitive, Unsigned, WrappingMul};
200
178
 
201
179
 
@@ -206,32 +184,6 @@
206
184
 
207
185
 
208
186
 
209
- trait Neg {
210
-
211
- type Output;
212
-
213
- }
214
-
215
-
216
-
217
- impl Neg for i32 {
218
-
219
- type Output = Self;
220
-
221
- }
222
-
223
-
224
-
225
- trait Mul<T> {
226
-
227
- type Output;
228
-
229
- fn mul(self, rhs: T) -> Self::Output;
230
-
231
- }
232
-
233
-
234
-
235
187
  impl Mul<i32> for SignedDecimal<i32> {
236
188
 
237
189
  type Output = Self;

1

わかりやすさのためにコードブロック内の行の順番を変えました

2021/08/18 23:21

投稿

tatsuya6502
tatsuya6502

スコア2046

test CHANGED
@@ -34,6 +34,22 @@
34
34
 
35
35
 
36
36
 
37
+ trait Neg {
38
+
39
+ type Output;
40
+
41
+ }
42
+
43
+
44
+
45
+ impl Neg for i32 {
46
+
47
+ type Output = Self;
48
+
49
+ }
50
+
51
+
52
+
37
53
  trait Mul<T> {
38
54
 
39
55
  type Output;
@@ -58,6 +74,138 @@
58
74
 
59
75
 
60
76
 
77
+ impl<S, T> Mul<S> for Decimal<T>
78
+
79
+ where
80
+
81
+ S: 'static + Neg<Output = S> + Copy,
82
+
83
+ T: AsPrimitive<S> + WrappingMul + Unsigned,
84
+
85
+ {
86
+
87
+ type Output = Self;
88
+
89
+ fn mul(self, rhs: S) -> Self::Output {
90
+
91
+ // コンパイルエラーになるためコメントアウト
92
+
93
+ // error[E0308]: mismatched types:
94
+
95
+ // expected type parameter `S`, found type `{integer}`
96
+
97
+ // if rhs < 0 {
98
+
99
+ // // error[E0369]: cannot multiply `Decimal<T>` by `u32`
100
+
101
+ // // error[E0605]: non-primitive cast: `S` as `u32`
102
+
103
+ // -(self * rhs as u32)
104
+
105
+ // } else {
106
+
107
+ // self * rhs as u32
108
+
109
+ // }
110
+
111
+ todo!()
112
+
113
+ }
114
+
115
+ }
116
+
117
+ ```
118
+
119
+
120
+
121
+ また、エラーメッセージは以下のとおりです。
122
+
123
+
124
+
125
+ ```console
126
+
127
+ error[E0119]: conflicting implementations of trait `Mul<i32>` for type `Decimal<i32>`
128
+
129
+ |
130
+
131
+ 18 | impl Mul<i32> for Decimal<i32> {
132
+
133
+ | ------------------------------ first implementation here
134
+
135
+ ...
136
+
137
+ 33 | / impl<S, T> Mul<S> for Decimal<T>
138
+
139
+ 34 | | where
140
+
141
+ 35 | | S: 'static + Neg<Output = S> + PartialOrd + Copy,
142
+
143
+ 36 | | T: AsPrimitive<S> + WrappingMul + Unsigned,
144
+
145
+ ... |
146
+
147
+ 51 | | }
148
+
149
+ 52 | | }
150
+
151
+ | |_^ conflicting implementation for `Decimal<i32>`
152
+
153
+ |
154
+
155
+ = note: upstream crates may add a new impl of trait `num_traits::Unsigned` for type `i32` in future versions
156
+
157
+ ```
158
+
159
+
160
+
161
+ ## 質問の回答
162
+
163
+
164
+
165
+ 質問の追記依頼の欄のコメントより
166
+
167
+
168
+
169
+ > `Unsiged`は`i32`は実装することはなく、`u32`は`Signed`を実装することがないことが人間にはわかりますが、コンパイラはわからないので、型境界に`Unsigned`をつけた型`T`についての`Mul<T>`の実装と、`i32`についての`Mul<i32>`の実装がコンフリクトするんです。
170
+
171
+ > これをうまくコンフリクトさせずに分けて実装できる、択一型(e.g. `Unsigned`を実装したら`Signed`は実装できないし、逆も成り立つ)みたいな型境界はないんですかね。
172
+
173
+
174
+
175
+ 現時点のRustでは択一型を定義したり、否定のようなトレイト境界をつけることはできないと思います。そのため`Decimal<i32>`と`Decimal<T: Unsigned>`がコンフリクトするのは避けられません。
176
+
177
+
178
+
179
+ 回避方法ですが、`Decimal<T>`を以下の2つの型に分けるのはどうでしょうか?
180
+
181
+
182
+
183
+ ```rust
184
+
185
+ struct UnsignedDecimal<T: Unsigned>(T);
186
+
187
+ struct SignedDecimal<T: Signed>(T);
188
+
189
+ ```
190
+
191
+
192
+
193
+ これを用いると以下のようなコードになり、コンフリクトを回避できます。
194
+
195
+
196
+
197
+ ```rust
198
+
199
+ use num_traits::{AsPrimitive, Signed, ToPrimitive, Unsigned, WrappingMul};
200
+
201
+
202
+
203
+ struct UnsignedDecimal<T: Unsigned>(T);
204
+
205
+ struct SignedDecimal<T: Signed>(T);
206
+
207
+
208
+
61
209
  trait Neg {
62
210
 
63
211
  type Output;
@@ -74,7 +222,31 @@
74
222
 
75
223
 
76
224
 
225
+ trait Mul<T> {
226
+
227
+ type Output;
228
+
229
+ fn mul(self, rhs: T) -> Self::Output;
230
+
231
+ }
232
+
233
+
234
+
235
+ impl Mul<i32> for SignedDecimal<i32> {
236
+
237
+ type Output = Self;
238
+
239
+ fn mul(self, rhs: i32) -> Self::Output {
240
+
241
+ SignedDecimal(self.0.wrapping_mul(rhs.to_i32().unwrap()))
242
+
243
+ }
244
+
245
+ }
246
+
247
+
248
+
77
- impl<S, T> Mul<S> for Decimal<T>
249
+ impl<S, T> Mul<S> for UnsignedDecimal<T>
78
250
 
79
251
  where
80
252
 
@@ -88,26 +260,6 @@
88
260
 
89
261
  fn mul(self, rhs: S) -> Self::Output {
90
262
 
91
- // コンパイルエラーになるためコメントアウト
92
-
93
- // error[E0308]: mismatched types:
94
-
95
- // expected type parameter `S`, found type `{integer}`
96
-
97
- // if rhs < 0 {
98
-
99
- // // error[E0369]: cannot multiply `Decimal<T>` by `u32`
100
-
101
- // // error[E0605]: non-primitive cast: `S` as `u32`
102
-
103
- // -(self * rhs as u32)
104
-
105
- // } else {
106
-
107
- // self * rhs as u32
108
-
109
- // }
110
-
111
263
  todo!()
112
264
 
113
265
  }
@@ -115,157 +267,3 @@
115
267
  }
116
268
 
117
269
  ```
118
-
119
-
120
-
121
- また、エラーメッセージは以下のとおりです。
122
-
123
-
124
-
125
- ```console
126
-
127
- error[E0119]: conflicting implementations of trait `Mul<i32>` for type `Decimal<i32>`
128
-
129
- |
130
-
131
- 18 | impl Mul<i32> for Decimal<i32> {
132
-
133
- | ------------------------------ first implementation here
134
-
135
- ...
136
-
137
- 33 | / impl<S, T> Mul<S> for Decimal<T>
138
-
139
- 34 | | where
140
-
141
- 35 | | S: 'static + Neg<Output = S> + PartialOrd + Copy,
142
-
143
- 36 | | T: AsPrimitive<S> + WrappingMul + Unsigned,
144
-
145
- ... |
146
-
147
- 51 | | }
148
-
149
- 52 | | }
150
-
151
- | |_^ conflicting implementation for `Decimal<i32>`
152
-
153
- |
154
-
155
- = note: upstream crates may add a new impl of trait `num_traits::Unsigned` for type `i32` in future versions
156
-
157
- ```
158
-
159
-
160
-
161
- ## 質問の回答
162
-
163
-
164
-
165
- 質問の追記依頼の欄のコメントより
166
-
167
-
168
-
169
- > `Unsiged`は`i32`は実装することはなく、`u32`は`Signed`を実装することがないことが人間にはわかりますが、コンパイラはわからないので、型境界に`Unsigned`をつけた型`T`についての`Mul<T>`の実装と、`i32`についての`Mul<i32>`の実装がコンフリクトするんです。
170
-
171
- > これをうまくコンフリクトさせずに分けて実装できる、択一型(e.g. `Unsigned`を実装したら`Signed`は実装できないし、逆も成り立つ)みたいな型境界はないんですかね。
172
-
173
-
174
-
175
- 現時点のRustでは択一型を定義したり、否定のようなトレイト境界をつけることはできないと思います。そのため`Decimal<i32>`と`Decimal<T: Unsigned>`がコンフリクトするのは避けられません。
176
-
177
-
178
-
179
- 回避方法ですが、`Decimal<T>`を以下の2つの型に分けるのはどうでしょうか?
180
-
181
-
182
-
183
- ```rust
184
-
185
- struct UnsignedDecimal<T: Unsigned>(T);
186
-
187
- struct SignedDecimal<T: Signed>(T);
188
-
189
- ```
190
-
191
-
192
-
193
- これを用いると以下のようなコードになり、コンフリクトを回避できます。
194
-
195
-
196
-
197
- ```rust
198
-
199
- use num_traits::{AsPrimitive, Signed, ToPrimitive, Unsigned, WrappingMul};
200
-
201
-
202
-
203
- struct UnsignedDecimal<T: Unsigned>(T);
204
-
205
-
206
-
207
- struct SignedDecimal<T: Signed>(T);
208
-
209
-
210
-
211
- trait Mul<T> {
212
-
213
- type Output;
214
-
215
- fn mul(self, rhs: T) -> Self::Output;
216
-
217
- }
218
-
219
-
220
-
221
- impl Mul<i32> for SignedDecimal<i32> {
222
-
223
- type Output = Self;
224
-
225
- fn mul(self, rhs: i32) -> Self::Output {
226
-
227
- SignedDecimal(self.0.wrapping_mul(rhs.to_i32().unwrap()))
228
-
229
- }
230
-
231
- }
232
-
233
-
234
-
235
- trait Neg {
236
-
237
- type Output;
238
-
239
- }
240
-
241
-
242
-
243
- impl Neg for i32 {
244
-
245
- type Output = Self;
246
-
247
- }
248
-
249
-
250
-
251
- impl<S, T> Mul<S> for UnsignedDecimal<T>
252
-
253
- where
254
-
255
- S: 'static + Neg<Output = S> + Copy,
256
-
257
- T: AsPrimitive<S> + WrappingMul + Unsigned,
258
-
259
- {
260
-
261
- type Output = Self;
262
-
263
- fn mul(self, rhs: S) -> Self::Output {
264
-
265
- todo!()
266
-
267
- }
268
-
269
- }
270
-
271
- ```