Skip to content

rustdoc: Show whether generic type params actually are ?Sized, not whether definition site syntactically includes ?Sized #143197

Open
@obi1kenobi

Description

@obi1kenobi

Code

?Sized is unlike other bounds: while T: Foo demands that T implement Foo, T: ?Sized allows T to not be Sized — it does not demand it. It relaxes an obligation, that's it.

If that obligation is demanded by another clause, then adding ?Sized has no effect. For example:

trait Private: Sized {}

pub fn example<T: Private + ?Sized>(value: &T) {}

Here T: Private and Private: Sized imply T: Sized, so T: ?Sized has no effect. This is confirmed by clippy, which raises a needless_maybe_sized lint here.

Since rustdoc is a tool for documenting the public API of Rust programs, I believe that it is misleading and undesirable for it to report T: ?Sized in circumstances where unsized types will not be accepted. It doesn't matter if the definition site of the generic type parameter syntactically mentions T: ?Sized if that clause has no effect on the public API.

Reproduction Steps

cargo doc for HTML output.

RUSTDOCFLAGS="-Z unstable-options --output-format=json --cap-lints=allow" cargo doc for JSON output.

Expected Outcome

Observe pub fn example<T: Private>(value: &T) as the recorded function signature in HTML docs. T: ?Sized does not apply to the API in practice, so it is excluded.

By the same reasoning, do not include T: ?Sized as a trait bound in rustdoc JSON.

Actual Output

Observe pub fn example<T: Private + ?Sized>(value: &T) as the recorded function signature in HTML docs.

Observe the following item in rustdoc JSON:

{
    "id": 0,
    "crate_id": 0,
    "name": "example",
    "span": {
        // omitted for brevity
    },
    "visibility": "public",
    "docs": null,
    "links": {},
    "attrs": [],
    "deprecation": null,
    "inner": {
        "function": {
            "sig": {
                // omitted for brevity
            },
            "generics": {
                "params": [
                    {
                        "name": "T",
                        "kind": {
                            "type": {
                                "bounds": [
                                    {
                                        "trait_bound": {
                                            "trait": {
                                                "path": "Private",
                                                "id": 1,
                                                "args": {
                                                    "angle_bracketed": {
                                                        "args": [],
                                                        "constraints": []
                                                    }
                                                }
                                            },
                                            "generic_params": [],
                                            "modifier": "none"
                                        }
                                    },
                                    {
                                        "trait_bound": {
                                            "trait": {
                                                "path": "Sized",
                                                "id": 2,
                                                "args": {
                                                    "angle_bracketed": {
                                                        "args": [],
                                                        "constraints": []
                                                    }
                                                }
                                            },
                                            "generic_params": [],
                                            "modifier": "maybe"  // <-- `?Sized`
                                        }
                                    }
                                ],
                                "default": null,
                                "is_synthetic": false
                            }
                        }
                    }
                ],
                "where_predicates": []
            },
            // omitted for brevity
        }
    }
}

Version

rustc 1.90.0-nightly (28f1c8079 2025-06-24)
binary: rustc
commit-hash: 28f1c807911c63f08d98e7b468cfcf15a441e34b
commit-date: 2025-06-24
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7

@rustbot label +A-rustdoc-json

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-rustdoc-jsonArea: Rustdoc JSON backendC-bugCategory: This is a bug.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions