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(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 };
103 Diagnostic::new(code, message, display_range).stable()
104}
105
106pub(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]
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 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 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}