class T::Props::Decorator

def prop_defined(name, cls, rules={})

def prop_defined(name, cls, rules={})
  cls = T::Utils.resolve_alias(cls)
  if prop_nilable?(cls, rules)
    # :_tnilable is introduced internally for performance purpose so that clients do not need to call
    # T::Utils::Nilable.is_tnilable(cls) again.
    # It is strictly internal: clients should always use T::Props::Utils.required_prop?() or
    # T::Props::Utils.optional_prop?() for checking whether a field is required or optional.
    rules[:_tnilable] = true
  end
  name = name.to_sym
  type = cls
  if !cls.is_a?(Module)
    cls = convert_type_to_class(cls)
  end
  type_object = smart_coerce(type, enum: rules[:enum])
  prop_validate_definition!(name, cls, rules, type_object)
  # Retrieve the possible underlying object with T.nilable.
  type = T::Utils::Nilable.get_underlying_type(type)
  rules_sensitivity = rules[:sensitivity]
  sensitivity_and_pii = {sensitivity: rules_sensitivity}
  if !rules_sensitivity.nil?
    normalize = T::Configuration.normalize_sensitivity_and_pii_handler
    if normalize
      sensitivity_and_pii = normalize.call(sensitivity_and_pii)
      # We check for Class so this is only applied on concrete
      # documents/models; We allow mixins containing props to not
      # specify their PII nature, as long as every class into which they
      # are ultimately included does.
      #
      if sensitivity_and_pii[:pii] && @class.is_a?(Class) && !T.unsafe(@class).contains_pii?
        raise ArgumentError.new(
          'Cannot include a pii prop in a class that declares `contains_no_pii`'
        )
      end
    end
  end
  rules[:type] = type
  rules[:type_object] = type_object
  rules[:accessor_key] = "@#{name}".to_sym
  rules[:sensitivity] = sensitivity_and_pii[:sensitivity]
  rules[:pii] = sensitivity_and_pii[:pii]
  rules[:extra] = rules[:extra]&.freeze
  # extra arbitrary metadata attached by the code defining this property
  validate_not_missing_sensitivity(name, rules)
  # for backcompat (the `:array` key is deprecated but because the name is
  # so generic it's really hard to be sure it's not being relied on anymore)
  if type.is_a?(T::Types::TypedArray)
    inner = T::Utils::Nilable.get_underlying_type(type.type)
    if inner.is_a?(Module)
      rules[:array] = inner
    end
  end
  setter_proc, value_validate_proc = T::Props::Private::SetterFactory.build_setter_proc(@class, name, rules)
  setter_proc.freeze
  value_validate_proc.freeze
  rules[:setter_proc] = setter_proc
  rules[:value_validate_proc] = value_validate_proc
  add_prop_definition(name, rules)
  # NB: using `without_accessors` doesn't make much sense unless you also define some other way to
  # get at the property (e.g., Chalk::ODM::Document exposes `get` and `set`).
  define_getter_and_setter(name, rules) unless rules[:without_accessors]
  handle_foreign_option(name, cls, rules, rules[:foreign]) if rules[:foreign]
  handle_redaction_option(name, rules[:redaction]) if rules[:redaction]
end