5656//  - a type defined in the runtime package, without the 'runtime.' prefix 
5757//  - anytype to match all possible types 
5858//  - an expression of the form T1|T2 where both T1 and T2 can be arbitrary type expressions 
59+ // 
60+ // GO VERSION RESTRICTIONS 
61+ // 
62+ // A rtype comment of this form: 
63+ // 
64+ // // +rtype go1.24 ... 
65+ // 
66+ // Will only be applied to versions of Go following version 1.24.0 
5967
6068package  main
6169
@@ -70,6 +78,7 @@ import (
7078	"log" 
7179	"os" 
7280	"path/filepath" 
81+ 	"runtime" 
7382	"sort" 
7483	"strconv" 
7584	"strings" 
@@ -78,6 +87,7 @@ import (
7887)
7988
8089const  magicCommentPrefix  =  "+rtype" 
90+ const  gover  =  "go1." 
8191
8292var  fset  =  & token.FileSet {}
8393var  checkVarTypeRules  =  []* checkVarType {}
@@ -97,6 +107,7 @@ type rtypeCmnt struct {
97107type  checkVarType  struct  {
98108	V , T  string  // V must have type T 
99109	pos   token.Pos 
110+ 	firstMinor 
100111}
101112
102113func  (c  * checkVarType ) String () string  {
@@ -111,6 +122,7 @@ type checkFieldType struct {
111122	S , F , T  string  // S.F must have type T 
112123	opt      bool 
113124	pos      token.Pos 
125+ 	firstMinor 
114126}
115127
116128func  (c  * checkFieldType ) String () string  {
@@ -122,6 +134,13 @@ type checkConstVal struct {
122134	C    string  // const C = V 
123135	V    constant.Value 
124136	pos  token.Pos 
137+ 	firstMinor 
138+ }
139+ 
140+ type  firstMinor  int 
141+ 
142+ func  (firstMinor  firstMinor ) versionOk (curminor  int ) bool  {
143+ 	return  curminor  >=  int (firstMinor )
125144}
126145
127146func  (c  * checkConstVal ) String () string  {
@@ -255,31 +274,38 @@ func process(pkg *packages.Package, rtcmnt *rtypeCmnt, cmntmap ast.CommentMap, r
255274	tinfo  :=  pkg .TypesInfo 
256275	fields  :=  strings .Split (rtcmnt .txt , " " )
257276
277+ 	firstMinor  :=  0 
278+ 
279+ 	if  strings .HasPrefix (fields [1 ], gover ) {
280+ 		firstMinor , _  =  strconv .Atoi (fields [1 ][len (gover ):])
281+ 		fields  =  fields [1 :]
282+ 	}
283+ 
258284	switch  fields [1 ] {
259285	case  "-var" :
260286		// -var V T 
261287		// requests that variable V is of type T 
262- 		addCheckVarType (fields [2 ], fields [3 ], rtcmnt .slash )
288+ 		addCheckVarType (fields [2 ], fields [3 ], rtcmnt .slash ,  firstMinor )
263289	case  "-field" :
264290		// -field S.F T 
265291		// requests that field F of type S is of type T 
266292		v  :=  strings .Split (fields [2 ], "." )
267- 		addCheckFieldType (v [0 ], v [1 ], fields [3 ], false , rtcmnt .slash )
293+ 		addCheckFieldType (v [0 ], v [1 ], fields [3 ], false , rtcmnt .slash ,  firstMinor )
268294	default :
269295		ok  :=  false 
270296		if  ident  :=  isProcVariableDecl (rtcmnt .stmt , tinfo ); ident  !=  nil  {
271297			if  len (fields ) ==  2  {
272- 				processProcVariableUses (rtcmnt .toplevel , tinfo , ident , cmntmap , rtcmnts , fields [1 ])
298+ 				processProcVariableUses (rtcmnt .toplevel , tinfo , ident , cmntmap , rtcmnts , fields [1 ],  firstMinor )
273299				ok  =  true 
274300			} else  if  len (fields ) ==  3  &&  fields [1 ] ==  "-opt"  {
275- 				processProcVariableUses (rtcmnt .toplevel , tinfo , ident , cmntmap , rtcmnts , fields [2 ])
301+ 				processProcVariableUses (rtcmnt .toplevel , tinfo , ident , cmntmap , rtcmnts , fields [2 ],  firstMinor )
276302				ok  =  true 
277303			}
278304		} else  if  ident  :=  isConstDecl (rtcmnt .toplevel , rtcmnt .node ); len (fields ) ==  2  &&  ident  !=  nil  {
279- 			addCheckConstVal (fields [1 ], constValue (tinfo .Defs [ident ]), rtcmnt .slash )
305+ 			addCheckConstVal (fields [1 ], constValue (tinfo .Defs [ident ]), rtcmnt .slash ,  firstMinor )
280306			ok  =  true 
281307		} else  if  F  :=  isStringCaseClause (rtcmnt .stmt ); F  !=  ""  &&  len (fields ) ==  4  &&  fields [1 ] ==  "-fieldof"  {
282- 			addCheckFieldType (fields [2 ], F , fields [3 ], false , rtcmnt .slash )
308+ 			addCheckFieldType (fields [2 ], F , fields [3 ], false , rtcmnt .slash ,  firstMinor )
283309			ok  =  true 
284310		}
285311		if  ! ok  {
@@ -359,7 +385,7 @@ func isStringCaseClause(stmt ast.Stmt) string {
359385// processProcVariableUses scans the body of the function declaration 'decl' 
360386// looking for uses of 'procVarIdent' which is assumed to be an identifier 
361387// for a *proc.Variable variable. 
362- func  processProcVariableUses (decl  ast.Node , tinfo  * types.Info , procVarIdent  * ast.Ident , cmntmap  ast.CommentMap , rtcmnts  []* rtypeCmnt , S  string ) {
388+ func  processProcVariableUses (decl  ast.Node , tinfo  * types.Info , procVarIdent  * ast.Ident , cmntmap  ast.CommentMap , rtcmnts  []* rtypeCmnt , S  string ,  firstMinor   int ) {
363389	if  len (S ) >  0  &&  S [0 ] ==  '*'  {
364390		S  =  S [1 :]
365391	}
@@ -435,7 +461,7 @@ func processProcVariableUses(decl ast.Node, tinfo *types.Info, procVarIdent *ast
435461				}
436462			}
437463			F , _  :=  strconv .Unquote (arg0 .Value )
438- 			addCheckFieldType (S , F , typ , opt , fncall .Pos ())
464+ 			addCheckFieldType (S , F , typ , opt , fncall .Pos (),  firstMinor )
439465			//printNode(fset, fncall) 
440466		default :
441467			pos  :=  fset .Position (n .Pos ())
@@ -454,18 +480,18 @@ func findComment(slash token.Pos, rtcmnts []*rtypeCmnt) int {
454480	return  - 1 
455481}
456482
457- func  addCheckVarType (V , T  string , pos  token.Pos ) {
458- 	checkVarTypeRules  =  append (checkVarTypeRules , & checkVarType {V , T , pos })
483+ func  addCheckVarType (V , T  string , pos  token.Pos ,  firstMinor_   int ) {
484+ 	checkVarTypeRules  =  append (checkVarTypeRules , & checkVarType {V , T , pos ,  firstMinor ( firstMinor_ ) })
459485}
460486
461- func  addCheckFieldType (S , F , T  string , opt  bool , pos  token.Pos ) {
487+ func  addCheckFieldType (S , F , T  string , opt  bool , pos  token.Pos ,  firstMinor_   int ) {
462488	if  ! strings .Contains (S , "|" ) {
463- 		checkFieldTypeRules [S ] =  append (checkFieldTypeRules [S ], & checkFieldType {S , F , T , opt , pos })
489+ 		checkFieldTypeRules [S ] =  append (checkFieldTypeRules [S ], & checkFieldType {S , F , T , opt , pos ,  firstMinor ( firstMinor_ ) })
464490	}
465491}
466492
467- func  addCheckConstVal (C  string , V  constant.Value , pos  token.Pos ) {
468- 	checkConstValRules [C ] =  append (checkConstValRules [C ], & checkConstVal {C , V , pos })
493+ func  addCheckConstVal (C  string , V  constant.Value , pos  token.Pos ,  firstMinor_   int ) {
494+ 	checkConstValRules [C ] =  append (checkConstValRules [C ], & checkConstVal {C , V , pos ,  firstMinor ( firstMinor_ ) })
469495}
470496
471497// report writes a report of all rules derived from the proc package to stdout. 
@@ -548,7 +574,7 @@ func check() {
548574	pkgmap  :=  map [string ]* packages.Package {}
549575	allok  :=  true 
550576
551- 	for  _ , rule  :=  range  checkVarTypeRules  {
577+ 	for  _ , rule  :=  range  versionOkFilter ( checkVarTypeRules )  {
552578		pos  :=  fset .Position (rule .pos )
553579		def  :=  lookupPackage (pkgmap , "runtime" ).Types .Scope ().Lookup (rule .V )
554580		if  def  ==  nil  {
@@ -569,7 +595,10 @@ func check() {
569595	}
570596	sort .Strings (Ss )
571597	for  _ , S  :=  range  Ss  {
572- 		rules  :=  checkFieldTypeRules [S ]
598+ 		rules  :=  versionOkFilter (checkFieldTypeRules [S ])
599+ 		if  len (rules ) ==  0  {
600+ 			continue 
601+ 		}
573602		pos  :=  fset .Position (rules [0 ].pos )
574603
575604		def  :=  lookupTypeDef (pkgmap , S )
@@ -617,7 +646,10 @@ func check() {
617646	}
618647	sort .Strings (Cs )
619648	for  _ , C  :=  range  Cs  {
620- 		rules  :=  checkConstValRules [C ]
649+ 		rules  :=  versionOkFilter (checkConstValRules [C ])
650+ 		if  len (rules ) ==  0  {
651+ 			continue 
652+ 		}
621653		pos  :=  fset .Position (rules [0 ].pos )
622654		def  :=  findConst (pkgmap , C )
623655		if  def  ==  nil  {
@@ -716,3 +748,14 @@ func relative(s string) string {
716748	}
717749	return  r 
718750}
751+ 
752+ func  versionOkFilter [T  interface { versionOk (int ) bool  }](rules  []T ) []T  {
753+ 	curminor , _  :=  strconv .Atoi (strings .Split (runtime .Version ()[len (gover ):], "." )[0 ])
754+ 	r  :=  []T {}
755+ 	for  _ , rule  :=  range  rules  {
756+ 		if  rule .versionOk (curminor ) {
757+ 			rules  =  append (rules , rule )
758+ 		}
759+ 	}
760+ 	return  r 
761+ }
0 commit comments