Skip to content

trivial_casts diagnostic creates spurious errors when working with Any #148219

Description

@VorpalBlade

Code

trait DynKey: Any {
    fn eq(&self, other: &dyn DynKey) -> bool;
    fn hash(&self) -> u64;
    fn type_name(&self) -> &'static str;
}

impl<T: Eq + Hash + 'static> DynKey for T {
    #[warn(trivial_casts)]
    fn eq(&self, other: &dyn DynKey) -> bool {
        if let Some(other) = (other as &dyn Any).downcast_ref::<T>() {
            return self == other;
        }
        false
    }

    fn hash(&self) -> u64 {
        let mut h = DefaultHasher::new();
        // mix the typeid of T into the hash to make distinct types
        // provide distinct hashes
        Hash::hash(&(TypeId::of::<T>(), self), &mut h);
        h.finish()
    }
    
    fn type_name(&self) -> &'static str {
        std::any::type_name::<T>()
    }
}

Current output

warning: trivial cast: `&(dyn DynKey + 'static)` as `&(dyn Any + 'static)`
  --> src/lib.rs:13:30
   |
13 |         if let Some(other) = (other as &dyn Any).downcast_ref::<T>() {
   |                              ^^^^^^^^^^^^^^^^^^^
   |
   = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here

Desired output

Not lint on this

Rationale and extra context

Removing the cast doesn't work, as downcast_ref is then not found.

        let other_any = other as &dyn Any;
        if let Some(other) = other_any.downcast_ref::<T>() {
            return self == other;
        }

just moves the warning to another line. And I don't really see how

let other_any: &dyn Any = other;

(which does work) is any cleaner to begin with. So it seems there is no reasonable way to solve this apart from allowing it? In general I do like this lint, it just seems to be rather incorrect in this case.

If this lint should ever become enabled by default, I think this case needs a reasonable solution.

Other cases

Rust Version

❯ rustc --version --verbose
rustc 1.90.0 (1159e78c4 2025-09-14)
binary: rustc
commit-hash: 1159e78c4747b02ef996e55082b704c09b970588
commit-date: 2025-09-14
host: x86_64-unknown-linux-gnu
release: 1.90.0
LLVM version: 20.1.8

Anything else?

First reported at https://users.rust-lang.org/t/broken-diagnostic-trivial-casts-from-rust/134965

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions