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
18pub(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 };
110 Diagnostic::new(code, message, display_range).stable()
111}
112
113pub(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]
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 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 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}