Skip to main content

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