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+
7+ using System ;
58using System . Collections . Generic ;
69using System . Diagnostics ;
10+ using System . Diagnostics . CodeAnalysis ;
711using System . Runtime . CompilerServices ;
812
913using Microsoft . Scripting ;
1519namespace IronPython . Runtime {
1620 [ PythonType ( "super" ) ]
1721 public class Super : PythonTypeSlot , ICodeFormattable {
18- private PythonType _thisClass ;
19- private object _self ;
20- private object _selfClass ;
22+ [ DisallowNull ]
23+ private PythonType ? _thisClass ; // set during __init__
24+ private object ? _self ;
25+ private object ? _selfClass ;
2126
2227 public Super ( ) {
2328 }
@@ -28,12 +33,14 @@ public void __init__() {
2833 throw PythonOps . RuntimeError ( "super(): no arguments" ) ;
2934 }
3035
31- public void __init__ ( PythonType type ) {
36+ public void __init__ ( [ NotNone ] PythonType type ) {
3237 __init__ ( type , null ) ;
3338 }
3439
35- public void __init__ ( PythonType type , object obj ) {
36- if ( obj != null ) {
40+ public void __init__ ( [ NotNone ] PythonType type , object ? obj ) {
41+ if ( type is null ) throw new ArgumentNullException ( nameof ( type ) ) ;
42+
43+ if ( obj is not null ) {
3744 if ( PythonOps . IsInstance ( obj , type ) ) {
3845 _thisClass = type ;
3946 _self = obj ;
@@ -52,22 +59,29 @@ public void __init__(PythonType type, object obj) {
5259 }
5360 }
5461
55- public PythonType __thisclass__ {
62+ public PythonType ? __thisclass__ {
5663 get { return _thisClass ; }
5764 }
5865
59- public object __self__ {
66+ public object ? __self__ {
6067 get { return _self ; }
6168 }
6269
63- public object __self_class__ {
70+ public object ? __self_class__ {
6471 get { return _selfClass ; }
6572 }
6673
67- public new object __get__ ( CodeContext /*!*/ context , object instance , object owner ) {
74+ public new object ? __get__ ( CodeContext /*!*/ context , object ? instance , object ? owner = null ) {
75+ if ( instance is null && owner is null ) {
76+ throw PythonOps . TypeError ( "__get__(None, None) is invalid" ) ;
77+ }
78+
6879 PythonType selfType = PythonType ;
6980
7081 if ( selfType == TypeCache . Super ) {
82+ if ( _thisClass is null ) {
83+ throw PythonOps . TypeError ( "super(): __init__ not called" ) ;
84+ }
7185 Super res = new Super ( ) ;
7286 res . __init__ ( _thisClass , instance ) ;
7387 return res ;
@@ -81,10 +95,10 @@ public object __self_class__ {
8195 #region Custom member access
8296
8397 [ SpecialName ]
84- public object GetCustomMember ( CodeContext context , string name ) {
98+ public object GetCustomMember ( CodeContext context , [ NotNone ] string name ) {
8599 // first find where we are in the mro...
86- object value ;
87- if ( _selfClass is PythonType mroType ) { // can be null if the user does super.__new__
100+ object ? value ;
101+ if ( _selfClass is PythonType mroType && _thisClass is not null ) { // can be null if the user does super.__new__
88102 IList < PythonType > mro = mroType . ResolutionOrder ;
89103
90104 int lookupType ;
@@ -105,7 +119,7 @@ public object GetCustomMember(CodeContext context, string name) {
105119 }
106120
107121 // if we're super on a class then we have no self.
108- object self = _self == _selfClass ? null : _self ;
122+ object ? self = _self == _selfClass ? null : _self ;
109123
110124 // then skip our class, and lookup in everything
111125 // above us until we get a hit.
@@ -127,16 +141,16 @@ public object GetCustomMember(CodeContext context, string name) {
127141 }
128142
129143 [ SpecialName ]
130- public void SetMember ( CodeContext context , string name , object value ) {
144+ public void SetMember ( CodeContext context , [ NotNone ] string name , object ? value ) {
131145 PythonType . SetMember ( context , this , name , value ) ;
132146 }
133147
134148 [ SpecialName ]
135- public void DeleteCustomMember ( CodeContext context , string name ) {
149+ public void DeleteCustomMember ( CodeContext context , [ NotNone ] string name ) {
136150 PythonType . DeleteMember ( context , this , name ) ;
137151 }
138152
139- private bool TryLookupInBase ( CodeContext context , PythonType pt , string name , object self , out object value ) {
153+ private bool TryLookupInBase ( CodeContext context , PythonType pt , string name , object ? self , [ NotNullWhen ( true ) ] out object ? value ) {
140154 // new-style class, or reflected type, lookup slot
141155 if ( pt . TryLookupSlot ( context , name , out PythonTypeSlot dts ) &&
142156 dts . TryGetValue ( context , self , DescriptorContext , out value ) ) {
@@ -146,7 +160,7 @@ private bool TryLookupInBase(CodeContext context, PythonType pt, string name, ob
146160 return false ;
147161 }
148162
149- private PythonType DescriptorContext {
163+ private PythonType ? DescriptorContext {
150164 get {
151165 if ( ! DynamicHelpers . GetPythonType ( _self ) . IsSubclassOf ( _thisClass ) ) {
152166 if ( _self == _selfClass ) // Using @classmethod
@@ -164,16 +178,16 @@ private PythonType PythonType {
164178 if ( GetType ( ) == typeof ( Super ) )
165179 return TypeCache . Super ;
166180
167- IPythonObject sdo = this as IPythonObject ;
168- Debug . Assert ( sdo != null ) ;
181+ Debug . Assert ( this is IPythonObject ) ;
182+ IPythonObject sdo = ( IPythonObject ) this ;
169183
170184 return sdo . PythonType ;
171185 }
172186 }
173187
174188 #endregion
175189
176- internal override bool TryGetValue ( CodeContext context , object instance , PythonType owner , out object value ) {
190+ internal override bool TryGetValue ( CodeContext context , object ? instance , PythonType ? owner , out object ? value ) {
177191 value = __get__ ( context , instance , owner ) ;
178192 return true ;
179193 }
0 commit comments