Skip to content

Commit 1fec6a5

Browse files
authored
Enable nullable annotations in ConversionWrappers (#1446)
* Enable nullable annotations in ConversionWrappers * Replace [NotNone] with ArgumentNullException
1 parent 9636e35 commit 1fec6a5

1 file changed

Lines changed: 75 additions & 46 deletions

File tree

Src/IronPython/Runtime/ConversionWrappers.cs

Lines changed: 75 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
6+
57
using System;
68
using System.Buffers;
79
using System.Collections;
810
using System.Collections.Generic;
11+
using System.Diagnostics.CodeAnalysis;
912
using System.Numerics;
1013

1114
namespace IronPython.Runtime {
1215

1316
public class ListGenericWrapper<T> : IList<T> {
14-
private readonly IList<object> _value;
17+
private readonly IList<object?> _value;
1518
// PEP 237: int/long unification (GH #52)
1619
private static readonly bool IsBigIntWrapper = typeof(T) == typeof(BigInteger) || typeof(T) == typeof(BigInteger?);
1720

18-
public ListGenericWrapper(IList<object> value) { _value = value; }
21+
public ListGenericWrapper(IList<object?> value) {
22+
_value = value ?? throw new ArgumentNullException(nameof(value));
23+
}
1924

2025
#region IList<T> Members
2126

@@ -40,11 +45,17 @@ public void RemoveAt(int index) {
4045

4146
public T this[int index] {
4247
get {
43-
object item = _value[index];
48+
object? item = _value[index];
4449
if (IsBigIntWrapper && item is int i32) {
4550
item = new BigInteger(i32);
4651
}
47-
return (T)item;
52+
try {
53+
return (T)item!;
54+
} catch (NullReferenceException nex) {
55+
throw new InvalidCastException(string.Format("Error in ListGenericWrapper.this[]. Could not cast: from null to {0}", typeof(T).ToString()), nex);
56+
} catch (InvalidCastException iex) {
57+
throw new InvalidCastException(string.Format("Error in ListGenericWrapper.this[]. Could not cast: from {1} to {0}", typeof(T).ToString(), item!.GetType().ToString()), iex);
58+
}
4859
}
4960

5061
set => _value[index] = value;
@@ -112,61 +123,65 @@ IEnumerator IEnumerable.GetEnumerator() {
112123
#endregion
113124
}
114125

126+
#if NETCOREAPP3_1 // In netcoreapp3.1, IDictionary<K, V> has constraint where K : notnull
127+
#nullable disable warnings
128+
#endif
129+
115130
public class DictionaryGenericWrapper<K, V> : IDictionary<K, V> {
116-
private readonly IDictionary<object, object> self;
131+
private readonly IDictionary<object?, object?> self;
117132
// PEP 237: int/long unification (GH #52)
118133
private static readonly bool IsBigIntWrapperK = typeof(K) == typeof(BigInteger) || typeof(K) == typeof(BigInteger?);
119134
private static readonly bool IsBigIntWrapperV = typeof(V) == typeof(BigInteger) || typeof(V) == typeof(BigInteger?);
120135

121-
public DictionaryGenericWrapper(IDictionary<object, object> self) {
122-
this.self = self;
136+
public DictionaryGenericWrapper(IDictionary<object?, object?> self) {
137+
this.self = self ?? throw new ArgumentNullException(nameof(self));
123138
}
124139

125140
#region IDictionary<K,V> Members
126141

127142
public void Add(K key, V value) {
128-
object okey = key;
129-
if (IsValidKey32(key, out object i32) && self.ContainsKey(i32)) {
143+
object? okey = key;
144+
if (IsValidKey32(key, out object? i32) && self.ContainsKey(i32)) {
130145
okey = i32;
131146
}
132147
self.Add(okey, value);
133148
}
134149

135150
public bool ContainsKey(K key) {
136-
return self.ContainsKey(key) || (IsValidKey32(key, out object i32) && self.ContainsKey(i32));
151+
return self.ContainsKey(key) || (IsValidKey32(key, out object? i32) && self.ContainsKey(i32));
137152
}
138153

139154
public ICollection<K> Keys {
140155
get {
141156
List<K> res = new List<K>(Count);
142-
foreach (object o in self.Keys) {
157+
foreach (object? o in self.Keys) {
143158
res.Add(CastKey(o));
144159
}
145160
return res;
146161
}
147162
}
148163

149164
public bool Remove(K key) {
150-
return self.Remove(key) || (IsValidKey32(key, out object i32) && self.Remove(i32));
165+
return self.Remove(key) || (IsValidKey32(key, out object? i32) && self.Remove(i32));
151166
}
152167

153168
public bool TryGetValue(K key, out V value) {
154-
if (self.TryGetValue(key, out object outValue)) {
169+
if (self.TryGetValue(key, out object? outValue)) {
155170
value = CastValue(outValue);
156171
return true;
157172
}
158-
if (IsValidKey32(key, out object i32) && self.TryGetValue(i32, out object outValue2)) {
173+
if (IsValidKey32(key, out object? i32) && self.TryGetValue(i32, out object? outValue2)) {
159174
value = CastValue(outValue2);
160175
return true;
161176
}
162-
value = default;
177+
value = default(V)!;
163178
return false;
164179
}
165180

166181
public ICollection<V> Values {
167182
get {
168183
List<V> res = new List<V>();
169-
foreach (object o in self.Values) {
184+
foreach (object? o in self.Values) {
170185
res.Add(CastValue(o));
171186
}
172187
return res;
@@ -191,23 +206,23 @@ public V this[K key] {
191206
#region ICollection<KeyValuePair<K,V>> Members
192207

193208
public void Add(KeyValuePair<K, V> item) {
194-
object key = item.Key;
195-
if (IsValidKey32(item.Key, out object i32) && self.ContainsKey(i32)) {
209+
object? key = item.Key;
210+
if (IsValidKey32(item.Key, out object? i32) && self.ContainsKey(i32)) {
196211
key = i32;
197212
}
198-
self.Add(new KeyValuePair<object, object>(key, item.Value));
213+
self.Add(new KeyValuePair<object?, object?>(key, item.Value));
199214
}
200215

201216
public void Clear() {
202217
self.Clear();
203218
}
204219

205220
public bool Contains(KeyValuePair<K, V> item) {
206-
object key = item.Key;
207-
if (IsValidKey32(item.Key, out object i32) && self.ContainsKey(i32)) {
221+
object? key = item.Key;
222+
if (IsValidKey32(item.Key, out object? i32) && self.ContainsKey(i32)) {
208223
key = i32;
209224
}
210-
return self.Contains(new KeyValuePair<object, object>(key, item.Value));
225+
return self.Contains(new KeyValuePair<object?, object?>(key, item.Value));
211226
}
212227

213228
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) {
@@ -225,19 +240,19 @@ public bool IsReadOnly {
225240
}
226241

227242
public bool Remove(KeyValuePair<K, V> item) {
228-
object key = item.Key;
229-
if (IsValidKey32(item.Key, out object i32) && self.ContainsKey(i32)) {
243+
object? key = item.Key;
244+
if (IsValidKey32(item.Key, out object? i32) && self.ContainsKey(i32)) {
230245
key = i32;
231246
}
232-
return self.Remove(new KeyValuePair<object, object>(key, item.Value));
247+
return self.Remove(new KeyValuePair<object?, object?>(key, item.Value));
233248
}
234249

235250
#endregion
236251

237252
#region IEnumerable<KeyValuePair<K,V>> Members
238253

239254
public IEnumerator<KeyValuePair<K, V>> GetEnumerator() {
240-
foreach (KeyValuePair<object, object> kv in self) {
255+
foreach (KeyValuePair<object?, object?> kv in self) {
241256
yield return new KeyValuePair<K, V>(CastKey(kv.Key), CastValue(kv.Value));
242257
}
243258
}
@@ -252,21 +267,33 @@ IEnumerator IEnumerable.GetEnumerator() {
252267

253268
#endregion
254269

255-
private static K CastKey(object key) {
270+
private static K CastKey(object? key) {
256271
if (IsBigIntWrapperK && key is int i32) {
257272
key = new BigInteger(i32);
258273
}
259-
return (K)key;
274+
try {
275+
return (K)key!;
276+
} catch (NullReferenceException nex) {
277+
throw new InvalidCastException(string.Format("Error in DictionaryGenericWrapper.CastKey. Could not cast: from null to {0}", typeof(K).ToString()), nex);
278+
} catch (InvalidCastException iex) {
279+
throw new InvalidCastException(string.Format("Error in DictionaryGenericWrapper.CastKey. Could not cast: from {1} to {0}", typeof(K).ToString(), key!.GetType().ToString()), iex);
280+
}
260281
}
261282

262-
private static V CastValue(object val) {
283+
private static V CastValue(object? val) {
263284
if (IsBigIntWrapperV && val is int i32) {
264285
val = new BigInteger(i32);
265286
}
266-
return (V)val;
287+
try {
288+
return (V)val!;
289+
} catch (NullReferenceException nex) {
290+
throw new InvalidCastException(string.Format("Error in DictionaryGenericWrapper.CastValue. Could not cast: from null to {0}", typeof(V).ToString()), nex);
291+
} catch (InvalidCastException iex) {
292+
throw new InvalidCastException(string.Format("Error in DictionaryGenericWrapper.CastValue. Could not cast: from {1} to {0}", typeof(V).ToString(), val!.GetType().ToString()), iex);
293+
}
267294
}
268295

269-
private static bool IsValidKey32(K key, out object key32) {
296+
private static bool IsValidKey32(K key, [NotNullWhen(true)] out object? key32) {
270297
if (IsBigIntWrapperK && key is BigInteger bi && bi >= int.MinValue && bi <= int.MaxValue) {
271298
key32 = (int)bi;
272299
return true;
@@ -276,26 +303,33 @@ private static bool IsValidKey32(K key, out object key32) {
276303
}
277304
}
278305

306+
#if NETCOREAPP3_1
307+
#nullable enable
308+
#endif
309+
279310
public class IEnumeratorOfTWrapper<T> : IEnumerator<T> {
280311
private readonly IEnumerator enumerable;
281312
// PEP 237: int/long unification (GH #52)
282313
private static readonly bool IsBigIntWrapper = typeof(T) == typeof(BigInteger) || typeof(T) == typeof(BigInteger?);
283314

284315
public IEnumeratorOfTWrapper(IEnumerator enumerable) {
285-
this.enumerable = enumerable;
316+
this.enumerable = enumerable ?? throw new ArgumentNullException(nameof(enumerable));
286317
}
287318

288319
#region IEnumerator<T> Members
320+
289321
public T Current {
290322
get {
323+
object? current = enumerable.Current;
324+
if (IsBigIntWrapper && current is int i32) {
325+
current = new BigInteger(i32);
326+
}
291327
try {
292-
object current = enumerable.Current;
293-
if (IsBigIntWrapper && current is int i32) {
294-
current = new BigInteger(i32);
295-
}
296-
return (T)current;
297-
} catch (System.InvalidCastException iex) {
298-
throw new System.InvalidCastException(string.Format("Error in IEnumeratorOfTWrapper.Current. Could not cast: from {1} to {0}", typeof(T).ToString(), enumerable.Current.GetType().ToString()), iex);
328+
return (T)current!;
329+
} catch (NullReferenceException nex) {
330+
throw new InvalidCastException(string.Format("Error in IEnumeratorOfTWrapper.Current. Could not cast: from null to {0}", typeof(T).ToString()), nex);
331+
} catch (InvalidCastException iex) {
332+
throw new InvalidCastException(string.Format("Error in IEnumeratorOfTWrapper.Current. Could not cast: from {1} to {0}", typeof(T).ToString(), current!.GetType().ToString()), iex);
299333
}
300334
}
301335
}
@@ -311,7 +345,7 @@ public void Dispose() {
311345

312346
#region IEnumerator Members
313347

314-
object IEnumerator.Current {
348+
object? IEnumerator.Current {
315349
get { return enumerable.Current; }
316350
}
317351

@@ -326,12 +360,11 @@ public void Reset() {
326360
#endregion
327361
}
328362

329-
[PythonType("enumerable_wrapper")]
330363
public class IEnumerableOfTWrapper<T> : IEnumerable<T>, IEnumerable {
331364
private readonly IEnumerable enumerable;
332365

333366
public IEnumerableOfTWrapper(IEnumerable enumerable) {
334-
this.enumerable = enumerable;
367+
this.enumerable = enumerable ?? throw new ArgumentNullException(nameof(enumerable));
335368
}
336369

337370
#region IEnumerable<T> Members
@@ -351,8 +384,6 @@ IEnumerator IEnumerable.GetEnumerator() {
351384
#endregion
352385
}
353386

354-
#nullable enable
355-
356387
public sealed class MemoryBufferWrapper : IPythonBuffer {
357388
private readonly ReadOnlyMemory<byte> _rom;
358389
private readonly Memory<byte>? _memory;
@@ -425,6 +456,4 @@ public IPythonBuffer GetBuffer(BufferFlags flags) {
425456
return new MemoryBufferWrapper(_rom, flags);
426457
}
427458
}
428-
429-
#nullable restore
430459
}

0 commit comments

Comments
 (0)