Skip to content

coerce_container_to_any should not trigger in method chains #15045

Open
@flip1995

Description

@flip1995

Summary

This just triggered in the Rust repo and I think that's a false positive.

As I think this is significant, I moved this lint to nursery in the Clippy->Rust sync.

Added in #14812
cc @Ralith @llogiq

Lint Name

coerce_container_to_any

Reproducer

I tried this code:

let stepcache: &mut HashMap<S, <S as Step>::Output> = cache // RefMut<'_, HashMap<TypeId, …>>
    .entry(key: type_id) // Entry<'_, TypeId, Box<dyn Any + 'static>>
    .or_insert_with(default: || Box::<HashMap<S, S::Output>>::default()) // &mut Box<dyn Any + 'static>
    .downcast_mut::<HashMap<S, S::Output>>() // Option<&mut HashMap<S, <S as Step>::Output>>
    .expect(msg: "invalid type mapped");

I saw this happen:

warning: coercing `&mut std::boxed::Box<dyn std::any::Any>` to `&dyn Any`
   --> src/bootstrap/src/utils/cache.rs:231:25
    |
231 |           let stepcache = cache
    |  _________________________^
232 | |             .entry(type_id)
233 | |             .or_insert_with(|| Box::<HashMap<S, S::Output>>::default())
    | |_______________________________________________________________________^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#coerce_container_to_any
    = note: `-D clippy::coerce-container-to-any` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::coerce_container_to_any)]`
help: consider dereferencing
    |
231 |         let stepcache = &**cache
    |                         +++

I expected to see this happen: no lint. In a method chain the actual type is &mut Box<dyn Any>. Calling downcast_mut on that type will go through the Deref implementations and then call downcast_mut on the actual dyn Any. The Box is not converted into a &dyn Any reference.

Also the suggestion is wrong, as adding the derefs like shown in the suggestion, it would apply to the whole method chain, not to the offending code only. This is the correct "fix":

let stepcache: &mut HashMap<S, <S as Step>::Output> =
    (**cache.entry(key: type_id).or_insert_with(default: || Box::<HashMap<S, S::Output>>::default())) // dyn Any + 'static
        .downcast_mut::<HashMap<S, S::Output>>() // Option<&mut HashMap<S, <S as Step>::Output>>
        .expect(msg: "invalid type mapped");

Version

Current master: 4ef75291b5dd6739212f1f61666d19d4e086690d

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't haveI-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when applied

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions