]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/structured_errors.rs
Rollup merge of #66633 - GuillaumeGomez:err-codes-cleanup, r=Dylan-DPC
[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 use rustc_error_codes::*;
7
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 {
53         syntax::diagnostic_used!(E0617);
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         };
67         if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
68             err.span_suggestion(
69                 self.span,
70                 &format!("cast the value to `{}`", self.cast_ty),
71                 format!("{} as {}", snippet, self.cast_ty),
72                 Applicability::MachineApplicable,
73             );
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 {
109         syntax::diagnostic_used!(E0607);
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:
142 https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions");
143         err
144     }
145 }