@@ -506,8 +506,88 @@ def build_one_instance(type_name, extension_name: nil)
506506 )
507507 end
508508 end
509+
510+ validate_parameter_variance (
511+ decl : decl ,
512+ methods : definition . methods
513+ )
514+ end
515+ end
516+ end
517+
518+ def validate_params_with ( type_params , result :)
519+ type_params . each do |param |
520+ unless param . skip_validation
521+ unless result . compatible? ( param . name , with_annotation : param . variance )
522+ yield param
523+ end
524+ end
525+ end
526+ end
527+
528+ def validate_parameter_variance ( decl :, methods :)
529+ type_params = case decl
530+ when AST ::Declarations ::Extension
531+ env . find_class ( decl . name . absolute! ) . type_params . rename_to ( decl . type_params )
532+ else
533+ decl . type_params
534+ end
535+
536+ namespace = decl . name . absolute! . to_namespace
537+ calculator = VarianceCalculator . new ( builder : self )
538+ param_names = type_params . each . map ( &:name )
539+
540+ errors = [ ]
541+
542+ if decl . is_a? ( AST ::Declarations ::Class )
543+ if decl . super_class
544+ absolute_super_name = absolute_type_name ( decl . super_class . name , namespace : namespace , location : decl . location )
545+ absolute_args = decl . super_class . args . map { |type | absolute_type ( type , namespace : namespace ) }
546+ result = calculator . in_inherit ( name : absolute_super_name , args : absolute_args , variables : param_names )
547+
548+ validate_params_with type_params , result : result do |param |
549+ errors . push InvalidVarianceAnnotationError ::InheritanceError . new (
550+ param : param
551+ )
552+ end
553+ end
554+ end
555+
556+ decl . members . each do |member |
557+ case member
558+ when AST ::Members ::Include
559+ if member . name . class?
560+ absolute_module_name = absolute_type_name ( member . name , namespace : namespace , location : decl . location )
561+ absolute_args = member . args . map { |type | absolute_type ( type , namespace : namespace ) }
562+ result = calculator . in_inherit ( name : absolute_module_name , args : absolute_args , variables : param_names )
563+
564+ validate_params_with type_params , result : result do |param |
565+ errors . push InvalidVarianceAnnotationError ::MixinError . new (
566+ include_member : member ,
567+ param : param
568+ )
569+ end
570+ end
509571 end
510572 end
573+
574+ methods . each do |name , method |
575+ method . method_types . each do |method_type |
576+ result = calculator . in_method_type ( method_type : method_type , variables : param_names )
577+
578+ validate_params_with type_params , result : result do |param |
579+ errors . push InvalidVarianceAnnotationError ::MethodTypeError . new (
580+ method_name : name ,
581+ method_type : method_type ,
582+ param : param
583+ )
584+ end
585+ end
586+ end
587+
588+ unless errors . empty?
589+ raise InvalidVarianceAnnotationError . new ( decl : decl , errors : errors )
590+ end
511591 end
512592
513593 def build_one_singleton ( type_name , extension_name : nil )
0 commit comments