]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_infer/src/infer/error_reporting/note.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / note.rs
1 use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
2 use crate::infer::{self, InferCtxt, SubregionOrigin};
3 use rustc_errors::{struct_span_err, DiagnosticBuilder};
4 use rustc_middle::ty::error::TypeError;
5 use rustc_middle::ty::{self, Region};
6
7 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
8 pub(super) fn note_region_origin(
9 &self,
10 err: &mut DiagnosticBuilder<'_>,
11 origin: &SubregionOrigin<'tcx>,
12 ) {
13 let mut label_or_note = |span, msg| {
14 let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count();
15 let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count();
16 let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span);
17 if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
18 err.span_label(span, msg);
19 } else if span_is_primary && expanded_sub_count == 0 {
20 err.note(msg);
21 } else {
22 err.span_note(span, msg);
23 }
24 };
25 match *origin {
26 infer::Subtype(ref trace) => {
27 if let Some((expected, found)) = self.values_str(&trace.values) {
28 label_or_note(
29 trace.cause.span,
30 &format!("...so that the {}", trace.cause.as_requirement_str()),
31 );
32
33 err.note_expected_found(&"", expected, &"", found);
34 } else {
35 // FIXME: this really should be handled at some earlier stage. Our
36 // handling of region checking when type errors are present is
37 // *terrible*.
38
39 label_or_note(
40 trace.cause.span,
41 &format!("...so that {}", trace.cause.as_requirement_str()),
42 );
43 }
44 }
45 infer::Reborrow(span) => {
46 label_or_note(span, "...so that reference does not outlive borrowed content");
47 }
48 infer::ReborrowUpvar(span, ref upvar_id) => {
49 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
50 label_or_note(span, &format!("...so that closure can access `{}`", var_name));
51 }
52 infer::RelateObjectBound(span) => {
53 label_or_note(span, "...so that it can be closed over into an object");
54 }
55 infer::CallReturn(span) => {
56 label_or_note(span, "...so that return value is valid for the call");
57 }
58 infer::DataBorrowed(ty, span) => {
59 label_or_note(
60 span,
61 &format!(
62 "...so that the type `{}` is not borrowed for too long",
63 self.ty_to_string(ty)
64 ),
65 );
66 }
67 infer::ReferenceOutlivesReferent(ty, span) => {
68 label_or_note(
69 span,
70 &format!(
71 "...so that the reference type `{}` does not outlive the data it points at",
72 self.ty_to_string(ty)
73 ),
74 );
75 }
76 infer::RelateParamBound(span, t) => {
77 label_or_note(
78 span,
79 &format!(
80 "...so that the type `{}` will meet its required lifetime bounds",
81 self.ty_to_string(t)
82 ),
83 );
84 }
85 infer::RelateRegionParamBound(span) => {
86 label_or_note(
87 span,
88 "...so that the declared lifetime parameter bounds are satisfied",
89 );
90 }
91 infer::CompareImplMethodObligation { span, .. } => {
92 label_or_note(
93 span,
94 "...so that the definition in impl matches the definition from the trait",
95 );
96 }
97 }
98 }
99
100 pub(super) fn report_concrete_failure(
101 &self,
102 origin: SubregionOrigin<'tcx>,
103 sub: Region<'tcx>,
104 sup: Region<'tcx>,
105 ) -> DiagnosticBuilder<'tcx> {
106 match origin {
107 infer::Subtype(box trace) => {
108 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
109 let mut err = self.report_and_explain_type_error(trace, &terr);
110 note_and_explain_region(self.tcx, &mut err, "", sup, "...");
111 note_and_explain_region(
112 self.tcx,
113 &mut err,
114 "...does not necessarily outlive ",
115 sub,
116 "",
117 );
118 err
119 }
120 infer::Reborrow(span) => {
121 let mut err = struct_span_err!(
122 self.tcx.sess,
123 span,
124 E0312,
125 "lifetime of reference outlives lifetime of borrowed content..."
126 );
127 note_and_explain_region(
128 self.tcx,
129 &mut err,
130 "...the reference is valid for ",
131 sub,
132 "...",
133 );
134 note_and_explain_region(
135 self.tcx,
136 &mut err,
137 "...but the borrowed content is only valid for ",
138 sup,
139 "",
140 );
141 err
142 }
143 infer::ReborrowUpvar(span, ref upvar_id) => {
144 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
145 let mut err = struct_span_err!(
146 self.tcx.sess,
147 span,
148 E0313,
149 "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
150 var_name
151 );
152 note_and_explain_region(
153 self.tcx,
154 &mut err,
155 "...the borrowed pointer is valid for ",
156 sub,
157 "...",
158 );
159 note_and_explain_region(
160 self.tcx,
161 &mut err,
162 &format!("...but `{}` is only valid for ", var_name),
163 sup,
164 "",
165 );
166 err
167 }
168 infer::RelateObjectBound(span) => {
169 let mut err = struct_span_err!(
170 self.tcx.sess,
171 span,
172 E0476,
173 "lifetime of the source pointer does not outlive lifetime bound of the \
174 object type"
175 );
176 note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
177 note_and_explain_region(
178 self.tcx,
179 &mut err,
180 "source pointer is only valid for ",
181 sup,
182 "",
183 );
184 err
185 }
186 infer::RelateParamBound(span, ty) => {
187 let mut err = struct_span_err!(
188 self.tcx.sess,
189 span,
190 E0477,
191 "the type `{}` does not fulfill the required lifetime",
192 self.ty_to_string(ty)
193 );
194 match *sub {
195 ty::ReStatic => {
196 note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
197 }
198 _ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
199 }
200 err
201 }
202 infer::RelateRegionParamBound(span) => {
203 let mut err =
204 struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
205 note_and_explain_region(
206 self.tcx,
207 &mut err,
208 "lifetime parameter instantiated with ",
209 sup,
210 "",
211 );
212 note_and_explain_region(
213 self.tcx,
214 &mut err,
215 "but lifetime parameter must outlive ",
216 sub,
217 "",
218 );
219 err
220 }
221 infer::CallReturn(span) => {
222 let mut err = struct_span_err!(
223 self.tcx.sess,
224 span,
225 E0482,
226 "lifetime of return value does not outlive the function call"
227 );
228 note_and_explain_region(
229 self.tcx,
230 &mut err,
231 "the return value is only valid for ",
232 sup,
233 "",
234 );
235 err
236 }
237 infer::DataBorrowed(ty, span) => {
238 let mut err = struct_span_err!(
239 self.tcx.sess,
240 span,
241 E0490,
242 "a value of type `{}` is borrowed for too long",
243 self.ty_to_string(ty)
244 );
245 note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
246 note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
247 err
248 }
249 infer::ReferenceOutlivesReferent(ty, span) => {
250 let mut err = struct_span_err!(
251 self.tcx.sess,
252 span,
253 E0491,
254 "in type `{}`, reference has a longer lifetime than the data it references",
255 self.ty_to_string(ty)
256 );
257 note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
258 note_and_explain_region(
259 self.tcx,
260 &mut err,
261 "but the referenced data is only valid for ",
262 sup,
263 "",
264 );
265 err
266 }
267 infer::CompareImplMethodObligation {
268 span,
269 item_name,
270 impl_item_def_id,
271 trait_item_def_id,
272 } => self.report_extra_impl_obligation(
273 span,
274 item_name,
275 impl_item_def_id,
276 trait_item_def_id,
277 &format!("`{}: {}`", sup, sub),
278 ),
279 }
280 }
281
282 pub(super) fn report_placeholder_failure(
283 &self,
284 placeholder_origin: SubregionOrigin<'tcx>,
285 sub: Region<'tcx>,
286 sup: Region<'tcx>,
287 ) -> DiagnosticBuilder<'tcx> {
288 // I can't think how to do better than this right now. -nikomatsakis
289 match placeholder_origin {
290 infer::Subtype(box trace) => {
291 let terr = TypeError::RegionsPlaceholderMismatch;
292 self.report_and_explain_type_error(trace, &terr)
293 }
294
295 _ => self.report_concrete_failure(placeholder_origin, sub, sup),
296 }
297 }
298 }