From nobody Sat Feb 7 23:48:16 2026 Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D0F527A93C for ; Wed, 24 Dec 2025 04:00:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766548831; cv=none; b=gbdOtklb7Q8zkxAmhg6ExAZuu53YPLpviothc1sk65LeYK63Ctue49cfHblOnKShY/QAa5MjC8GazVIMc8QoPBKvxTuQ+n/xji/mzgs9qRty4NwC2ywYKgtHxnJGYE8rLDhCo6wGItlDGhv7IMGjj82P0NDV0EiBoKwsDPdKvnY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766548831; c=relaxed/simple; bh=XpcsuDJ/2lDILNGUcElL4lA//owDOu6l3dDreMlckIY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Uz3lL4Mh8t3q49C7WzqKe/ETQ9pYj20heCTiejDmgiqaO5LGpS/fZWlok9qOZMS5sn1vQgrVRjG61aecvPHWA3rLgy6Pgzku6T5LR7p2v1hk7EQkQF92Ab7qVDtM8eVV2iwQlOXwKpNZsCHwC5jxVTrx5AXmMdKaXFttjrfhnLQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=cp5SZJwB; arc=none smtp.client-ip=209.85.210.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cp5SZJwB" Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-7bc248dc16aso4575660b3a.0 for ; Tue, 23 Dec 2025 20:00:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766548829; x=1767153629; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mkwxtv2tcqZ+eg9BpVXUQ9wLIpxRDXBq7bR2sRAqPuQ=; b=cp5SZJwB6tYQq6LioP3DWXFoPGDg+B+VQd2NUgaii/ineughYr0IleE18HJIzPsnWS /+Nlb8pbnrvWlCA3mJ29MkFyiZM4/EHLhPCijV5wQn+32D+Zzf3SioyaEW4ixARfQHkt cN2jlCW/uwG0hrLBdNJmldcht5S0Af69LIaoBKP+oZeRCRAal+5ZydPCBaWeAwiRT1Cb 5/ku5StIPncBnhGqrov7en+m3Qb4jYgNxRy1G3gBQith2SJt5eNj1mDsPU5t02FvmRQq 7xv/4eRW8fXYqrEfXh6ScmPbajUmCSyIvU/xI4lrmnDq1D4M3cK93V4lK8mTSOfDaTNQ 9BXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766548829; x=1767153629; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=mkwxtv2tcqZ+eg9BpVXUQ9wLIpxRDXBq7bR2sRAqPuQ=; b=XdXY/tZcHlMZZT4zbgOpB+YX8cQww93Sd++HsazNfDjPqoOjWL6WeJoDFTmz/sVHXT GgoGpzH0NUcW/zBy2Fkf4R+5t8V4RfHp2zsR8Og4kYHM4B0+dmd5tKseLCgwnZNzW5yx 2bRCtvNjp4SkQpkiQh1ISO+Ft1ND5LLNe42NW6gHGLkqfCSJh+6AcNxrbe2j0AxLRIyL X3fsCxwtH0juZLFU37a2ZgZbFftMBDnUU7aHJYyqpPSCvZfMINDrvbUPl6AyskYk+AkL u7wdhNzPDtv2UGEaDCi8q0GNFLc5fJ7XYGLEtM6XICLhSVVGKfVZYwZC9ZfBdohajSZD 1muw== X-Forwarded-Encrypted: i=1; AJvYcCVdy3wfq2QCbBbCpCDXKse+GfZwfDGUnI5+JLF89HZ1YuDnw8PURNAJaBqfC2eY9YvFj7pMGGLunTdKNL8=@vger.kernel.org X-Gm-Message-State: AOJu0YwrUpE6e2NldUecPjLNmX0ch5cKepplthOOGibjLDbzRUTkzqpo YZmibNnEByxP32mqSb9rH40nhe8ZokMNtLbs/OiNdtkFVgsMNu+Gaoku X-Gm-Gg: AY/fxX4gwL+XmNge4e+pHNpmf5xuMAH2ZmvGKHeJa2EP3pKhdh8z2K+AK8+/awXM2vw cn5XUxuRD/Rib3RhvH+7IXYPL+XB+G+3jWMIjhBtC1kzpAjzB17+Bo7sbCW7EqiT7d2g2rbhjuw Apxk3qBzFwvgwi3fYaXKEDbCdVbHuQQDXDKEa3k/8kTEOjTZ33wnE0k+p6dkOcayb4K527ue9lq DtziyIPIlooNZbjVM8986NwsKyw9FE/40fjeoC1YC/QgcD7/DVpmqrGpQooGgLP+S9uuMwaNiex zr5ilFagU1HVtGVjcV+83dgbZhexiEGT57M0NiqhHwvcj1BVJsZeIp4IFFB2yba3vAYVgg+o5Ex ze3vCp8phZV3hXsJ0K0ZFNYboBnOZrB7I0EsuLZtUYo4SIwUcA3qbY9Uhl18lzcITiAY+YJI2VV hSa6ehT1ogRGJp8cpbAfHOTg== X-Google-Smtp-Source: AGHT+IF8d3Ro11kpgCi6eRfTtq+mc1aavRgY7ZNgf4vUnw2+Bof1xnaW/PVlb6H/zAFCBHJVO7PXPg== X-Received: by 2002:a05:6a20:939f:b0:366:1fea:9b54 with SMTP id adf61e73a8af0-376a96b9a4fmr13776384637.39.1766548829368; Tue, 23 Dec 2025 20:00:29 -0800 (PST) Received: from localhost.localdomain ([104.28.249.217]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c1e7c5307c7sm13255131a12.28.2025.12.23.20.00.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Dec 2025 20:00:29 -0800 (PST) From: Jesung Yang To: Alexandre Courbot , Miguel Ojeda , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Cc: rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org, linux-kernel@vger.kernel.org, Jesung Yang Subject: [PATCH v3 3/4] rust: macros: add private doctests for `Into` derive macro Date: Wed, 24 Dec 2025 03:59:56 +0000 Message-ID: <8afdff63fdebdfd619000e711e010191641b669b.1766544407.git.y.j3ms.n@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add internal doctests to verify the `Into` derive macro's logic. This ensures comprehensive testing while keeping the public-facing documentation compact and readable. Signed-off-by: Jesung Yang --- rust/macros/convert.rs | 436 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) diff --git a/rust/macros/convert.rs b/rust/macros/convert.rs index ceaf089c1ecb..7159fb4dd187 100644 --- a/rust/macros/convert.rs +++ b/rust/macros/convert.rs @@ -529,3 +529,439 @@ fn is_valid_primitive(ident: &Ident) -> bool { | "isize" ) } + +mod derive_into_tests { + /// ``` + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(u8)] + /// enum Foo { + /// // Works with const expressions. + /// A =3D add(0, 0), + /// B =3D 2_isize.pow(1) - 1, + /// } + /// + /// const fn add(a: isize, b: isize) -> isize { + /// a + b + /// } + /// + /// assert_eq!(0_u8, Foo::A.into()); + /// assert_eq!(1_u8, Foo::B.into()); + /// ``` + mod works_with_const_expr {} + + /// ``` + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(bool)] + /// enum Foo { + /// A, + /// B, + /// } + /// + /// assert_eq!(false, Foo::A.into()); + /// assert_eq!(true, Foo::B.into()); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(bool)] + /// enum Foo { + /// // `-1` cannot be represented with `bool`. + /// A =3D -1, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(bool)] + /// enum Foo { + /// // `2` cannot be represented with `bool`. + /// A =3D 2, + /// } + /// ``` + mod overflow_assert_works_on_bool {} + + /// ``` + /// use kernel::{ + /// macros::Into, + /// num::Bounded, // + /// }; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// A =3D -1 << 6, // The minimum value of `Bounded`. + /// B =3D (1 << 6) - 1, // The maximum value of `Bounded`. + /// } + /// + /// let foo_a: Bounded =3D Foo::A.into(); + /// let foo_b: Bounded =3D Foo::B.into(); + /// assert_eq!(Bounded::::new::<{ -1_i8 << 6 }>(), foo_a); + /// assert_eq!(Bounded::::new::<{ (1_i8 << 6) - 1 }>(), foo_b); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `1 << 6` cannot be represented with `Bounded`. + /// A =3D 1 << 6, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `(-1 << 6) - 1` cannot be represented with `Bounded`. + /// A =3D (-1 << 6) - 1, + /// } + /// ``` + /// + /// ``` + /// use kernel::{ + /// macros::Into, + /// num::Bounded, // + /// }; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// A =3D -1, // The minimum value of `Bounded`. + /// B, // The maximum value of `Bounded`. + /// } + /// + /// let foo_a: Bounded =3D Foo::A.into(); + /// let foo_b: Bounded =3D Foo::B.into(); + /// assert_eq!(Bounded::::new::<{ -1_i8 }>(), foo_a); + /// assert_eq!(Bounded::::new::<{ 0_i8 } >(), foo_b); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `1` cannot be represented with `Bounded`. + /// A =3D 1, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `-2` cannot be represented with `Bounded`. + /// A =3D -2, + /// } + /// ``` + /// + /// ``` + /// use kernel::{ + /// macros::Into, + /// num::Bounded, // + /// }; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// #[repr(i64)] + /// enum Foo { + /// A =3D i32::MIN as i64, + /// B =3D i32::MAX as i64, + /// } + /// + /// let foo_a: Bounded =3D Foo::A.into(); + /// let foo_b: Bounded =3D Foo::B.into(); + /// assert_eq!(Bounded::::new::<{ i32::MIN }>(), foo_a); + /// assert_eq!(Bounded::::new::<{ i32::MAX }>(), foo_b); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// #[repr(i64)] + /// enum Foo { + /// // `1 << 31` cannot be represented with `Bounded`. + /// A =3D 1 << 31, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// #[repr(i64)] + /// enum Foo { + /// // `(-1 << 31) - 1` cannot be represented with `Bounded`. + /// A =3D (-1 << 31) - 1, + /// } + /// ``` + mod overflow_assert_works_on_signed_bounded {} + + /// ``` + /// use kernel::{ + /// macros::Into, + /// num::Bounded, // + /// }; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// A, // The minimum value of `Bounded`. + /// B =3D (1 << 7) - 1, // The maximum value of `Bounded`. + /// } + /// + /// let foo_a: Bounded =3D Foo::A.into(); + /// let foo_b: Bounded =3D Foo::B.into(); + /// assert_eq!(Bounded::::new::<{ 0 }>(), foo_a); + /// assert_eq!(Bounded::::new::<{ (1_u8 << 7) - 1 }>(), foo_b); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `1 << 7` cannot be represented with `Bounded`. + /// A =3D 1 << 7, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `-1` cannot be represented with `Bounded`. + /// A =3D -1, + /// } + /// ``` + /// + /// ``` + /// use kernel::{ + /// macros::Into, + /// num::Bounded, // + /// }; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// A, // The minimum value of `Bounded`. + /// B, // The maximum value of `Bounded`. + /// } + /// + /// let foo_a: Bounded =3D Foo::A.into(); + /// let foo_b: Bounded =3D Foo::B.into(); + /// assert_eq!(Bounded::::new::<{ 0 }>(), foo_a); + /// assert_eq!(Bounded::::new::<{ 1 }>(), foo_b); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `2` cannot be represented with `Bounded`. + /// A =3D 2, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// enum Foo { + /// // `-1` cannot be represented with `Bounded`. + /// A =3D -1, + /// } + /// ``` + /// + /// ``` + /// use kernel::{ + /// macros::Into, + /// num::Bounded, // + /// }; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// #[repr(u64)] + /// enum Foo { + /// A =3D u32::MIN as u64, + /// B =3D u32::MAX as u64, + /// } + /// + /// let foo_a: Bounded =3D Foo::A.into(); + /// let foo_b: Bounded =3D Foo::B.into(); + /// assert_eq!(Bounded::::new::<{ u32::MIN }>(), foo_a); + /// assert_eq!(Bounded::::new::<{ u32::MAX }>(), foo_b); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// #[repr(u64)] + /// enum Foo { + /// // `1 << 32` cannot be represented with `Bounded`. + /// A =3D 1 << 32, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded)] + /// #[repr(u64)] + /// enum Foo { + /// // `-1` cannot be represented with `Bounded`. + /// A =3D -1, + /// } + /// ``` + mod overflow_assert_works_on_unsigned_bounded {} + + /// ``` + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(isize)] + /// #[repr(isize)] + /// enum Foo { + /// A =3D isize::MIN, + /// B =3D isize::MAX, + /// } + /// + /// assert_eq!(isize::MIN, Foo::A.into()); + /// assert_eq!(isize::MAX, Foo::B.into()); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(isize)] + /// #[repr(usize)] + /// enum Foo { + /// A =3D (isize::MAX as usize) + 1 + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(i32)] + /// #[repr(i64)] + /// enum Foo { + /// A =3D (i32::MIN as i64) - 1, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(i32)] + /// #[repr(i64)] + /// enum Foo { + /// A =3D (i32::MAX as i64) + 1, + /// } + /// ``` + mod overflow_assert_works_on_signed_int {} + + /// ``` + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(usize)] + /// #[repr(usize)] + /// enum Foo { + /// A =3D usize::MIN, + /// B =3D usize::MAX, + /// } + /// + /// assert_eq!(usize::MIN, Foo::A.into()); + /// assert_eq!(usize::MAX, Foo::B.into()); + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(usize)] + /// #[repr(isize)] + /// enum Foo { + /// A =3D -1, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(u32)] + /// #[repr(i64)] + /// enum Foo { + /// A =3D (u32::MIN as i64) - 1, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(u32)] + /// #[repr(i64)] + /// enum Foo { + /// A =3D (u32::MAX as i64) + 1, + /// } + /// ``` + mod overflow_assert_works_on_unsigned_int {} + + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(Bounded, i8, i16, i32, i64)] + /// #[repr(i8)] + /// enum Foo { + /// // `i8::MAX` cannot be represented with `Bounded`. + /// A =3D i8::MAX, + /// } + /// ``` + /// + /// ```compile_fail + /// use kernel::macros::Into; + /// + /// #[derive(Into)] + /// #[into(i8, i16, i32, i64, Bounded)] + /// #[repr(i8)] + /// enum Foo { + /// // `i8::MAX` cannot be represented with `Bounded`. + /// A =3D i8::MAX, + /// } + /// ``` + mod any_into_target_overflow_is_rejected {} +} --=20 2.47.3