]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | use rustc::session::Session; |
2 | use syntax_pos::Span; | |
b7449926 | 3 | use errors::{Applicability, DiagnosticId, DiagnosticBuilder}; |
2c00a5a8 XL |
4 | use rustc::ty::{Ty, TypeFoldable}; |
5 | ||
60c5eb7d XL |
6 | use rustc_error_codes::*; |
7 | ||
2c00a5a8 XL |
8 | pub trait StructuredDiagnostic<'tcx> { |
9 | fn session(&self) -> &Session; | |
10 | ||
11 | fn code(&self) -> DiagnosticId; | |
12 | ||
13 | fn common(&self) -> DiagnosticBuilder<'tcx>; | |
14 | ||
15 | fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { | |
16 | let err = self.common(); | |
17 | if self.session().teach(&self.code()) { | |
18 | self.extended(err) | |
19 | } else { | |
20 | self.regular(err) | |
21 | } | |
22 | } | |
23 | ||
24 | fn regular(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { | |
25 | err | |
26 | } | |
27 | ||
28 | fn extended(&self, err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { | |
29 | err | |
30 | } | |
31 | } | |
32 | ||
33 | pub struct VariadicError<'tcx> { | |
34 | sess: &'tcx Session, | |
35 | span: Span, | |
36 | t: Ty<'tcx>, | |
37 | cast_ty: &'tcx str, | |
38 | } | |
39 | ||
40 | impl<'tcx> VariadicError<'tcx> { | |
41 | pub fn new(sess: &'tcx Session, | |
42 | span: Span, | |
43 | t: Ty<'tcx>, | |
44 | cast_ty: &'tcx str) -> VariadicError<'tcx> { | |
45 | VariadicError { sess, span, t, cast_ty } | |
46 | } | |
47 | } | |
48 | ||
49 | impl<'tcx> StructuredDiagnostic<'tcx> for VariadicError<'tcx> { | |
50 | fn session(&self) -> &Session { self.sess } | |
51 | ||
52 | fn code(&self) -> DiagnosticId { | |
e1599b0c | 53 | syntax::diagnostic_used!(E0617); |
2c00a5a8 XL |
54 | DiagnosticId::Error("E0617".to_owned()) |
55 | } | |
56 | ||
57 | fn common(&self) -> DiagnosticBuilder<'tcx> { | |
58 | let mut err = if self.t.references_error() { | |
59 | self.sess.diagnostic().struct_dummy() | |
60 | } else { | |
61 | self.sess.struct_span_fatal_with_code( | |
62 | self.span, | |
63 | &format!("can't pass `{}` to variadic function", self.t), | |
64 | self.code(), | |
65 | ) | |
66 | }; | |
b7449926 | 67 | if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) { |
9fa01778 | 68 | err.span_suggestion( |
b7449926 XL |
69 | self.span, |
70 | &format!("cast the value to `{}`", self.cast_ty), | |
71 | format!("{} as {}", snippet, self.cast_ty), | |
72 | Applicability::MachineApplicable, | |
73 | ); | |
2c00a5a8 XL |
74 | } else { |
75 | err.help(&format!("cast the value to `{}`", self.cast_ty)); | |
76 | } | |
77 | err | |
78 | } | |
79 | ||
80 | fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { | |
81 | err.note(&format!("certain types, like `{}`, must be cast before passing them to a \ | |
82 | variadic function, because of arcane ABI rules dictated by the C \ | |
83 | standard", | |
84 | self.t)); | |
85 | err | |
86 | } | |
87 | } | |
88 | ||
89 | pub struct SizedUnsizedCastError<'tcx> { | |
90 | sess: &'tcx Session, | |
91 | span: Span, | |
92 | expr_ty: Ty<'tcx>, | |
93 | cast_ty: String, | |
94 | } | |
95 | ||
96 | impl<'tcx> SizedUnsizedCastError<'tcx> { | |
97 | pub fn new(sess: &'tcx Session, | |
98 | span: Span, | |
99 | expr_ty: Ty<'tcx>, | |
100 | cast_ty: String) -> SizedUnsizedCastError<'tcx> { | |
101 | SizedUnsizedCastError { sess, span, expr_ty, cast_ty } | |
102 | } | |
103 | } | |
104 | ||
105 | impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCastError<'tcx> { | |
106 | fn session(&self) -> &Session { self.sess } | |
107 | ||
108 | fn code(&self) -> DiagnosticId { | |
e1599b0c | 109 | syntax::diagnostic_used!(E0607); |
2c00a5a8 XL |
110 | DiagnosticId::Error("E0607".to_owned()) |
111 | } | |
112 | ||
113 | fn common(&self) -> DiagnosticBuilder<'tcx> { | |
114 | if self.expr_ty.references_error() { | |
115 | self.sess.diagnostic().struct_dummy() | |
116 | } else { | |
117 | self.sess.struct_span_fatal_with_code( | |
118 | self.span, | |
119 | &format!("cannot cast thin pointer `{}` to fat pointer `{}`", | |
120 | self.expr_ty, | |
121 | self.cast_ty), | |
122 | self.code(), | |
123 | ) | |
124 | } | |
125 | } | |
126 | ||
127 | fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx> { | |
128 | err.help( | |
129 | "Thin pointers are \"simple\" pointers: they are purely a reference to a | |
130 | memory address. | |
131 | ||
132 | Fat pointers are pointers referencing \"Dynamically Sized Types\" (also | |
133 | called DST). DST don't have a statically known size, therefore they can | |
134 | only exist behind some kind of pointers that contain additional | |
135 | information. Slices and trait objects are DSTs. In the case of slices, | |
136 | the additional information the fat pointer holds is their size. | |
137 | ||
138 | To fix this error, don't try to cast directly between thin and fat | |
139 | pointers. | |
140 | ||
141 | For more information about casts, take a look at The Book: | |
9fa01778 | 142 | https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions"); |
2c00a5a8 XL |
143 | err |
144 | } | |
145 | } |