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