@@ -10,25 +10,35 @@ use rustc_session::declare_lint_pass;
10
10
declare_clippy_lint ! {
11
11
/// ### What it does
12
12
///
13
- /// Detects cases where a `&dyn Any` is constructed directly referencing a `Box< dyn Any>` or
14
- /// other value that dereferences to `dyn Any`.
13
+ /// Protects against unintended coercion of references to container types to `& dyn Any`
14
+ /// when the container type dereferences to a `dyn Any` which could be reborrowed instead .
15
15
///
16
16
/// ### Why is this bad?
17
17
///
18
- /// The intention is usually to borrow the `dyn Any` available by dereferencing the value,
19
- /// rather than the value itself .
18
+ /// The intention is usually to get a reference to the `dyn Any` the value derefernces to ,
19
+ /// rather than getting a `&dyn Any` which is actually referring to the outer container type .
20
20
///
21
21
/// ### Example
22
+ ///
23
+ /// Here we see that because `Box<dyn Any>` itself implements `Any`, `&Box<dyn Any>`
24
+ /// gets coerced to an `&dyn Any` which refers to *the `Box` itself`*, rather than the
25
+ /// inner `dyn Any`.
22
26
/// ```no_run
23
27
/// # use std::any::Any;
24
- /// let x: Box<dyn Any> = Box::new(());
25
- /// let _: &dyn Any = &x;
28
+ /// let x: Box<dyn Any> = Box::new(0u32);
29
+ /// let dyn_any_of_box: &dyn Any = &x;
30
+ ///
31
+ /// // Fails as we have a &dyn Any to the Box, not the u32
32
+ /// assert_eq!(dyn_any_of_box.downcast_ref::<u32>(), None);
26
33
/// ```
27
34
/// Use instead:
28
35
/// ```no_run
29
36
/// # use std::any::Any;
30
- /// let x: Box<dyn Any> = Box::new(());
31
- /// let _: &dyn Any = &*x;
37
+ /// let x: Box<dyn Any> = Box::new(0u32);
38
+ /// let dyn_any_of_u32: &dyn Any = &*x;
39
+ ///
40
+ /// // Succeeds sincwe have a &dyn Any to the inner u32!
41
+ /// assert_eq!(dyn_any_of_u32.downcast_ref::<u32>(), Some(&0u32));
32
42
/// ```
33
43
#[ clippy:: version = "1.88.0" ]
34
44
pub COERCE_ANY_REF_TO_ANY ,
0 commit comments