ide_diagnostics/handlers/
invalid_cast.rs

1use hir::{CastError, ClosureStyle, HirDisplay};
2
3use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
4
5macro_rules! format_ty {
6    ($ctx:expr, $fmt:literal, $($arg:expr),* $(,)?) => {{
7        std::format!(
8            $fmt,
9            $(
10                $arg
11                    .display($ctx.sema.db, $ctx.display_target)
12                    .with_closure_style(ClosureStyle::ClosureWithId)
13            ),*
14        )
15    }}
16}
17
18// Diagnostic: invalid-cast
19//
20// This diagnostic is triggered if the code contains an illegal cast
21pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast<'_>) -> Diagnostic {
22    let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into()));
23    let (code, message) = match d.error {
24        CastError::CastToBool => (
25            DiagnosticCode::RustcHardError("E0054"),
26            format_ty!(ctx, "cannot cast `{}` as `bool`", d.expr_ty),
27        ),
28        CastError::CastToChar => (
29            DiagnosticCode::RustcHardError("E0604"),
30            format_ty!(ctx, "only `u8` can be cast as `char`, not {}", d.expr_ty),
31        ),
32        CastError::DifferingKinds => (
33            DiagnosticCode::RustcHardError("E0606"),
34            format_ty!(
35                ctx,
36                "casting `{}` as `{}` is invalid: vtable kinds may not match",
37                d.expr_ty,
38                d.cast_ty
39            ),
40        ),
41        CastError::SizedUnsizedCast => (
42            DiagnosticCode::RustcHardError("E0607"),
43            format_ty!(
44                ctx,
45                "cannot cast thin pointer `{}` to fat pointer `{}`",
46                d.expr_ty,
47                d.cast_ty
48            ),
49        ),
50        CastError::Unknown | CastError::IllegalCast => (
51            DiagnosticCode::RustcHardError("E0606"),
52            format_ty!(ctx, "casting `{}` as `{}` is invalid", d.expr_ty, d.cast_ty),
53        ),
54        CastError::IntToFatCast => (
55            DiagnosticCode::RustcHardError("E0606"),
56            format_ty!(ctx, "cannot cast `{}` to a fat pointer `{}`", d.expr_ty, d.cast_ty),
57        ),
58        CastError::NeedDeref => (
59            DiagnosticCode::RustcHardError("E0606"),
60            format_ty!(
61                ctx,
62                "casting `{}` as `{}` is invalid: needs dereference or removal of unneeded borrow",
63                d.expr_ty,
64                d.cast_ty
65            ),
66        ),
67        CastError::NeedViaPtr => (
68            DiagnosticCode::RustcHardError("E0606"),
69            format_ty!(
70                ctx,
71                "casting `{}` as `{}` is invalid: needs casting through a raw pointer first",
72                d.expr_ty,
73                d.cast_ty
74            ),
75        ),
76        CastError::NeedViaThinPtr => (
77            DiagnosticCode::RustcHardError("E0606"),
78            format_ty!(
79                ctx,
80                "casting `{}` as `{}` is invalid: needs casting through a thin pointer first",
81                d.expr_ty,
82                d.cast_ty
83            ),
84        ),
85        CastError::NeedViaInt => (
86            DiagnosticCode::RustcHardError("E0606"),
87            format_ty!(
88                ctx,
89                "casting `{}` as `{}` is invalid: needs casting through an integer first",
90                d.expr_ty,
91                d.cast_ty
92            ),
93        ),
94        CastError::NonScalar => (
95            DiagnosticCode::RustcHardError("E0605"),
96            format_ty!(ctx, "non-primitive cast: `{}` as `{}`", d.expr_ty, d.cast_ty),
97        ),
98        // CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => (
99        //     DiagnosticCode::RustcHardError("E0641"),
100        //     "cannot cast to a pointer of an unknown kind".to_owned(),
101        // ),
102    };
103    Diagnostic::new(code, message, display_range).stable()
104}
105
106// Diagnostic: cast-to-unsized
107//
108// This diagnostic is triggered when casting to an unsized type
109pub(crate) fn cast_to_unsized(
110    ctx: &DiagnosticsContext<'_>,
111    d: &hir::CastToUnsized<'_>,
112) -> Diagnostic {
113    let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into()));
114    Diagnostic::new(
115        DiagnosticCode::RustcHardError("E0620"),
116        format_ty!(ctx, "cast to unsized type: `{}`", d.cast_ty),
117        display_range,
118    )
119    .stable()
120}
121
122#[cfg(test)]
123mod tests {
124    use crate::tests::{check_diagnostics, check_diagnostics_with_disabled};
125
126    #[test]
127    fn cast_as_bool() {
128        check_diagnostics(
129            r#"
130//- minicore: sized
131fn main() {
132    let u = 5 as bool;
133          //^^^^^^^^^ error: cannot cast `i32` as `bool`
134
135    let t = (1 + 2) as bool;
136          //^^^^^^^^^^^^^^^ error: cannot cast `i32` as `bool`
137
138    let _ = 5_u32 as bool;
139          //^^^^^^^^^^^^^ error: cannot cast `u32` as `bool`
140
141    let _ = 64.0_f64 as bool;
142          //^^^^^^^^^^^^^^^^ error: cannot cast `f64` as `bool`
143
144    enum IntEnum {
145        Zero,
146        One,
147        Two
148    }
149    let _ = IntEnum::One as bool;
150          //^^^^^^^^^^^^^^^^^^^^ error: cannot cast `IntEnum` as `bool`
151
152    fn uwu(_: u8) -> i32 {
153        5
154    }
155
156    unsafe fn owo() {}
157
158    let _ = uwu as bool;
159          //^^^^^^^^^^^ error: cannot cast `fn uwu(u8) -> i32` as `bool`
160    let _ = owo as bool;
161          //^^^^^^^^^^^ error: cannot cast `unsafe fn owo()` as `bool`
162
163    let _ = uwu as fn(u8) -> i32 as bool;
164          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot cast `fn(u8) -> i32` as `bool`
165    let _ = 'x' as bool;
166          //^^^^^^^^^^^ error: cannot cast `char` as `bool`
167
168    let ptr = 1 as *const ();
169
170    let _ = ptr as bool;
171          //^^^^^^^^^^^ error: cannot cast `*const ()` as `bool`
172    let v = "hello" as bool;
173          //^^^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first
174}
175"#,
176        );
177    }
178
179    #[test]
180    fn cast_pointee_projection() {
181        check_diagnostics(
182            r#"
183//- minicore: sized
184trait Tag<'a> {
185    type Type: ?Sized;
186}
187
188trait IntoRaw: for<'a> Tag<'a> {
189    fn into_raw(this: *const <Self as Tag<'_>>::Type) -> *mut <Self as Tag<'_>>::Type;
190}
191
192impl<T: for<'a> Tag<'a>> IntoRaw for T {
193    fn into_raw(this: *const <Self as Tag<'_>>::Type) -> *mut <Self as Tag<'_>>::Type {
194        this as *mut T::Type
195    }
196}
197
198fn main() {}
199"#,
200        );
201    }
202
203    #[test]
204    fn cast_region_to_int() {
205        check_diagnostics(
206            r#"
207//- minicore: sized
208fn main() {
209    let x: isize = 3;
210    let _ = &x as *const isize as usize;
211}
212"#,
213        );
214    }
215
216    #[test]
217    fn cast_to_bare_fn() {
218        check_diagnostics(
219            r#"
220//- minicore: sized
221fn foo(_x: isize) { }
222
223fn main() {
224    let v: u64 = 5;
225    let x = foo as extern "C" fn() -> isize;
226          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `fn foo(isize)` as `fn() -> isize`
227    let y = v as extern "Rust" fn(isize) -> (isize, isize);
228          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `u64` as `fn(isize) -> (isize, isize)`
229    y(x());
230}
231"#,
232        );
233    }
234
235    #[test]
236    fn cast_to_unit() {
237        check_diagnostics(
238            r#"
239//- minicore: sized
240fn main() {
241    let _ = 0u32 as ();
242          //^^^^^^^^^^ error: non-primitive cast: `u32` as `()`
243}
244"#,
245        );
246    }
247
248    #[test]
249    fn cast_to_slice() {
250        check_diagnostics_with_disabled(
251            r#"
252//- minicore: sized
253fn as_bytes(_: &str) -> &[u8] {
254    loop {}
255}
256
257fn main() {
258    as_bytes("example") as [char];
259  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cast to unsized type: `[char]`
260
261    let arr: &[u8] = &[0, 2, 3];
262    arr as [char];
263  //^^^^^^^^^^^^^ error: cast to unsized type: `[char]`
264}
265"#,
266            &["E0308"],
267        );
268    }
269
270    #[test]
271    fn cast() {
272        check_diagnostics(
273            r#"
274//- minicore: sized
275fn null_mut<T: ?Sized>() -> *mut T {
276    loop {}
277}
278
279pub fn main() {
280    let i: isize = 'Q' as isize;
281    let _u: u32 = i as u32;
282
283    // Test that `_` is correctly inferred.
284    let x = &"hello";
285    let mut y = x as *const _;
286    y = null_mut();
287}
288"#,
289        );
290    }
291
292    #[test]
293    fn dyn_tail_need_normalization() {
294        check_diagnostics(
295            r#"
296//- minicore: dispatch_from_dyn
297trait Trait {
298    type Associated;
299}
300
301impl Trait for i32 {
302    type Associated = i64;
303}
304
305trait Generic<T> {}
306
307type TraitObject = dyn Generic<<i32 as Trait>::Associated>;
308
309struct Wrap(TraitObject);
310
311fn cast(x: *mut TraitObject) {
312    x as *mut Wrap;
313}
314"#,
315        );
316    }
317
318    #[test]
319    fn enum_to_numeric_cast() {
320        check_diagnostics(
321            r#"
322//- minicore: sized
323pub enum UnitOnly {
324    Foo,
325    Bar,
326    Baz,
327}
328
329pub enum Fieldless {
330    Tuple(),
331    Struct{},
332    Unit,
333}
334
335pub enum NotUnitOnlyOrFieldless {
336    Foo,
337    Bar(u8),
338    Baz
339}
340
341fn main() {
342    let unit_only = UnitOnly::Foo;
343
344    let _ = unit_only as isize;
345    let _ = unit_only as i32;
346    let _ = unit_only as usize;
347    let _ = unit_only as u32;
348
349
350    let fieldless = Fieldless::Struct{};
351
352    let _ = fieldless as isize;
353    let _ = fieldless as i32;
354    let _ = fieldless as usize;
355    let _ = fieldless as u32;
356
357
358    let not_unit_only_or_fieldless = NotUnitOnlyOrFieldless::Foo;
359
360    let _ = not_unit_only_or_fieldless as isize;
361          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `isize`
362    let _ = not_unit_only_or_fieldless as i32;
363          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `i32`
364    let _ = not_unit_only_or_fieldless as usize;
365          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `usize`
366    let _ = not_unit_only_or_fieldless as u32;
367          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `u32`
368}
369"#,
370        );
371    }
372
373    #[test]
374    fn fat_ptr_cast() {
375        check_diagnostics_with_disabled(
376            r#"
377//- minicore: sized
378trait Foo {
379    fn foo(&self) {} //~ WARN method `foo` is never used
380}
381
382struct Bar;
383
384impl Foo for Bar {}
385
386fn to_raw<T>(_: *mut T) -> *mut () {
387    loop {}
388}
389
390fn main() {
391    // Test we can turn a fat pointer to array back into a thin pointer.
392    let a: *const [i32] = &[1, 2, 3];
393    let b = a as *const [i32; 2];
394
395    // Test conversion to an address (usize).
396    let a: *const [i32; 3] = &[1, 2, 3];
397    let b: *const [i32] = a;
398
399    // And conversion to a void pointer/address for trait objects too.
400    let a: *mut dyn Foo = &mut Bar;
401    let b = a as *mut () as usize;
402    let c = a as *const () as usize;
403    let d = to_raw(a) as usize;
404}
405"#,
406            &["E0308"],
407        );
408
409        check_diagnostics_with_disabled(
410            r#"
411//- minicore: sized
412trait Trait {}
413
414struct Box<T: ?Sized>;
415
416impl<T: ?Sized> Box<T> {
417    fn new(_: T) -> Self {
418        loop {}
419    }
420}
421
422fn as_ptr(_: &[i32]) -> *const i32 {
423    loop {}
424}
425
426fn main() {
427    let a: &[i32] = &[1, 2, 3];
428    let b: Box<[i32]> = Box::new([1, 2, 3]);
429    let p = a as *const [i32];
430    let q = as_ptr(a);
431
432    a as usize;
433  //^^^^^^^^^^ error: casting `&[i32]` as `usize` is invalid: needs casting through a raw pointer first
434    a as isize;
435  //^^^^^^^^^^ error: casting `&[i32]` as `isize` is invalid: needs casting through a raw pointer first
436    a as i16;
437  //^^^^^^^^ error: casting `&[i32]` as `i16` is invalid: needs casting through a raw pointer first
438    a as u32;
439  //^^^^^^^^ error: casting `&[i32]` as `u32` is invalid: needs casting through a raw pointer first
440    b as usize;
441  //^^^^^^^^^^ error: non-primitive cast: `Box<[i32]>` as `usize`
442    p as usize;
443  //^^^^^^^^^^ error: casting `*const [i32]` as `usize` is invalid: needs casting through a thin pointer first
444    q as *const [i32];
445  //^^^^^^^^^^^^^^^^^ error: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]`
446
447    // FIXME: This should emit diagnostics but disabled to prevent many false positives
448    let t: *mut (dyn Trait + 'static) = 0 as *mut _;
449
450    let mut fail: *const str = 0 as *const str;
451                             //^^^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const str`
452    let mut fail2: *const str = 0isize as *const str;
453                              //^^^^^^^^^^^^^^^^^^^^ error: cannot cast `isize` to a fat pointer `*const str`
454}
455
456fn foo<T: ?Sized>() {
457    let s = 0 as *const T;
458          //^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const T`
459}
460"#,
461            &["E0308", "unused_variables"],
462        );
463    }
464
465    //     #[test]
466    //     fn order_dependent_cast_inference() {
467    //         check_diagnostics(
468    //             r#"
469    // //- minicore: sized
470    // fn main() {
471    //     let x = &"hello";
472    //     let mut y = 0 as *const _;
473    //               //^^^^^^^^^^^^^ error: cannot cast to a pointer of an unknown kind
474    //     y = x as *const _;
475    // }
476    // "#,
477    //         );
478    //     }
479
480    #[test]
481    fn ptr_to_ptr_different_regions() {
482        check_diagnostics(
483            r#"
484//- minicore: sized
485struct Foo<'a> { a: &'a () }
486
487fn extend_lifetime_very_very_safely<'a>(v: *const Foo<'a>) -> *const Foo<'static> {
488    // This should pass because raw pointer casts can do anything they want.
489    v as *const Foo<'static>
490}
491
492trait Trait {}
493
494fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) {
495    ptr as _
496}
497
498fn main() {
499    let unit = ();
500    let foo = Foo { a: &unit };
501    let _long: *const Foo<'static> = extend_lifetime_very_very_safely(&foo);
502}
503"#,
504        );
505    }
506
507    #[test]
508    fn ptr_to_trait_obj_add_auto() {
509        check_diagnostics(
510            r#"
511//- minicore: pointee
512trait Trait<'a> {}
513
514fn add_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send) {
515    x as _
516}
517
518// (to test diagnostic list formatting)
519fn add_multiple_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send + Sync + Unpin) {
520    x as _
521}
522"#,
523        );
524    }
525
526    #[test]
527    fn ptr_to_trait_obj_add_super_auto() {
528        check_diagnostics(
529            r#"
530//- minicore: pointee
531trait Trait: Send {}
532impl Trait for () {}
533
534fn main() {
535    // This is OK: `Trait` has `Send` super trait.
536    &() as *const dyn Trait as *const (dyn Trait + Send);
537}
538"#,
539        );
540    }
541
542    #[test]
543    fn ptr_to_trait_obj_ok() {
544        check_diagnostics(
545            r#"
546//- minicore: pointee
547trait Trait<'a> {}
548
549fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> {
550    x as _
551}
552
553fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) {
554    x as _
555}
556
557fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
558    x as _
559}
560"#,
561        );
562    }
563
564    #[ignore = "issue #18047"]
565    #[test]
566    fn ptr_to_trait_obj_wrap_upcast() {
567        check_diagnostics(
568            r#"
569//- minicore: sized
570trait Super {}
571trait Sub: Super {}
572
573struct Wrapper<T: ?Sized>(T);
574
575// This cast should not compile.
576// Upcasting can't work here, because we are also changing the type (`Wrapper`),
577// and reinterpreting would be confusing/surprising.
578// See <https://github.com/rust-lang/rust/pull/120248#discussion_r1487739518>
579fn cast(ptr: *const dyn Sub) -> *const Wrapper<dyn Super> {
580    ptr as _
581  //^^^^^^^^ error: casting `*const dyn Sub` as `*const Wrapper<dyn Super>` is invalid: vtable kinds may not match
582}
583"#,
584        );
585    }
586
587    #[test]
588    fn supported_cast() {
589        check_diagnostics(
590            r#"
591//- minicore: sized
592pub fn main() {
593    struct String;
594
595    let f = 1_usize as *const String;
596
597    let _ = f as isize;
598    let _ = f as usize;
599    let _ = f as i8;
600    let _ = f as i16;
601    let _ = f as i32;
602    let _ = f as i64;
603    let _ = f as u8;
604    let _ = f as u16;
605    let _ = f as u32;
606    let _ = f as u64;
607
608    let _ = 1 as isize;
609    let _ = 1 as usize;
610    let _ = 1 as *const String;
611    let _ = 1 as i8;
612    let _ = 1 as i16;
613    let _ = 1 as i32;
614    let _ = 1 as i64;
615    let _ = 1 as u8;
616    let _ = 1 as u16;
617    let _ = 1 as u32;
618    let _ = 1 as u64;
619    let _ = 1 as f32;
620    let _ = 1 as f64;
621
622    let _ = 1_usize as isize;
623    let _ = 1_usize as usize;
624    let _ = 1_usize as *const String;
625    let _ = 1_usize as i8;
626    let _ = 1_usize as i16;
627    let _ = 1_usize as i32;
628    let _ = 1_usize as i64;
629    let _ = 1_usize as u8;
630    let _ = 1_usize as u16;
631    let _ = 1_usize as u32;
632    let _ = 1_usize as u64;
633    let _ = 1_usize as f32;
634    let _ = 1_usize as f64;
635
636    let _ = 1i8 as isize;
637    let _ = 1i8 as usize;
638    let _ = 1i8 as *const String;
639    let _ = 1i8 as i8;
640    let _ = 1i8 as i16;
641    let _ = 1i8 as i32;
642    let _ = 1i8 as i64;
643    let _ = 1i8 as u8;
644    let _ = 1i8 as u16;
645    let _ = 1i8 as u32;
646    let _ = 1i8 as u64;
647    let _ = 1i8 as f32;
648    let _ = 1i8 as f64;
649
650    let _ = 1u8 as isize;
651    let _ = 1u8 as usize;
652    let _ = 1u8 as *const String;
653    let _ = 1u8 as i8;
654    let _ = 1u8 as i16;
655    let _ = 1u8 as i32;
656    let _ = 1u8 as i64;
657    let _ = 1u8 as u8;
658    let _ = 1u8 as u16;
659    let _ = 1u8 as u32;
660    let _ = 1u8 as u64;
661    let _ = 1u8 as f32;
662    let _ = 1u8 as f64;
663
664    let _ = 1i16 as isize;
665    let _ = 1i16 as usize;
666    let _ = 1i16 as *const String;
667    let _ = 1i16 as i8;
668    let _ = 1i16 as i16;
669    let _ = 1i16 as i32;
670    let _ = 1i16 as i64;
671    let _ = 1i16 as u8;
672    let _ = 1i16 as u16;
673    let _ = 1i16 as u32;
674    let _ = 1i16 as u64;
675    let _ = 1i16 as f32;
676    let _ = 1i16 as f64;
677
678    let _ = 1u16 as isize;
679    let _ = 1u16 as usize;
680    let _ = 1u16 as *const String;
681    let _ = 1u16 as i8;
682    let _ = 1u16 as i16;
683    let _ = 1u16 as i32;
684    let _ = 1u16 as i64;
685    let _ = 1u16 as u8;
686    let _ = 1u16 as u16;
687    let _ = 1u16 as u32;
688    let _ = 1u16 as u64;
689    let _ = 1u16 as f32;
690    let _ = 1u16 as f64;
691
692    let _ = 1i32 as isize;
693    let _ = 1i32 as usize;
694    let _ = 1i32 as *const String;
695    let _ = 1i32 as i8;
696    let _ = 1i32 as i16;
697    let _ = 1i32 as i32;
698    let _ = 1i32 as i64;
699    let _ = 1i32 as u8;
700    let _ = 1i32 as u16;
701    let _ = 1i32 as u32;
702    let _ = 1i32 as u64;
703    let _ = 1i32 as f32;
704    let _ = 1i32 as f64;
705
706    let _ = 1u32 as isize;
707    let _ = 1u32 as usize;
708    let _ = 1u32 as *const String;
709    let _ = 1u32 as i8;
710    let _ = 1u32 as i16;
711    let _ = 1u32 as i32;
712    let _ = 1u32 as i64;
713    let _ = 1u32 as u8;
714    let _ = 1u32 as u16;
715    let _ = 1u32 as u32;
716    let _ = 1u32 as u64;
717    let _ = 1u32 as f32;
718    let _ = 1u32 as f64;
719
720    let _ = 1i64 as isize;
721    let _ = 1i64 as usize;
722    let _ = 1i64 as *const String;
723    let _ = 1i64 as i8;
724    let _ = 1i64 as i16;
725    let _ = 1i64 as i32;
726    let _ = 1i64 as i64;
727    let _ = 1i64 as u8;
728    let _ = 1i64 as u16;
729    let _ = 1i64 as u32;
730    let _ = 1i64 as u64;
731    let _ = 1i64 as f32;
732    let _ = 1i64 as f64;
733
734    let _ = 1u64 as isize;
735    let _ = 1u64 as usize;
736    let _ = 1u64 as *const String;
737    let _ = 1u64 as i8;
738    let _ = 1u64 as i16;
739    let _ = 1u64 as i32;
740    let _ = 1u64 as i64;
741    let _ = 1u64 as u8;
742    let _ = 1u64 as u16;
743    let _ = 1u64 as u32;
744    let _ = 1u64 as u64;
745    let _ = 1u64 as f32;
746    let _ = 1u64 as f64;
747
748    let _ = 1u64 as isize;
749    let _ = 1u64 as usize;
750    let _ = 1u64 as *const String;
751    let _ = 1u64 as i8;
752    let _ = 1u64 as i16;
753    let _ = 1u64 as i32;
754    let _ = 1u64 as i64;
755    let _ = 1u64 as u8;
756    let _ = 1u64 as u16;
757    let _ = 1u64 as u32;
758    let _ = 1u64 as u64;
759    let _ = 1u64 as f32;
760    let _ = 1u64 as f64;
761
762    let _ = true as isize;
763    let _ = true as usize;
764    let _ = true as i8;
765    let _ = true as i16;
766    let _ = true as i32;
767    let _ = true as i64;
768    let _ = true as u8;
769    let _ = true as u16;
770    let _ = true as u32;
771    let _ = true as u64;
772
773    let _ = 1f32 as isize;
774    let _ = 1f32 as usize;
775    let _ = 1f32 as i8;
776    let _ = 1f32 as i16;
777    let _ = 1f32 as i32;
778    let _ = 1f32 as i64;
779    let _ = 1f32 as u8;
780    let _ = 1f32 as u16;
781    let _ = 1f32 as u32;
782    let _ = 1f32 as u64;
783    let _ = 1f32 as f32;
784    let _ = 1f32 as f64;
785
786    let _ = 1f64 as isize;
787    let _ = 1f64 as usize;
788    let _ = 1f64 as i8;
789    let _ = 1f64 as i16;
790    let _ = 1f64 as i32;
791    let _ = 1f64 as i64;
792    let _ = 1f64 as u8;
793    let _ = 1f64 as u16;
794    let _ = 1f64 as u32;
795    let _ = 1f64 as u64;
796    let _ = 1f64 as f32;
797    let _ = 1f64 as f64;
798}
799"#,
800        );
801    }
802
803    #[test]
804    fn unsized_struct_cast() {
805        check_diagnostics(
806            r#"
807//- minicore: sized
808pub struct Data([u8]);
809
810fn foo(x: &[u8]) {
811    let _: *const Data = x as *const Data;
812                       //^^^^^^^^^^^^^^^^ error: casting `&[u8]` as `*const Data` is invalid
813}
814"#,
815        );
816    }
817
818    #[test]
819    fn unsupported_cast() {
820        check_diagnostics(
821            r#"
822//- minicore: sized
823struct A;
824
825fn main() {
826    let _ = 1.0 as *const A;
827          //^^^^^^^^^^^^^^^ error: casting `f64` as `*const A` is invalid
828}
829"#,
830        );
831    }
832
833    #[test]
834    fn issue_17897() {
835        check_diagnostics(
836            r#"
837//- minicore: sized
838fn main() {
839    _ = ((), ()) as ();
840      //^^^^^^^^^^^^^^ error: non-primitive cast: `((), ())` as `()`
841}
842"#,
843        );
844    }
845
846    #[test]
847    fn rustc_issue_10991() {
848        check_diagnostics(
849            r#"
850//- minicore: sized
851fn main() {
852    let nil = ();
853    let _t = nil as usize;
854           //^^^^^^^^^^^^ error: non-primitive cast: `()` as `usize`
855}
856"#,
857        );
858    }
859
860    #[test]
861    fn rustc_issue_17444() {
862        check_diagnostics(
863            r#"
864//- minicore: sized
865enum Test {
866    Foo = 0
867}
868
869fn main() {
870    let _x = Test::Foo as *const isize;
871           //^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `Test` as `*const isize` is invalid
872}
873"#,
874        );
875    }
876
877    #[test]
878    fn rustc_issue_43825() {
879        check_diagnostics(
880            r#"
881//- minicore: sized
882fn main() {
883    let error = error;
884              //^^^^^ error: no such value in this scope
885
886    0 as f32;
887    0.0 as u32;
888}
889"#,
890        );
891    }
892
893    #[test]
894    fn rustc_issue_84213() {
895        check_diagnostics(
896            r#"
897//- minicore: sized
898struct Something {
899    pub field: u32,
900}
901
902fn main() {
903    let mut something = Something { field: 1337 };
904    let _ = something.field;
905
906    let _pointer_to_something = something as *const Something;
907                              //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `Something` as `*const Something`
908
909    let _mut_pointer_to_something = something as *mut Something;
910                                  //^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `Something` as `*mut Something`
911}
912"#,
913        );
914
915        // Fixed
916        check_diagnostics(
917            r#"
918//- minicore: sized
919struct Something {
920    pub field: u32,
921}
922
923fn main() {
924    let mut something = Something { field: 1337 };
925    let _ = something.field;
926
927    let _pointer_to_something = &something as *const Something;
928
929    let _mut_pointer_to_something = &mut something as *mut Something;
930}
931"#,
932        );
933    }
934
935    #[test]
936    fn rustc_issue_88621() {
937        check_diagnostics(
938            r#"
939//- minicore: sized
940#[repr(u8)]
941enum Kind2 {
942    Foo() = 1,
943    Bar{} = 2,
944    Baz = 3,
945}
946
947fn main() {
948    let _ = Kind2::Foo() as u8;
949          //^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `Kind2` as `u8`
950}
951"#,
952        );
953    }
954
955    #[test]
956    fn rustc_issue_89497() {
957        check_diagnostics(
958            r#"
959//- minicore: sized
960fn main() {
961    let pointer: usize = &1_i32 as *const i32 as usize;
962    let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
963                                          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&'static i32`
964}
965"#,
966        );
967
968        // Fixed
969        check_diagnostics(
970            r#"
971//- minicore: sized
972fn main() {
973    let pointer: usize = &1_i32 as *const i32 as usize;
974    let _reference: &'static i32 = unsafe { &*(pointer as *const i32) };
975}
976"#,
977        );
978    }
979
980    #[test]
981    fn rustc_issue_106883() {
982        check_diagnostics_with_disabled(
983            r#"
984//- minicore: sized, deref
985use core::ops::Deref;
986
987struct Foo;
988
989impl Deref for Foo {
990    type Target = [u8];
991
992    fn deref(&self) -> &Self::Target {
993        &[]
994    }
995}
996
997fn main() {
998    let _ = "foo" as bool;
999          //^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first
1000
1001    let _ = Foo as bool;
1002          //^^^^^^^^^^^ error: non-primitive cast: `Foo` as `bool`
1003}
1004
1005fn _slice(bar: &[i32]) -> bool {
1006    bar as bool
1007  //^^^^^^^^^^^ error: casting `&[i32]` as `bool` is invalid: needs casting through a raw pointer first
1008}
1009"#,
1010            &["E0308"],
1011        );
1012    }
1013
1014    #[test]
1015    fn trait_upcasting() {
1016        check_diagnostics(
1017            r#"
1018//- minicore: coerce_unsized, dispatch_from_dyn
1019#![feature(trait_upcasting)]
1020trait Foo {}
1021trait Bar: Foo {}
1022
1023impl dyn Bar {
1024    fn bar(&self) {
1025        _ = self as &dyn Foo;
1026    }
1027}
1028"#,
1029        );
1030    }
1031
1032    #[test]
1033    fn issue_18047() {
1034        check_diagnostics(
1035            r#"
1036//- minicore: coerce_unsized, dispatch_from_dyn
1037trait LocalFrom<T> {
1038    fn from(_: T) -> Self;
1039}
1040trait LocalInto<T> {
1041    fn into(self) -> T;
1042}
1043
1044impl<T, U> LocalInto<U> for T
1045where
1046    U: LocalFrom<T>,
1047{
1048    fn into(self) -> U {
1049        U::from(self)
1050    }
1051}
1052
1053impl<T> LocalFrom<T> for T {
1054    fn from(t: T) -> T {
1055        t
1056    }
1057}
1058
1059trait Foo {
1060    type ErrorType;
1061    type Assoc;
1062}
1063
1064trait Bar {
1065    type ErrorType;
1066}
1067
1068struct ErrorLike;
1069
1070impl<E> LocalFrom<E> for ErrorLike
1071where
1072    E: Trait + 'static,
1073{
1074    fn from(_: E) -> Self {
1075        loop {}
1076    }
1077}
1078
1079trait Baz {
1080    type Assoc: Bar;
1081    type Error: LocalInto<ErrorLike>;
1082}
1083
1084impl<T, U> Baz for T
1085where
1086    T: Foo<Assoc = U>,
1087    T::ErrorType: LocalInto<ErrorLike>,
1088    U: Bar,
1089    <U as Bar>::ErrorType: LocalInto<ErrorLike>,
1090{
1091    type Assoc = U;
1092    type Error = T::ErrorType;
1093}
1094struct S;
1095trait Trait {}
1096impl Trait for S {}
1097
1098fn test<T>()
1099where
1100    T: Baz,
1101    T::Assoc: 'static,
1102{
1103    let _ = &S as &dyn Trait;
1104}
1105"#,
1106        );
1107    }
1108
1109    #[test]
1110    fn cast_literal_to_char() {
1111        check_diagnostics(
1112            r#"
1113fn foo() {
1114    0 as char;
1115}
1116            "#,
1117        );
1118    }
1119
1120    #[test]
1121    fn cast_isize_to_infer_pointer() {
1122        check_diagnostics(
1123            r#"
1124//- minicore: coerce_unsized
1125struct Foo {}
1126
1127struct Wrap<'a>(&'a mut Foo);
1128
1129fn main() {
1130    let lparam: isize = 0;
1131
1132    let _wrap = Wrap(unsafe { &mut *(lparam as *mut _) });
1133}
1134        "#,
1135        );
1136    }
1137
1138    #[test]
1139    fn regression_18682() {
1140        check_diagnostics(
1141            r#"
1142//- minicore: coerce_unsized
1143struct Flexible {
1144    body: [u8],
1145}
1146
1147trait Field {
1148    type Type: ?Sized;
1149}
1150
1151impl Field for Flexible {
1152    type Type = [u8];
1153}
1154
1155trait KnownLayout {
1156    type MaybeUninit: ?Sized;
1157}
1158
1159
1160impl<T> KnownLayout for [T] {
1161    type MaybeUninit = [T];
1162}
1163
1164struct ZerocopyKnownLayoutMaybeUninit(<<Flexible as Field>::Type as KnownLayout>::MaybeUninit);
1165
1166fn test(ptr: *mut [u8]) -> *mut ZerocopyKnownLayoutMaybeUninit {
1167    ptr as *mut _
1168}
1169"#,
1170        );
1171    }
1172
1173    #[test]
1174    fn regression_19431() {
1175        check_diagnostics(
1176            r#"
1177//- minicore: coerce_unsized
1178struct Dst([u8]);
1179
1180struct Struct {
1181    body: Dst,
1182}
1183
1184trait Field {
1185    type Type: ?Sized;
1186}
1187
1188impl Field for Struct {
1189    type Type = Dst;
1190}
1191
1192trait KnownLayout {
1193    type MaybeUninit: ?Sized;
1194    type PointerMetadata;
1195}
1196
1197impl<T> KnownLayout for [T] {
1198    type MaybeUninit = [T];
1199    type PointerMetadata = usize;
1200}
1201
1202impl KnownLayout for Dst {
1203    type MaybeUninit = Dst;
1204    type PointerMetadata = <[u8] as KnownLayout>::PointerMetadata;
1205}
1206
1207struct ZerocopyKnownLayoutMaybeUninit(<<Struct as Field>::Type as KnownLayout>::MaybeUninit);
1208
1209fn test(ptr: *mut ZerocopyKnownLayoutMaybeUninit) -> *mut <<Struct as Field>::Type as KnownLayout>::MaybeUninit {
1210    ptr as *mut _
1211}
1212"#,
1213        );
1214    }
1215}