1 //! Error Reporting Code for the inference engine
2 //!
3 //! Because of the way inference, and in particular region inference,
4 //! works, it often happens that errors are not detected until far after
5 //! the relevant line of code has been type-checked. Therefore, there is
6 //! an elaborate system to track why a particular constraint in the
7 //! inference graph arose so that we can explain to the user what gave
8 //! rise to a particular error.
9 //!
10 //! The system is based around a set of "origin" types. An "origin" is the
11 //! reason that a constraint or inference variable arose. There are
12 //! different "origin" enums for different kinds of constraints/variables
13 //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
14 //! a span, but also more information so that we can generate a meaningful
15 //! error message.
16 //!
17 //! Having a catalog of all the different reasons an error can arise is
18 //! also useful for other reasons, like cross-referencing FAQs etc, though
19 //! we are not really taking advantage of this yet.
20 //!
21 //! # Region Inference
22 //!
23 //! Region inference is particularly tricky because it always succeeds "in
24 //! the moment" and simply registers a constraint. Then, at the end, we
25 //! can compute the full graph and report errors, so we need to be able to
26 //! store and later report what gave rise to the conflicting constraints.
27 //!
28 //! # Subtype Trace
29 //!
30 //! Determining whether `T1 <: T2` often involves a number of subtypes and
31 //! subconstraints along the way. A "TypeTrace" is an extended version
32 //! of an origin that traces the types and other values that were being
33 //! compared. It is not necessarily comprehensive (in fact, at the time of
34 //! this writing it only tracks the root values being compared) but I'd
35 //! like to extend it to include significant "waypoints". For example, if
36 //! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
37 //! <: T4` fails, I'd like the trace to include enough information to say
38 //! "in the 2nd element of the tuple". Similarly, failures when comparing
39 //! arguments or return types in fn types should be able to cite the
40 //! specific position, etc.
41 //!
42 //! # Reality vs plan
43 //!
44 //! Of course, there is still a LOT of code in typeck that has yet to be
45 //! ported to this system, and which relies on string concatenation at the
46 //! time of error detection.
47
48 use super::lexical_region_resolve::RegionResolutionError;
49 use super::region_constraints::GenericKind;
50 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
51
52 use crate::infer;
53 use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
54 use crate::traits::error_reporting::report_object_safety_error;
55 use crate::traits::{
56 IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
57 StatementAsExpression,
58 };
59
60 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
61 use rustc_errors::{pluralize, struct_span_err};
62 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
63 use rustc_hir as hir;
64 use rustc_hir::def_id::DefId;
65 use rustc_hir::lang_items::LangItem;
66 use rustc_hir::{Item, ItemKind, Node};
67 use rustc_middle::dep_graph::DepContext;
68 use rustc_middle::ty::error::TypeError;
69 use rustc_middle::ty::{
70 self,
71 subst::{GenericArgKind, Subst, SubstsRef},
72 Region, Ty, TyCtxt, TypeFoldable,
73 };
74 use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span};
75 use rustc_target::spec::abi;
76 use std::ops::ControlFlow;
77 use std::{cmp, fmt, iter};
78
79 mod note;
80
81 mod need_type_info;
82 pub use need_type_info::TypeAnnotationNeeded;
83
84 pub mod nice_region_error;
85
note_and_explain_region( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, region: ty::Region<'tcx>, suffix: &str, alt_span: Option<Span>, )86 pub(super) fn note_and_explain_region(
87 tcx: TyCtxt<'tcx>,
88 err: &mut DiagnosticBuilder<'_>,
89 prefix: &str,
90 region: ty::Region<'tcx>,
91 suffix: &str,
92 alt_span: Option<Span>,
93 ) {
94 let (description, span) = match *region {
95 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
96 msg_span_from_free_region(tcx, region, alt_span)
97 }
98
99 ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), alt_span),
100
101 // uh oh, hope no user ever sees THIS
102 ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), alt_span),
103
104 ty::RePlaceholder(_) => return,
105
106 // FIXME(#13998) RePlaceholder should probably print like
107 // ReFree rather than dumping Debug output on the user.
108 //
109 // We shouldn't really be having unification failures with ReVar
110 // and ReLateBound though.
111 ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
112 (format!("lifetime {:?}", region), alt_span)
113 }
114 };
115
116 emit_msg_span(err, prefix, description, span, suffix);
117 }
118
explain_free_region( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, region: ty::Region<'tcx>, suffix: &str, )119 fn explain_free_region(
120 tcx: TyCtxt<'tcx>,
121 err: &mut DiagnosticBuilder<'_>,
122 prefix: &str,
123 region: ty::Region<'tcx>,
124 suffix: &str,
125 ) {
126 let (description, span) = msg_span_from_free_region(tcx, region, None);
127
128 label_msg_span(err, prefix, description, span, suffix);
129 }
130
msg_span_from_free_region( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, alt_span: Option<Span>, ) -> (String, Option<Span>)131 fn msg_span_from_free_region(
132 tcx: TyCtxt<'tcx>,
133 region: ty::Region<'tcx>,
134 alt_span: Option<Span>,
135 ) -> (String, Option<Span>) {
136 match *region {
137 ty::ReEarlyBound(_) | ty::ReFree(_) => {
138 let (msg, span) = msg_span_from_early_bound_and_free_regions(tcx, region);
139 (msg, Some(span))
140 }
141 ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
142 ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), alt_span),
143 ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), alt_span),
144 _ => bug!("{:?}", region),
145 }
146 }
147
msg_span_from_early_bound_and_free_regions( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, ) -> (String, Span)148 fn msg_span_from_early_bound_and_free_regions(
149 tcx: TyCtxt<'tcx>,
150 region: ty::Region<'tcx>,
151 ) -> (String, Span) {
152 let sm = tcx.sess.source_map();
153
154 let scope = region.free_region_binding_scope(tcx);
155 let node = tcx.hir().local_def_id_to_hir_id(scope.expect_local());
156 match *region {
157 ty::ReEarlyBound(ref br) => {
158 let mut sp = sm.guess_head_span(tcx.hir().span(node));
159 if let Some(param) =
160 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
161 {
162 sp = param.span;
163 }
164 (format!("the lifetime `{}` as defined here", br.name), sp)
165 }
166 ty::ReFree(ty::FreeRegion {
167 bound_region: ty::BoundRegionKind::BrNamed(_, name), ..
168 }) => {
169 let mut sp = sm.guess_head_span(tcx.hir().span(node));
170 if let Some(param) =
171 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
172 {
173 sp = param.span;
174 }
175 (format!("the lifetime `{}` as defined here", name), sp)
176 }
177 ty::ReFree(ref fr) => match fr.bound_region {
178 ty::BrAnon(idx) => {
179 if let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) {
180 ("the anonymous lifetime defined here".to_string(), ty.span)
181 } else {
182 (
183 format!("the anonymous lifetime #{} defined here", idx + 1),
184 tcx.hir().span(node),
185 )
186 }
187 }
188 _ => (
189 format!("the lifetime `{}` as defined here", region),
190 sm.guess_head_span(tcx.hir().span(node)),
191 ),
192 },
193 _ => bug!(),
194 }
195 }
196
emit_msg_span( err: &mut DiagnosticBuilder<'_>, prefix: &str, description: String, span: Option<Span>, suffix: &str, )197 fn emit_msg_span(
198 err: &mut DiagnosticBuilder<'_>,
199 prefix: &str,
200 description: String,
201 span: Option<Span>,
202 suffix: &str,
203 ) {
204 let message = format!("{}{}{}", prefix, description, suffix);
205
206 if let Some(span) = span {
207 err.span_note(span, &message);
208 } else {
209 err.note(&message);
210 }
211 }
212
label_msg_span( err: &mut DiagnosticBuilder<'_>, prefix: &str, description: String, span: Option<Span>, suffix: &str, )213 fn label_msg_span(
214 err: &mut DiagnosticBuilder<'_>,
215 prefix: &str,
216 description: String,
217 span: Option<Span>,
218 suffix: &str,
219 ) {
220 let message = format!("{}{}{}", prefix, description, suffix);
221
222 if let Some(span) = span {
223 err.span_label(span, &message);
224 } else {
225 err.note(&message);
226 }
227 }
228
unexpected_hidden_region_diagnostic( tcx: TyCtxt<'tcx>, span: Span, hidden_ty: Ty<'tcx>, hidden_region: ty::Region<'tcx>, ) -> DiagnosticBuilder<'tcx>229 pub fn unexpected_hidden_region_diagnostic(
230 tcx: TyCtxt<'tcx>,
231 span: Span,
232 hidden_ty: Ty<'tcx>,
233 hidden_region: ty::Region<'tcx>,
234 ) -> DiagnosticBuilder<'tcx> {
235 let mut err = struct_span_err!(
236 tcx.sess,
237 span,
238 E0700,
239 "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
240 );
241
242 // Explain the region we are capturing.
243 match hidden_region {
244 ty::ReEmpty(ty::UniverseIndex::ROOT) => {
245 // All lifetimes shorter than the function body are `empty` in
246 // lexical region resolution. The default explanation of "an empty
247 // lifetime" isn't really accurate here.
248 let message = format!(
249 "hidden type `{}` captures lifetime smaller than the function body",
250 hidden_ty
251 );
252 err.span_note(span, &message);
253 }
254 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
255 // Assuming regionck succeeded (*), we ought to always be
256 // capturing *some* region from the fn header, and hence it
257 // ought to be free. So under normal circumstances, we will go
258 // down this path which gives a decent human readable
259 // explanation.
260 //
261 // (*) if not, the `tainted_by_errors` field would be set to
262 // `Some(ErrorReported)` in any case, so we wouldn't be here at all.
263 explain_free_region(
264 tcx,
265 &mut err,
266 &format!("hidden type `{}` captures ", hidden_ty),
267 hidden_region,
268 "",
269 );
270 if let Some(reg_info) = tcx.is_suitable_region(hidden_region) {
271 let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id);
272 nice_region_error::suggest_new_region_bound(
273 tcx,
274 &mut err,
275 fn_returns,
276 hidden_region.to_string(),
277 None,
278 format!("captures {}", hidden_region),
279 None,
280 )
281 }
282 }
283 _ => {
284 // Ugh. This is a painful case: the hidden region is not one
285 // that we can easily summarize or explain. This can happen
286 // in a case like
287 // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
288 //
289 // ```
290 // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
291 // if condition() { a } else { b }
292 // }
293 // ```
294 //
295 // Here the captured lifetime is the intersection of `'a` and
296 // `'b`, which we can't quite express.
297
298 // We can at least report a really cryptic error for now.
299 note_and_explain_region(
300 tcx,
301 &mut err,
302 &format!("hidden type `{}` captures ", hidden_ty),
303 hidden_region,
304 "",
305 None,
306 );
307 }
308 }
309
310 err
311 }
312
313 /// Structurally compares two types, modulo any inference variables.
314 ///
315 /// Returns `true` if two types are equal, or if one type is an inference variable compatible
316 /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
317 /// FloatVar inference type are compatible with themselves or their concrete types (Int and
318 /// Float types, respectively). When comparing two ADTs, these rules apply recursively.
same_type_modulo_infer(a: Ty<'tcx>, b: Ty<'ctx>) -> bool319 pub fn same_type_modulo_infer(a: Ty<'tcx>, b: Ty<'ctx>) -> bool {
320 match (&a.kind(), &b.kind()) {
321 (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => {
322 if did_a != did_b {
323 return false;
324 }
325
326 substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type_modulo_infer(a, b))
327 }
328 (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
329 | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)))
330 | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
331 | (
332 &ty::Infer(ty::InferTy::FloatVar(_)),
333 &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
334 )
335 | (&ty::Infer(ty::InferTy::TyVar(_)), _)
336 | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
337 _ => a == b,
338 }
339 }
340
341 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)342 pub fn report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>) {
343 debug!("report_region_errors(): {} errors to start", errors.len());
344
345 // try to pre-process the errors, which will group some of them
346 // together into a `ProcessedErrors` group:
347 let errors = self.process_errors(errors);
348
349 debug!("report_region_errors: {} errors after preprocessing", errors.len());
350
351 for error in errors {
352 debug!("report_region_errors: error = {:?}", error);
353
354 if !self.try_report_nice_region_error(&error) {
355 match error.clone() {
356 // These errors could indicate all manner of different
357 // problems with many different solutions. Rather
358 // than generate a "one size fits all" error, what we
359 // attempt to do is go through a number of specific
360 // scenarios and try to find the best way to present
361 // the error. If all of these fails, we fall back to a rather
362 // general bit of code that displays the error information
363 RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
364 if sub.is_placeholder() || sup.is_placeholder() {
365 self.report_placeholder_failure(origin, sub, sup).emit();
366 } else {
367 self.report_concrete_failure(origin, sub, sup).emit();
368 }
369 }
370
371 RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
372 self.report_generic_bound_failure(
373 origin.span(),
374 Some(origin),
375 param_ty,
376 sub,
377 );
378 }
379
380 RegionResolutionError::SubSupConflict(
381 _,
382 var_origin,
383 sub_origin,
384 sub_r,
385 sup_origin,
386 sup_r,
387 ) => {
388 if sub_r.is_placeholder() {
389 self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
390 } else if sup_r.is_placeholder() {
391 self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
392 } else {
393 self.report_sub_sup_conflict(
394 var_origin, sub_origin, sub_r, sup_origin, sup_r,
395 );
396 }
397 }
398
399 RegionResolutionError::UpperBoundUniverseConflict(
400 _,
401 _,
402 var_universe,
403 sup_origin,
404 sup_r,
405 ) => {
406 assert!(sup_r.is_placeholder());
407
408 // Make a dummy value for the "sub region" --
409 // this is the initial value of the
410 // placeholder. In practice, we expect more
411 // tailored errors that don't really use this
412 // value.
413 let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
414
415 self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
416 }
417 }
418 }
419 }
420 }
421
422 // This method goes through all the errors and try to group certain types
423 // of error together, for the purpose of suggesting explicit lifetime
424 // parameters to the user. This is done so that we can have a more
425 // complete view of what lifetimes should be the same.
426 // If the return value is an empty vector, it means that processing
427 // failed (so the return value of this method should not be used).
428 //
429 // The method also attempts to weed out messages that seem like
430 // duplicates that will be unhelpful to the end-user. But
431 // obviously it never weeds out ALL errors.
process_errors( &self, errors: &[RegionResolutionError<'tcx>], ) -> Vec<RegionResolutionError<'tcx>>432 fn process_errors(
433 &self,
434 errors: &[RegionResolutionError<'tcx>],
435 ) -> Vec<RegionResolutionError<'tcx>> {
436 debug!("process_errors()");
437
438 // We want to avoid reporting generic-bound failures if we can
439 // avoid it: these have a very high rate of being unhelpful in
440 // practice. This is because they are basically secondary
441 // checks that test the state of the region graph after the
442 // rest of inference is done, and the other kinds of errors
443 // indicate that the region constraint graph is internally
444 // inconsistent, so these test results are likely to be
445 // meaningless.
446 //
447 // Therefore, we filter them out of the list unless they are
448 // the only thing in the list.
449
450 let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
451 RegionResolutionError::GenericBoundFailure(..) => true,
452 RegionResolutionError::ConcreteFailure(..)
453 | RegionResolutionError::SubSupConflict(..)
454 | RegionResolutionError::UpperBoundUniverseConflict(..) => false,
455 };
456
457 let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
458 errors.to_owned()
459 } else {
460 errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
461 };
462
463 // sort the errors by span, for better error message stability.
464 errors.sort_by_key(|u| match *u {
465 RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
466 RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
467 RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
468 RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
469 });
470 errors
471 }
472
473 /// Adds a note if the types come from similarly named crates
check_and_note_conflicting_crates( &self, err: &mut DiagnosticBuilder<'_>, terr: &TypeError<'tcx>, )474 fn check_and_note_conflicting_crates(
475 &self,
476 err: &mut DiagnosticBuilder<'_>,
477 terr: &TypeError<'tcx>,
478 ) {
479 use hir::def_id::CrateNum;
480 use rustc_hir::definitions::DisambiguatedDefPathData;
481 use ty::print::Printer;
482 use ty::subst::GenericArg;
483
484 struct AbsolutePathPrinter<'tcx> {
485 tcx: TyCtxt<'tcx>,
486 }
487
488 struct NonTrivialPath;
489
490 impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
491 type Error = NonTrivialPath;
492
493 type Path = Vec<String>;
494 type Region = !;
495 type Type = !;
496 type DynExistential = !;
497 type Const = !;
498
499 fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
500 self.tcx
501 }
502
503 fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
504 Err(NonTrivialPath)
505 }
506
507 fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
508 Err(NonTrivialPath)
509 }
510
511 fn print_dyn_existential(
512 self,
513 _predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
514 ) -> Result<Self::DynExistential, Self::Error> {
515 Err(NonTrivialPath)
516 }
517
518 fn print_const(self, _ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
519 Err(NonTrivialPath)
520 }
521
522 fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
523 Ok(vec![self.tcx.crate_name(cnum).to_string()])
524 }
525 fn path_qualified(
526 self,
527 _self_ty: Ty<'tcx>,
528 _trait_ref: Option<ty::TraitRef<'tcx>>,
529 ) -> Result<Self::Path, Self::Error> {
530 Err(NonTrivialPath)
531 }
532
533 fn path_append_impl(
534 self,
535 _print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
536 _disambiguated_data: &DisambiguatedDefPathData,
537 _self_ty: Ty<'tcx>,
538 _trait_ref: Option<ty::TraitRef<'tcx>>,
539 ) -> Result<Self::Path, Self::Error> {
540 Err(NonTrivialPath)
541 }
542 fn path_append(
543 self,
544 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
545 disambiguated_data: &DisambiguatedDefPathData,
546 ) -> Result<Self::Path, Self::Error> {
547 let mut path = print_prefix(self)?;
548 path.push(disambiguated_data.to_string());
549 Ok(path)
550 }
551 fn path_generic_args(
552 self,
553 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
554 _args: &[GenericArg<'tcx>],
555 ) -> Result<Self::Path, Self::Error> {
556 print_prefix(self)
557 }
558 }
559
560 let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
561 // Only external crates, if either is from a local
562 // module we could have false positives
563 if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
564 let abs_path =
565 |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]);
566
567 // We compare strings because DefPath can be different
568 // for imported and non-imported crates
569 let same_path = || -> Result<_, NonTrivialPath> {
570 Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
571 || abs_path(did1)? == abs_path(did2)?)
572 };
573 if same_path().unwrap_or(false) {
574 let crate_name = self.tcx.crate_name(did1.krate);
575 err.note(&format!(
576 "perhaps two different versions of crate `{}` are being used?",
577 crate_name
578 ));
579 }
580 }
581 };
582 match *terr {
583 TypeError::Sorts(ref exp_found) => {
584 // if they are both "path types", there's a chance of ambiguity
585 // due to different versions of the same crate
586 if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
587 (exp_found.expected.kind(), exp_found.found.kind())
588 {
589 report_path_match(err, exp_adt.did, found_adt.did);
590 }
591 }
592 TypeError::Traits(ref exp_found) => {
593 report_path_match(err, exp_found.expected, exp_found.found);
594 }
595 _ => (), // FIXME(#22750) handle traits and stuff
596 }
597 }
598
note_error_origin( &self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>, exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>, terr: &TypeError<'tcx>, )599 fn note_error_origin(
600 &self,
601 err: &mut DiagnosticBuilder<'tcx>,
602 cause: &ObligationCause<'tcx>,
603 exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
604 terr: &TypeError<'tcx>,
605 ) {
606 match cause.code {
607 ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
608 let ty = self.resolve_vars_if_possible(root_ty);
609 if ty.is_suggestable() {
610 // don't show type `_`
611 err.span_label(span, format!("this expression has type `{}`", ty));
612 }
613 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
614 if ty.is_box() && ty.boxed_ty() == found {
615 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
616 err.span_suggestion(
617 span,
618 "consider dereferencing the boxed value",
619 format!("*{}", snippet),
620 Applicability::MachineApplicable,
621 );
622 }
623 }
624 }
625 }
626 ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
627 err.span_label(span, "expected due to this");
628 }
629 ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
630 semi_span,
631 source,
632 ref prior_arms,
633 last_ty,
634 scrut_hir_id,
635 opt_suggest_box_span,
636 arm_span,
637 scrut_span,
638 ..
639 }) => match source {
640 hir::MatchSource::TryDesugar => {
641 if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
642 let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
643 let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
644 let arg_expr = args.first().expect("try desugaring call w/out arg");
645 self.in_progress_typeck_results.and_then(|typeck_results| {
646 typeck_results.borrow().expr_ty_opt(arg_expr)
647 })
648 } else {
649 bug!("try desugaring w/out call expr as scrutinee");
650 };
651
652 match scrut_ty {
653 Some(ty) if expected == ty => {
654 let source_map = self.tcx.sess.source_map();
655 err.span_suggestion(
656 source_map.end_point(cause.span),
657 "try removing this `?`",
658 "".to_string(),
659 Applicability::MachineApplicable,
660 );
661 }
662 _ => {}
663 }
664 }
665 }
666 _ => {
667 // `last_ty` can be `!`, `expected` will have better info when present.
668 let t = self.resolve_vars_if_possible(match exp_found {
669 Some(ty::error::ExpectedFound { expected, .. }) => expected,
670 _ => last_ty,
671 });
672 let source_map = self.tcx.sess.source_map();
673 let mut any_multiline_arm = source_map.is_multiline(arm_span);
674 if prior_arms.len() <= 4 {
675 for sp in prior_arms {
676 any_multiline_arm |= source_map.is_multiline(*sp);
677 err.span_label(*sp, format!("this is found to be of type `{}`", t));
678 }
679 } else if let Some(sp) = prior_arms.last() {
680 any_multiline_arm |= source_map.is_multiline(*sp);
681 err.span_label(
682 *sp,
683 format!("this and all prior arms are found to be of type `{}`", t),
684 );
685 }
686 let outer_error_span = if any_multiline_arm {
687 // Cover just `match` and the scrutinee expression, not
688 // the entire match body, to reduce diagram noise.
689 cause.span.shrink_to_lo().to(scrut_span)
690 } else {
691 cause.span
692 };
693 let msg = "`match` arms have incompatible types";
694 err.span_label(outer_error_span, msg);
695 if let Some((sp, boxed)) = semi_span {
696 if let (StatementAsExpression::NeedsBoxing, [.., prior_arm]) =
697 (boxed, &prior_arms[..])
698 {
699 err.multipart_suggestion(
700 "consider removing this semicolon and boxing the expressions",
701 vec![
702 (prior_arm.shrink_to_lo(), "Box::new(".to_string()),
703 (prior_arm.shrink_to_hi(), ")".to_string()),
704 (arm_span.shrink_to_lo(), "Box::new(".to_string()),
705 (arm_span.shrink_to_hi(), ")".to_string()),
706 (sp, String::new()),
707 ],
708 Applicability::HasPlaceholders,
709 );
710 } else if matches!(boxed, StatementAsExpression::NeedsBoxing) {
711 err.span_suggestion_short(
712 sp,
713 "consider removing this semicolon and boxing the expressions",
714 String::new(),
715 Applicability::MachineApplicable,
716 );
717 } else {
718 err.span_suggestion_short(
719 sp,
720 "consider removing this semicolon",
721 String::new(),
722 Applicability::MachineApplicable,
723 );
724 }
725 }
726 if let Some(ret_sp) = opt_suggest_box_span {
727 // Get return type span and point to it.
728 self.suggest_boxing_for_return_impl_trait(
729 err,
730 ret_sp,
731 prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
732 );
733 }
734 }
735 },
736 ObligationCauseCode::IfExpression(box IfExpressionCause {
737 then,
738 else_sp,
739 outer,
740 semicolon,
741 opt_suggest_box_span,
742 }) => {
743 err.span_label(then, "expected because of this");
744 if let Some(sp) = outer {
745 err.span_label(sp, "`if` and `else` have incompatible types");
746 }
747 if let Some((sp, boxed)) = semicolon {
748 if matches!(boxed, StatementAsExpression::NeedsBoxing) {
749 err.multipart_suggestion(
750 "consider removing this semicolon and boxing the expression",
751 vec![
752 (then.shrink_to_lo(), "Box::new(".to_string()),
753 (then.shrink_to_hi(), ")".to_string()),
754 (else_sp.shrink_to_lo(), "Box::new(".to_string()),
755 (else_sp.shrink_to_hi(), ")".to_string()),
756 (sp, String::new()),
757 ],
758 Applicability::MachineApplicable,
759 );
760 } else {
761 err.span_suggestion_short(
762 sp,
763 "consider removing this semicolon",
764 String::new(),
765 Applicability::MachineApplicable,
766 );
767 }
768 }
769 if let Some(ret_sp) = opt_suggest_box_span {
770 self.suggest_boxing_for_return_impl_trait(
771 err,
772 ret_sp,
773 vec![then, else_sp].into_iter(),
774 );
775 }
776 }
777 ObligationCauseCode::LetElse => {
778 err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
779 err.help("...or use `match` instead of `let...else`");
780 }
781 _ => {
782 if let ObligationCauseCode::BindingObligation(_, binding_span) =
783 cause.code.peel_derives()
784 {
785 if matches!(terr, TypeError::RegionsPlaceholderMismatch) {
786 err.span_note(*binding_span, "the lifetime requirement is introduced here");
787 }
788 }
789 }
790 }
791 }
792
suggest_boxing_for_return_impl_trait( &self, err: &mut DiagnosticBuilder<'tcx>, return_sp: Span, arm_spans: impl Iterator<Item = Span>, )793 fn suggest_boxing_for_return_impl_trait(
794 &self,
795 err: &mut DiagnosticBuilder<'tcx>,
796 return_sp: Span,
797 arm_spans: impl Iterator<Item = Span>,
798 ) {
799 err.multipart_suggestion(
800 "you could change the return type to be a boxed trait object",
801 vec![
802 (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
803 (return_sp.shrink_to_hi(), ">".to_string()),
804 ],
805 Applicability::MaybeIncorrect,
806 );
807 let sugg = arm_spans
808 .flat_map(|sp| {
809 vec![
810 (sp.shrink_to_lo(), "Box::new(".to_string()),
811 (sp.shrink_to_hi(), ")".to_string()),
812 ]
813 .into_iter()
814 })
815 .collect::<Vec<_>>();
816 err.multipart_suggestion(
817 "if you change the return type to expect trait objects, box the returned expressions",
818 sugg,
819 Applicability::MaybeIncorrect,
820 );
821 }
822
823 /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
824 /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
825 /// populate `other_value` with `other_ty`.
826 ///
827 /// ```text
828 /// Foo<Bar<Qux>>
829 /// ^^^^--------^ this is highlighted
830 /// | |
831 /// | this type argument is exactly the same as the other type, not highlighted
832 /// this is highlighted
833 /// Bar<Qux>
834 /// -------- this type is the same as a type argument in the other type, not highlighted
835 /// ```
highlight_outer( &self, value: &mut DiagnosticStyledString, other_value: &mut DiagnosticStyledString, name: String, sub: ty::subst::SubstsRef<'tcx>, pos: usize, other_ty: Ty<'tcx>, )836 fn highlight_outer(
837 &self,
838 value: &mut DiagnosticStyledString,
839 other_value: &mut DiagnosticStyledString,
840 name: String,
841 sub: ty::subst::SubstsRef<'tcx>,
842 pos: usize,
843 other_ty: Ty<'tcx>,
844 ) {
845 // `value` and `other_value` hold two incomplete type representation for display.
846 // `name` is the path of both types being compared. `sub`
847 value.push_highlighted(name);
848 let len = sub.len();
849 if len > 0 {
850 value.push_highlighted("<");
851 }
852
853 // Output the lifetimes for the first type
854 let lifetimes = sub
855 .regions()
856 .map(|lifetime| {
857 let s = lifetime.to_string();
858 if s.is_empty() { "'_".to_string() } else { s }
859 })
860 .collect::<Vec<_>>()
861 .join(", ");
862 if !lifetimes.is_empty() {
863 if sub.regions().count() < len {
864 value.push_normal(lifetimes + ", ");
865 } else {
866 value.push_normal(lifetimes);
867 }
868 }
869
870 // Highlight all the type arguments that aren't at `pos` and compare the type argument at
871 // `pos` and `other_ty`.
872 for (i, type_arg) in sub.types().enumerate() {
873 if i == pos {
874 let values = self.cmp(type_arg, other_ty);
875 value.0.extend((values.0).0);
876 other_value.0.extend((values.1).0);
877 } else {
878 value.push_highlighted(type_arg.to_string());
879 }
880
881 if len > 0 && i != len - 1 {
882 value.push_normal(", ");
883 }
884 }
885 if len > 0 {
886 value.push_highlighted(">");
887 }
888 }
889
890 /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
891 /// as that is the difference to the other type.
892 ///
893 /// For the following code:
894 ///
895 /// ```no_run
896 /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
897 /// ```
898 ///
899 /// The type error output will behave in the following way:
900 ///
901 /// ```text
902 /// Foo<Bar<Qux>>
903 /// ^^^^--------^ this is highlighted
904 /// | |
905 /// | this type argument is exactly the same as the other type, not highlighted
906 /// this is highlighted
907 /// Bar<Qux>
908 /// -------- this type is the same as a type argument in the other type, not highlighted
909 /// ```
cmp_type_arg( &self, mut t1_out: &mut DiagnosticStyledString, mut t2_out: &mut DiagnosticStyledString, path: String, sub: ty::subst::SubstsRef<'tcx>, other_path: String, other_ty: Ty<'tcx>, ) -> Option<()>910 fn cmp_type_arg(
911 &self,
912 mut t1_out: &mut DiagnosticStyledString,
913 mut t2_out: &mut DiagnosticStyledString,
914 path: String,
915 sub: ty::subst::SubstsRef<'tcx>,
916 other_path: String,
917 other_ty: Ty<'tcx>,
918 ) -> Option<()> {
919 for (i, ta) in sub.types().enumerate() {
920 if ta == other_ty {
921 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
922 return Some(());
923 }
924 if let ty::Adt(def, _) = ta.kind() {
925 let path_ = self.tcx.def_path_str(def.did);
926 if path_ == other_path {
927 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
928 return Some(());
929 }
930 }
931 }
932 None
933 }
934
935 /// Adds a `,` to the type representation only if it is appropriate.
push_comma( &self, value: &mut DiagnosticStyledString, other_value: &mut DiagnosticStyledString, len: usize, pos: usize, )936 fn push_comma(
937 &self,
938 value: &mut DiagnosticStyledString,
939 other_value: &mut DiagnosticStyledString,
940 len: usize,
941 pos: usize,
942 ) {
943 if len > 0 && pos != len - 1 {
944 value.push_normal(", ");
945 other_value.push_normal(", ");
946 }
947 }
948
949 /// For generic types with parameters with defaults, remove the parameters corresponding to
950 /// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
strip_generic_default_params( &self, def_id: DefId, substs: ty::subst::SubstsRef<'tcx>, ) -> SubstsRef<'tcx>951 fn strip_generic_default_params(
952 &self,
953 def_id: DefId,
954 substs: ty::subst::SubstsRef<'tcx>,
955 ) -> SubstsRef<'tcx> {
956 let generics = self.tcx.generics_of(def_id);
957 let mut num_supplied_defaults = 0;
958
959 let default_params = generics.params.iter().rev().filter_map(|param| match param.kind {
960 ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id),
961 ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
962 _ => None,
963 });
964 for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
965 match actual.unpack() {
966 GenericArgKind::Const(c) => {
967 if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c {
968 break;
969 }
970 }
971 GenericArgKind::Type(ty) => {
972 if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty {
973 break;
974 }
975 }
976 _ => break,
977 }
978 num_supplied_defaults += 1;
979 }
980 let len = generics.params.len();
981 let mut generics = generics.clone();
982 generics.params.truncate(len - num_supplied_defaults);
983 substs.truncate_to(self.tcx, &generics)
984 }
985
986 /// Given two `fn` signatures highlight only sub-parts that are different.
cmp_fn_sig( &self, sig1: &ty::PolyFnSig<'tcx>, sig2: &ty::PolyFnSig<'tcx>, ) -> (DiagnosticStyledString, DiagnosticStyledString)987 fn cmp_fn_sig(
988 &self,
989 sig1: &ty::PolyFnSig<'tcx>,
990 sig2: &ty::PolyFnSig<'tcx>,
991 ) -> (DiagnosticStyledString, DiagnosticStyledString) {
992 let get_lifetimes = |sig| {
993 use rustc_hir::def::Namespace;
994 let mut s = String::new();
995 let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
996 .name_all_regions(sig)
997 .unwrap();
998 let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();
999 (if lts.is_empty() { String::new() } else { format!("for<{}> ", lts.join(", ")) }, sig)
1000 };
1001
1002 let (lt1, sig1) = get_lifetimes(sig1);
1003 let (lt2, sig2) = get_lifetimes(sig2);
1004
1005 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1006 let mut values = (
1007 DiagnosticStyledString::normal("".to_string()),
1008 DiagnosticStyledString::normal("".to_string()),
1009 );
1010
1011 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1012 // ^^^^^^
1013 values.0.push(sig1.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety);
1014 values.1.push(sig2.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety);
1015
1016 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1017 // ^^^^^^^^^^
1018 if sig1.abi != abi::Abi::Rust {
1019 values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi);
1020 }
1021 if sig2.abi != abi::Abi::Rust {
1022 values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi);
1023 }
1024
1025 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1026 // ^^^^^^^^
1027 let lifetime_diff = lt1 != lt2;
1028 values.0.push(lt1, lifetime_diff);
1029 values.1.push(lt2, lifetime_diff);
1030
1031 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1032 // ^^^
1033 values.0.push_normal("fn(");
1034 values.1.push_normal("fn(");
1035
1036 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1037 // ^^^^^
1038 let len1 = sig1.inputs().len();
1039 let len2 = sig2.inputs().len();
1040 if len1 == len2 {
1041 for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() {
1042 let (x1, x2) = self.cmp(l, r);
1043 (values.0).0.extend(x1.0);
1044 (values.1).0.extend(x2.0);
1045 self.push_comma(&mut values.0, &mut values.1, len1, i);
1046 }
1047 } else {
1048 for (i, l) in sig1.inputs().iter().enumerate() {
1049 values.0.push_highlighted(l.to_string());
1050 if i != len1 - 1 {
1051 values.0.push_highlighted(", ");
1052 }
1053 }
1054 for (i, r) in sig2.inputs().iter().enumerate() {
1055 values.1.push_highlighted(r.to_string());
1056 if i != len2 - 1 {
1057 values.1.push_highlighted(", ");
1058 }
1059 }
1060 }
1061
1062 if sig1.c_variadic {
1063 if len1 > 0 {
1064 values.0.push_normal(", ");
1065 }
1066 values.0.push("...", !sig2.c_variadic);
1067 }
1068 if sig2.c_variadic {
1069 if len2 > 0 {
1070 values.1.push_normal(", ");
1071 }
1072 values.1.push("...", !sig1.c_variadic);
1073 }
1074
1075 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1076 // ^
1077 values.0.push_normal(")");
1078 values.1.push_normal(")");
1079
1080 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1081 // ^^^^^^^^
1082 let output1 = sig1.output();
1083 let output2 = sig2.output();
1084 let (x1, x2) = self.cmp(output1, output2);
1085 if !output1.is_unit() {
1086 values.0.push_normal(" -> ");
1087 (values.0).0.extend(x1.0);
1088 }
1089 if !output2.is_unit() {
1090 values.1.push_normal(" -> ");
1091 (values.1).0.extend(x2.0);
1092 }
1093 values
1094 }
1095
1096 /// Compares two given types, eliding parts that are the same between them and highlighting
1097 /// relevant differences, and return two representation of those types for highlighted printing.
cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString)1098 fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) {
1099 debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind(), t2, t2.kind());
1100
1101 // helper functions
1102 fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
1103 match (a.kind(), b.kind()) {
1104 (a, b) if *a == *b => true,
1105 (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
1106 | (
1107 &ty::Infer(ty::InferTy::IntVar(_)),
1108 &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)),
1109 )
1110 | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
1111 | (
1112 &ty::Infer(ty::InferTy::FloatVar(_)),
1113 &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
1114 ) => true,
1115 _ => false,
1116 }
1117 }
1118
1119 fn push_ty_ref<'tcx>(
1120 region: &ty::Region<'tcx>,
1121 ty: Ty<'tcx>,
1122 mutbl: hir::Mutability,
1123 s: &mut DiagnosticStyledString,
1124 ) {
1125 let mut r = region.to_string();
1126 if r == "'_" {
1127 r.clear();
1128 } else {
1129 r.push(' ');
1130 }
1131 s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str()));
1132 s.push_normal(ty.to_string());
1133 }
1134
1135 // process starts here
1136 match (t1.kind(), t2.kind()) {
1137 (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
1138 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
1139 let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
1140 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1141 let path1 = self.tcx.def_path_str(def1.did);
1142 let path2 = self.tcx.def_path_str(def2.did);
1143 if def1.did == def2.did {
1144 // Easy case. Replace same types with `_` to shorten the output and highlight
1145 // the differing ones.
1146 // let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
1147 // Foo<Bar, _>
1148 // Foo<Quz, _>
1149 // --- ^ type argument elided
1150 // |
1151 // highlighted in output
1152 values.0.push_normal(path1);
1153 values.1.push_normal(path2);
1154
1155 // Avoid printing out default generic parameters that are common to both
1156 // types.
1157 let len1 = sub_no_defaults_1.len();
1158 let len2 = sub_no_defaults_2.len();
1159 let common_len = cmp::min(len1, len2);
1160 let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
1161 let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
1162 let common_default_params =
1163 iter::zip(remainder1.iter().rev(), remainder2.iter().rev())
1164 .filter(|(a, b)| a == b)
1165 .count();
1166 let len = sub1.len() - common_default_params;
1167 let consts_offset = len - sub1.consts().count();
1168
1169 // Only draw `<...>` if there're lifetime/type arguments.
1170 if len > 0 {
1171 values.0.push_normal("<");
1172 values.1.push_normal("<");
1173 }
1174
1175 fn lifetime_display(lifetime: Region<'_>) -> String {
1176 let s = lifetime.to_string();
1177 if s.is_empty() { "'_".to_string() } else { s }
1178 }
1179 // At one point we'd like to elide all lifetimes here, they are irrelevant for
1180 // all diagnostics that use this output
1181 //
1182 // Foo<'x, '_, Bar>
1183 // Foo<'y, '_, Qux>
1184 // ^^ ^^ --- type arguments are not elided
1185 // | |
1186 // | elided as they were the same
1187 // not elided, they were different, but irrelevant
1188 //
1189 // For bound lifetimes, keep the names of the lifetimes,
1190 // even if they are the same so that it's clear what's happening
1191 // if we have something like
1192 //
1193 // for<'r, 's> fn(Inv<'r>, Inv<'s>)
1194 // for<'r> fn(Inv<'r>, Inv<'r>)
1195 let lifetimes = sub1.regions().zip(sub2.regions());
1196 for (i, lifetimes) in lifetimes.enumerate() {
1197 let l1 = lifetime_display(lifetimes.0);
1198 let l2 = lifetime_display(lifetimes.1);
1199 if lifetimes.0 != lifetimes.1 {
1200 values.0.push_highlighted(l1);
1201 values.1.push_highlighted(l2);
1202 } else if lifetimes.0.is_late_bound() {
1203 values.0.push_normal(l1);
1204 values.1.push_normal(l2);
1205 } else {
1206 values.0.push_normal("'_");
1207 values.1.push_normal("'_");
1208 }
1209 self.push_comma(&mut values.0, &mut values.1, len, i);
1210 }
1211
1212 // We're comparing two types with the same path, so we compare the type
1213 // arguments for both. If they are the same, do not highlight and elide from the
1214 // output.
1215 // Foo<_, Bar>
1216 // Foo<_, Qux>
1217 // ^ elided type as this type argument was the same in both sides
1218 let type_arguments = sub1.types().zip(sub2.types());
1219 let regions_len = sub1.regions().count();
1220 let num_display_types = consts_offset - regions_len;
1221 for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
1222 let i = i + regions_len;
1223 if ta1 == ta2 {
1224 values.0.push_normal("_");
1225 values.1.push_normal("_");
1226 } else {
1227 let (x1, x2) = self.cmp(ta1, ta2);
1228 (values.0).0.extend(x1.0);
1229 (values.1).0.extend(x2.0);
1230 }
1231 self.push_comma(&mut values.0, &mut values.1, len, i);
1232 }
1233
1234 // Do the same for const arguments, if they are equal, do not highlight and
1235 // elide them from the output.
1236 let const_arguments = sub1.consts().zip(sub2.consts());
1237 for (i, (ca1, ca2)) in const_arguments.enumerate() {
1238 let i = i + consts_offset;
1239 if ca1 == ca2 {
1240 values.0.push_normal("_");
1241 values.1.push_normal("_");
1242 } else {
1243 values.0.push_highlighted(ca1.to_string());
1244 values.1.push_highlighted(ca2.to_string());
1245 }
1246 self.push_comma(&mut values.0, &mut values.1, len, i);
1247 }
1248
1249 // Close the type argument bracket.
1250 // Only draw `<...>` if there're lifetime/type arguments.
1251 if len > 0 {
1252 values.0.push_normal(">");
1253 values.1.push_normal(">");
1254 }
1255 values
1256 } else {
1257 // Check for case:
1258 // let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
1259 // Foo<Bar<Qux>
1260 // ------- this type argument is exactly the same as the other type
1261 // Bar<Qux>
1262 if self
1263 .cmp_type_arg(
1264 &mut values.0,
1265 &mut values.1,
1266 path1.clone(),
1267 sub_no_defaults_1,
1268 path2.clone(),
1269 &t2,
1270 )
1271 .is_some()
1272 {
1273 return values;
1274 }
1275 // Check for case:
1276 // let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
1277 // Bar<Qux>
1278 // Foo<Bar<Qux>>
1279 // ------- this type argument is exactly the same as the other type
1280 if self
1281 .cmp_type_arg(
1282 &mut values.1,
1283 &mut values.0,
1284 path2,
1285 sub_no_defaults_2,
1286 path1,
1287 &t1,
1288 )
1289 .is_some()
1290 {
1291 return values;
1292 }
1293
1294 // We can't find anything in common, highlight relevant part of type path.
1295 // let x: foo::bar::Baz<Qux> = y:<foo::bar::Bar<Zar>>();
1296 // foo::bar::Baz<Qux>
1297 // foo::bar::Bar<Zar>
1298 // -------- this part of the path is different
1299
1300 let t1_str = t1.to_string();
1301 let t2_str = t2.to_string();
1302 let min_len = t1_str.len().min(t2_str.len());
1303
1304 const SEPARATOR: &str = "::";
1305 let separator_len = SEPARATOR.len();
1306 let split_idx: usize =
1307 iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR))
1308 .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
1309 .map(|(mod_str, _)| mod_str.len() + separator_len)
1310 .sum();
1311
1312 debug!(
1313 "cmp: separator_len={}, split_idx={}, min_len={}",
1314 separator_len, split_idx, min_len
1315 );
1316
1317 if split_idx >= min_len {
1318 // paths are identical, highlight everything
1319 (
1320 DiagnosticStyledString::highlighted(t1_str),
1321 DiagnosticStyledString::highlighted(t2_str),
1322 )
1323 } else {
1324 let (common, uniq1) = t1_str.split_at(split_idx);
1325 let (_, uniq2) = t2_str.split_at(split_idx);
1326 debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
1327
1328 values.0.push_normal(common);
1329 values.0.push_highlighted(uniq1);
1330 values.1.push_normal(common);
1331 values.1.push_highlighted(uniq2);
1332
1333 values
1334 }
1335 }
1336 }
1337
1338 // When finding T != &T, highlight only the borrow
1339 (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => {
1340 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1341 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1342 values.1.push_normal(t2.to_string());
1343 values
1344 }
1345 (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => {
1346 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1347 values.0.push_normal(t1.to_string());
1348 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
1349 values
1350 }
1351
1352 // When encountering &T != &mut T, highlight only the borrow
1353 (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2))
1354 if equals(&ref_ty1, &ref_ty2) =>
1355 {
1356 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1357 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1358 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
1359 values
1360 }
1361
1362 // When encountering tuples of the same size, highlight only the differing types
1363 (&ty::Tuple(substs1), &ty::Tuple(substs2)) if substs1.len() == substs2.len() => {
1364 let mut values =
1365 (DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("("));
1366 let len = substs1.len();
1367 for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() {
1368 let (x1, x2) = self.cmp(left, right);
1369 (values.0).0.extend(x1.0);
1370 (values.1).0.extend(x2.0);
1371 self.push_comma(&mut values.0, &mut values.1, len, i);
1372 }
1373 if len == 1 {
1374 // Keep the output for single element tuples as `(ty,)`.
1375 values.0.push_normal(",");
1376 values.1.push_normal(",");
1377 }
1378 values.0.push_normal(")");
1379 values.1.push_normal(")");
1380 values
1381 }
1382
1383 (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
1384 let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
1385 let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
1386 let mut values = self.cmp_fn_sig(&sig1, &sig2);
1387 let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
1388 let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
1389 let same_path = path1 == path2;
1390 values.0.push(path1, !same_path);
1391 values.1.push(path2, !same_path);
1392 values
1393 }
1394
1395 (ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
1396 let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
1397 let mut values = self.cmp_fn_sig(&sig1, sig2);
1398 values.0.push_highlighted(format!(
1399 " {{{}}}",
1400 self.tcx.def_path_str_with_substs(*did1, substs1)
1401 ));
1402 values
1403 }
1404
1405 (ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
1406 let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
1407 let mut values = self.cmp_fn_sig(sig1, &sig2);
1408 values.1.push_normal(format!(
1409 " {{{}}}",
1410 self.tcx.def_path_str_with_substs(*did2, substs2)
1411 ));
1412 values
1413 }
1414
1415 (ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2),
1416
1417 _ => {
1418 if t1 == t2 {
1419 // The two types are the same, elide and don't highlight.
1420 (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
1421 } else {
1422 // We couldn't find anything in common, highlight everything.
1423 (
1424 DiagnosticStyledString::highlighted(t1.to_string()),
1425 DiagnosticStyledString::highlighted(t2.to_string()),
1426 )
1427 }
1428 }
1429 }
1430 }
1431
note_type_err( &self, diag: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>, secondary_span: Option<(Span, String)>, mut values: Option<ValuePairs<'tcx>>, terr: &TypeError<'tcx>, )1432 pub fn note_type_err(
1433 &self,
1434 diag: &mut DiagnosticBuilder<'tcx>,
1435 cause: &ObligationCause<'tcx>,
1436 secondary_span: Option<(Span, String)>,
1437 mut values: Option<ValuePairs<'tcx>>,
1438 terr: &TypeError<'tcx>,
1439 ) {
1440 let span = cause.span(self.tcx);
1441 debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
1442
1443 // For some types of errors, expected-found does not make
1444 // sense, so just ignore the values we were given.
1445 if let TypeError::CyclicTy(_) = terr {
1446 values = None;
1447 }
1448 struct OpaqueTypesVisitor<'tcx> {
1449 types: FxHashMap<TyCategory, FxHashSet<Span>>,
1450 expected: FxHashMap<TyCategory, FxHashSet<Span>>,
1451 found: FxHashMap<TyCategory, FxHashSet<Span>>,
1452 ignore_span: Span,
1453 tcx: TyCtxt<'tcx>,
1454 }
1455
1456 impl<'tcx> OpaqueTypesVisitor<'tcx> {
1457 fn visit_expected_found(
1458 tcx: TyCtxt<'tcx>,
1459 expected: Ty<'tcx>,
1460 found: Ty<'tcx>,
1461 ignore_span: Span,
1462 ) -> Self {
1463 let mut types_visitor = OpaqueTypesVisitor {
1464 types: Default::default(),
1465 expected: Default::default(),
1466 found: Default::default(),
1467 ignore_span,
1468 tcx,
1469 };
1470 // The visitor puts all the relevant encountered types in `self.types`, but in
1471 // here we want to visit two separate types with no relation to each other, so we
1472 // move the results from `types` to `expected` or `found` as appropriate.
1473 expected.visit_with(&mut types_visitor);
1474 std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
1475 found.visit_with(&mut types_visitor);
1476 std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
1477 types_visitor
1478 }
1479
1480 fn report(&self, err: &mut DiagnosticBuilder<'_>) {
1481 self.add_labels_for_types(err, "expected", &self.expected);
1482 self.add_labels_for_types(err, "found", &self.found);
1483 }
1484
1485 fn add_labels_for_types(
1486 &self,
1487 err: &mut DiagnosticBuilder<'_>,
1488 target: &str,
1489 types: &FxHashMap<TyCategory, FxHashSet<Span>>,
1490 ) {
1491 for (key, values) in types.iter() {
1492 let count = values.len();
1493 let kind = key.descr();
1494 let mut returned_async_output_error = false;
1495 for &sp in values {
1496 if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
1497 if [sp] != err.span.primary_spans() {
1498 let mut span: MultiSpan = sp.into();
1499 span.push_span_label(
1500 sp,
1501 format!(
1502 "checked the `Output` of this `async fn`, {}{} {}{}",
1503 if count > 1 { "one of the " } else { "" },
1504 target,
1505 kind,
1506 pluralize!(count),
1507 ),
1508 );
1509 err.span_note(
1510 span,
1511 "while checking the return type of the `async fn`",
1512 );
1513 } else {
1514 err.span_label(
1515 sp,
1516 format!(
1517 "checked the `Output` of this `async fn`, {}{} {}{}",
1518 if count > 1 { "one of the " } else { "" },
1519 target,
1520 kind,
1521 pluralize!(count),
1522 ),
1523 );
1524 err.note("while checking the return type of the `async fn`");
1525 }
1526 returned_async_output_error = true;
1527 } else {
1528 err.span_label(
1529 sp,
1530 format!(
1531 "{}{} {}{}",
1532 if count == 1 { "the " } else { "one of the " },
1533 target,
1534 kind,
1535 pluralize!(count),
1536 ),
1537 );
1538 }
1539 }
1540 }
1541 }
1542 }
1543
1544 impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
1545 fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1546 Some(self.tcx)
1547 }
1548
1549 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1550 if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
1551 let span = self.tcx.def_span(def_id);
1552 // Avoid cluttering the output when the "found" and error span overlap:
1553 //
1554 // error[E0308]: mismatched types
1555 // --> $DIR/issue-20862.rs:2:5
1556 // |
1557 // LL | |y| x + y
1558 // | ^^^^^^^^^
1559 // | |
1560 // | the found closure
1561 // | expected `()`, found closure
1562 // |
1563 // = note: expected unit type `()`
1564 // found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
1565 if !self.ignore_span.overlaps(span) {
1566 self.types.entry(kind).or_default().insert(span);
1567 }
1568 }
1569 t.super_visit_with(self)
1570 }
1571 }
1572
1573 debug!("note_type_err(diag={:?})", diag);
1574 enum Mismatch<'a> {
1575 Variable(ty::error::ExpectedFound<Ty<'a>>),
1576 Fixed(&'static str),
1577 }
1578 let (expected_found, exp_found, is_simple_error) = match values {
1579 None => (None, Mismatch::Fixed("type"), false),
1580 Some(values) => {
1581 let (is_simple_error, exp_found) = match values {
1582 ValuePairs::Types(exp_found) => {
1583 let is_simple_err =
1584 exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
1585 OpaqueTypesVisitor::visit_expected_found(
1586 self.tcx,
1587 exp_found.expected,
1588 exp_found.found,
1589 span,
1590 )
1591 .report(diag);
1592
1593 (is_simple_err, Mismatch::Variable(exp_found))
1594 }
1595 ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
1596 _ => (false, Mismatch::Fixed("type")),
1597 };
1598 let vals = match self.values_str(values) {
1599 Some((expected, found)) => Some((expected, found)),
1600 None => {
1601 // Derived error. Cancel the emitter.
1602 diag.cancel();
1603 return;
1604 }
1605 };
1606 (vals, exp_found, is_simple_error)
1607 }
1608 };
1609
1610 // Ignore msg for object safe coercion
1611 // since E0038 message will be printed
1612 match terr {
1613 TypeError::ObjectUnsafeCoercion(_) => {}
1614 _ => {
1615 diag.span_label(span, terr.to_string());
1616 if let Some((sp, msg)) = secondary_span {
1617 diag.span_label(sp, msg);
1618 }
1619 }
1620 };
1621 if let Some((expected, found)) = expected_found {
1622 let (expected_label, found_label, exp_found) = match exp_found {
1623 Mismatch::Variable(ef) => (
1624 ef.expected.prefix_string(self.tcx),
1625 ef.found.prefix_string(self.tcx),
1626 Some(ef),
1627 ),
1628 Mismatch::Fixed(s) => (s.into(), s.into(), None),
1629 };
1630 match (&terr, expected == found) {
1631 (TypeError::Sorts(values), extra) => {
1632 let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
1633 (true, ty::Opaque(def_id, _)) => {
1634 let sm = self.tcx.sess.source_map();
1635 let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
1636 format!(
1637 " (opaque type at <{}:{}:{}>)",
1638 sm.filename_for_diagnostics(&pos.file.name),
1639 pos.line,
1640 pos.col.to_usize() + 1,
1641 )
1642 }
1643 (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
1644 (false, _) => "".to_string(),
1645 };
1646 if !(values.expected.is_simple_text() && values.found.is_simple_text())
1647 || (exp_found.map_or(false, |ef| {
1648 // This happens when the type error is a subset of the expectation,
1649 // like when you have two references but one is `usize` and the other
1650 // is `f32`. In those cases we still want to show the `note`. If the
1651 // value from `ef` is `Infer(_)`, then we ignore it.
1652 if !ef.expected.is_ty_infer() {
1653 ef.expected != values.expected
1654 } else if !ef.found.is_ty_infer() {
1655 ef.found != values.found
1656 } else {
1657 false
1658 }
1659 }))
1660 {
1661 diag.note_expected_found_extra(
1662 &expected_label,
1663 expected,
1664 &found_label,
1665 found,
1666 &sort_string(values.expected),
1667 &sort_string(values.found),
1668 );
1669 }
1670 }
1671 (TypeError::ObjectUnsafeCoercion(_), _) => {
1672 diag.note_unsuccessful_coercion(found, expected);
1673 }
1674 (_, _) => {
1675 debug!(
1676 "note_type_err: exp_found={:?}, expected={:?} found={:?}",
1677 exp_found, expected, found
1678 );
1679 if !is_simple_error || terr.must_include_note() {
1680 diag.note_expected_found(&expected_label, expected, &found_label, found);
1681 }
1682 }
1683 }
1684 }
1685 let exp_found = match exp_found {
1686 Mismatch::Variable(exp_found) => Some(exp_found),
1687 Mismatch::Fixed(_) => None,
1688 };
1689 let exp_found = match terr {
1690 // `terr` has more accurate type information than `exp_found` in match expressions.
1691 ty::error::TypeError::Sorts(terr)
1692 if exp_found.map_or(false, |ef| terr.found == ef.found) =>
1693 {
1694 Some(*terr)
1695 }
1696 _ => exp_found,
1697 };
1698 debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code);
1699 if let Some(exp_found) = exp_found {
1700 let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } =
1701 &cause.code
1702 {
1703 // Skip if the root_ty of the pattern is not the same as the expected_ty.
1704 // If these types aren't equal then we've probably peeled off a layer of arrays.
1705 same_type_modulo_infer(self.resolve_vars_if_possible(*root_ty), exp_found.expected)
1706 } else {
1707 true
1708 };
1709
1710 if should_suggest_fixes {
1711 self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
1712 self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
1713 self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
1714 }
1715 }
1716
1717 // In some (most?) cases cause.body_id points to actual body, but in some cases
1718 // it's an actual definition. According to the comments (e.g. in
1719 // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
1720 // is relied upon by some other code. This might (or might not) need cleanup.
1721 let body_owner_def_id =
1722 self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
1723 self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
1724 });
1725 self.check_and_note_conflicting_crates(diag, terr);
1726 self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
1727
1728 if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
1729 if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
1730 if let Some(def_id) = def_id.as_local() {
1731 let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
1732 let span = self.tcx.hir().span(hir_id);
1733 diag.span_note(span, "this closure does not fulfill the lifetime requirements");
1734 }
1735 }
1736 }
1737
1738 // It reads better to have the error origin as the final
1739 // thing.
1740 self.note_error_origin(diag, cause, exp_found, terr);
1741 }
1742
get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>>1743 pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
1744 if let ty::Opaque(def_id, substs) = ty.kind() {
1745 let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
1746 // Future::Output
1747 let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
1748
1749 let bounds = self.tcx.explicit_item_bounds(*def_id);
1750
1751 for (predicate, _) in bounds {
1752 let predicate = predicate.subst(self.tcx, substs);
1753 if let ty::PredicateKind::Projection(projection_predicate) =
1754 predicate.kind().skip_binder()
1755 {
1756 if projection_predicate.projection_ty.item_def_id == item_def_id {
1757 // We don't account for multiple `Future::Output = Ty` contraints.
1758 return Some(projection_predicate.ty);
1759 }
1760 }
1761 }
1762 }
1763 None
1764 }
1765
1766 /// A possible error is to forget to add `.await` when using futures:
1767 ///
1768 /// ```
1769 /// async fn make_u32() -> u32 {
1770 /// 22
1771 /// }
1772 ///
1773 /// fn take_u32(x: u32) {}
1774 ///
1775 /// async fn foo() {
1776 /// let x = make_u32();
1777 /// take_u32(x);
1778 /// }
1779 /// ```
1780 ///
1781 /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
1782 /// expected type. If this is the case, and we are inside of an async body, it suggests adding
1783 /// `.await` to the tail of the expression.
suggest_await_on_expect_found( &self, cause: &ObligationCause<'tcx>, exp_span: Span, exp_found: &ty::error::ExpectedFound<Ty<'tcx>>, diag: &mut DiagnosticBuilder<'tcx>, )1784 fn suggest_await_on_expect_found(
1785 &self,
1786 cause: &ObligationCause<'tcx>,
1787 exp_span: Span,
1788 exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1789 diag: &mut DiagnosticBuilder<'tcx>,
1790 ) {
1791 debug!(
1792 "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
1793 exp_span, exp_found.expected, exp_found.found,
1794 );
1795
1796 if let ObligationCauseCode::CompareImplMethodObligation { .. } = &cause.code {
1797 return;
1798 }
1799
1800 match (
1801 self.get_impl_future_output_ty(exp_found.expected),
1802 self.get_impl_future_output_ty(exp_found.found),
1803 ) {
1804 (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match &cause.code {
1805 ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {
1806 diag.multipart_suggestion(
1807 "consider `await`ing on both `Future`s",
1808 vec![
1809 (then.shrink_to_hi(), ".await".to_string()),
1810 (exp_span.shrink_to_hi(), ".await".to_string()),
1811 ],
1812 Applicability::MaybeIncorrect,
1813 );
1814 }
1815 ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
1816 prior_arms,
1817 ..
1818 }) => {
1819 if let [.., arm_span] = &prior_arms[..] {
1820 diag.multipart_suggestion(
1821 "consider `await`ing on both `Future`s",
1822 vec![
1823 (arm_span.shrink_to_hi(), ".await".to_string()),
1824 (exp_span.shrink_to_hi(), ".await".to_string()),
1825 ],
1826 Applicability::MaybeIncorrect,
1827 );
1828 } else {
1829 diag.help("consider `await`ing on both `Future`s");
1830 }
1831 }
1832 _ => {
1833 diag.help("consider `await`ing on both `Future`s");
1834 }
1835 },
1836 (_, Some(ty)) if same_type_modulo_infer(exp_found.expected, ty) => {
1837 diag.span_suggestion_verbose(
1838 exp_span.shrink_to_hi(),
1839 "consider `await`ing on the `Future`",
1840 ".await".to_string(),
1841 Applicability::MaybeIncorrect,
1842 );
1843 }
1844 (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code {
1845 ObligationCauseCode::Pattern { span: Some(span), .. }
1846 | ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => {
1847 diag.span_suggestion_verbose(
1848 span.shrink_to_hi(),
1849 "consider `await`ing on the `Future`",
1850 ".await".to_string(),
1851 Applicability::MaybeIncorrect,
1852 );
1853 }
1854 ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
1855 ref prior_arms,
1856 ..
1857 }) => {
1858 diag.multipart_suggestion_verbose(
1859 "consider `await`ing on the `Future`",
1860 prior_arms
1861 .iter()
1862 .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
1863 .collect(),
1864 Applicability::MaybeIncorrect,
1865 );
1866 }
1867 _ => {}
1868 },
1869 _ => {}
1870 }
1871 }
1872
suggest_accessing_field_where_appropriate( &self, cause: &ObligationCause<'tcx>, exp_found: &ty::error::ExpectedFound<Ty<'tcx>>, diag: &mut DiagnosticBuilder<'tcx>, )1873 fn suggest_accessing_field_where_appropriate(
1874 &self,
1875 cause: &ObligationCause<'tcx>,
1876 exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1877 diag: &mut DiagnosticBuilder<'tcx>,
1878 ) {
1879 debug!(
1880 "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
1881 cause, exp_found
1882 );
1883 if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
1884 if expected_def.is_enum() {
1885 return;
1886 }
1887
1888 if let Some((name, ty)) = expected_def
1889 .non_enum_variant()
1890 .fields
1891 .iter()
1892 .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
1893 .map(|field| (field.ident.name, field.ty(self.tcx, expected_substs)))
1894 .find(|(_, ty)| same_type_modulo_infer(ty, exp_found.found))
1895 {
1896 if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code {
1897 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1898 let suggestion = if expected_def.is_struct() {
1899 format!("{}.{}", snippet, name)
1900 } else if expected_def.is_union() {
1901 format!("unsafe {{ {}.{} }}", snippet, name)
1902 } else {
1903 return;
1904 };
1905 diag.span_suggestion(
1906 span,
1907 &format!(
1908 "you might have meant to use field `{}` whose type is `{}`",
1909 name, ty
1910 ),
1911 suggestion,
1912 Applicability::MaybeIncorrect,
1913 );
1914 }
1915 }
1916 }
1917 }
1918 }
1919
1920 /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
1921 /// suggests it.
suggest_as_ref_where_appropriate( &self, span: Span, exp_found: &ty::error::ExpectedFound<Ty<'tcx>>, diag: &mut DiagnosticBuilder<'tcx>, )1922 fn suggest_as_ref_where_appropriate(
1923 &self,
1924 span: Span,
1925 exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1926 diag: &mut DiagnosticBuilder<'tcx>,
1927 ) {
1928 if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
1929 (exp_found.expected.kind(), exp_found.found.kind())
1930 {
1931 if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
1932 let path_str = format!("{:?}", exp_def);
1933 if exp_def == &found_def {
1934 let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
1935 `.as_ref()`";
1936 let result_msg = "you can convert from `&Result<T, E>` to \
1937 `Result<&T, &E>` using `.as_ref()`";
1938 let have_as_ref = &[
1939 ("std::option::Option", opt_msg),
1940 ("core::option::Option", opt_msg),
1941 ("std::result::Result", result_msg),
1942 ("core::result::Result", result_msg),
1943 ];
1944 if let Some(msg) = have_as_ref
1945 .iter()
1946 .find_map(|(path, msg)| (&path_str == path).then_some(msg))
1947 {
1948 let mut show_suggestion = true;
1949 for (exp_ty, found_ty) in
1950 iter::zip(exp_substs.types(), found_substs.types())
1951 {
1952 match *exp_ty.kind() {
1953 ty::Ref(_, exp_ty, _) => {
1954 match (exp_ty.kind(), found_ty.kind()) {
1955 (_, ty::Param(_))
1956 | (_, ty::Infer(_))
1957 | (ty::Param(_), _)
1958 | (ty::Infer(_), _) => {}
1959 _ if same_type_modulo_infer(exp_ty, found_ty) => {}
1960 _ => show_suggestion = false,
1961 };
1962 }
1963 ty::Param(_) | ty::Infer(_) => {}
1964 _ => show_suggestion = false,
1965 }
1966 }
1967 if let (Ok(snippet), true) =
1968 (self.tcx.sess.source_map().span_to_snippet(span), show_suggestion)
1969 {
1970 diag.span_suggestion(
1971 span,
1972 msg,
1973 format!("{}.as_ref()", snippet),
1974 Applicability::MachineApplicable,
1975 );
1976 }
1977 }
1978 }
1979 }
1980 }
1981 }
1982
report_and_explain_type_error( &self, trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>, ) -> DiagnosticBuilder<'tcx>1983 pub fn report_and_explain_type_error(
1984 &self,
1985 trace: TypeTrace<'tcx>,
1986 terr: &TypeError<'tcx>,
1987 ) -> DiagnosticBuilder<'tcx> {
1988 use crate::traits::ObligationCauseCode::MatchExpressionArm;
1989
1990 debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
1991
1992 let span = trace.cause.span(self.tcx);
1993 let failure_code = trace.cause.as_failure_code(terr);
1994 let mut diag = match failure_code {
1995 FailureCode::Error0038(did) => {
1996 let violations = self.tcx.object_safety_violations(did);
1997 report_object_safety_error(self.tcx, span, did, violations)
1998 }
1999 FailureCode::Error0317(failure_str) => {
2000 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
2001 }
2002 FailureCode::Error0580(failure_str) => {
2003 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
2004 }
2005 FailureCode::Error0308(failure_str) => {
2006 let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
2007 if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) =
2008 trace.values
2009 {
2010 // If a tuple of length one was expected and the found expression has
2011 // parentheses around it, perhaps the user meant to write `(expr,)` to
2012 // build a tuple (issue #86100)
2013 match (expected.kind(), found.kind()) {
2014 (ty::Tuple(_), ty::Tuple(_)) => {}
2015 (ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => {
2016 if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
2017 if let Some(code) =
2018 code.strip_prefix('(').and_then(|s| s.strip_suffix(')'))
2019 {
2020 err.span_suggestion(
2021 span,
2022 "use a trailing comma to create a tuple with one element",
2023 format!("({},)", code),
2024 Applicability::MaybeIncorrect,
2025 );
2026 }
2027 }
2028 }
2029 _ => {}
2030 }
2031 }
2032 if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
2033 trace.cause.code
2034 {
2035 if let hir::MatchSource::TryDesugar = source {
2036 if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
2037 err.note(&format!(
2038 "`?` operator cannot convert from `{}` to `{}`",
2039 found_ty.content(),
2040 expected_ty.content(),
2041 ));
2042 }
2043 }
2044 }
2045 err
2046 }
2047 FailureCode::Error0644(failure_str) => {
2048 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
2049 }
2050 };
2051 self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
2052 diag
2053 }
2054
values_str( &self, values: ValuePairs<'tcx>, ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>2055 fn values_str(
2056 &self,
2057 values: ValuePairs<'tcx>,
2058 ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
2059 match values {
2060 infer::Types(exp_found) => self.expected_found_str_ty(exp_found),
2061 infer::Regions(exp_found) => self.expected_found_str(exp_found),
2062 infer::Consts(exp_found) => self.expected_found_str(exp_found),
2063 infer::TraitRefs(exp_found) => {
2064 let pretty_exp_found = ty::error::ExpectedFound {
2065 expected: exp_found.expected.print_only_trait_path(),
2066 found: exp_found.found.print_only_trait_path(),
2067 };
2068 match self.expected_found_str(pretty_exp_found) {
2069 Some((expected, found)) if expected == found => {
2070 self.expected_found_str(exp_found)
2071 }
2072 ret => ret,
2073 }
2074 }
2075 infer::PolyTraitRefs(exp_found) => {
2076 let pretty_exp_found = ty::error::ExpectedFound {
2077 expected: exp_found.expected.print_only_trait_path(),
2078 found: exp_found.found.print_only_trait_path(),
2079 };
2080 match self.expected_found_str(pretty_exp_found) {
2081 Some((expected, found)) if expected == found => {
2082 self.expected_found_str(exp_found)
2083 }
2084 ret => ret,
2085 }
2086 }
2087 }
2088 }
2089
expected_found_str_ty( &self, exp_found: ty::error::ExpectedFound<Ty<'tcx>>, ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>2090 fn expected_found_str_ty(
2091 &self,
2092 exp_found: ty::error::ExpectedFound<Ty<'tcx>>,
2093 ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
2094 let exp_found = self.resolve_vars_if_possible(exp_found);
2095 if exp_found.references_error() {
2096 return None;
2097 }
2098
2099 Some(self.cmp(exp_found.expected, exp_found.found))
2100 }
2101
2102 /// Returns a string of the form "expected `{}`, found `{}`".
expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>( &self, exp_found: ty::error::ExpectedFound<T>, ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)>2103 fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
2104 &self,
2105 exp_found: ty::error::ExpectedFound<T>,
2106 ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
2107 let exp_found = self.resolve_vars_if_possible(exp_found);
2108 if exp_found.references_error() {
2109 return None;
2110 }
2111
2112 Some((
2113 DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
2114 DiagnosticStyledString::highlighted(exp_found.found.to_string()),
2115 ))
2116 }
2117
report_generic_bound_failure( &self, span: Span, origin: Option<SubregionOrigin<'tcx>>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, )2118 pub fn report_generic_bound_failure(
2119 &self,
2120 span: Span,
2121 origin: Option<SubregionOrigin<'tcx>>,
2122 bound_kind: GenericKind<'tcx>,
2123 sub: Region<'tcx>,
2124 ) {
2125 self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
2126 }
2127
construct_generic_bound_failure( &self, span: Span, origin: Option<SubregionOrigin<'tcx>>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) -> DiagnosticBuilder<'a>2128 pub fn construct_generic_bound_failure(
2129 &self,
2130 span: Span,
2131 origin: Option<SubregionOrigin<'tcx>>,
2132 bound_kind: GenericKind<'tcx>,
2133 sub: Region<'tcx>,
2134 ) -> DiagnosticBuilder<'a> {
2135 let hir = &self.tcx.hir();
2136 // Attempt to obtain the span of the parameter so we can
2137 // suggest adding an explicit lifetime bound to it.
2138 let generics = self
2139 .in_progress_typeck_results
2140 .map(|typeck_results| typeck_results.borrow().hir_owner)
2141 .map(|owner| {
2142 let hir_id = hir.local_def_id_to_hir_id(owner);
2143 let parent_id = hir.get_parent_item(hir_id);
2144 (
2145 // Parent item could be a `mod`, so we check the HIR before calling:
2146 if let Some(Node::Item(Item {
2147 kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
2148 ..
2149 })) = hir.find(parent_id)
2150 {
2151 Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id()))
2152 } else {
2153 None
2154 },
2155 self.tcx.generics_of(owner.to_def_id()),
2156 hir.span(hir_id),
2157 )
2158 });
2159
2160 let span = match generics {
2161 // This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
2162 // for other diagnostics, so we need to recover it here.
2163 Some((_, _, node)) if span.is_dummy() => node,
2164 _ => span,
2165 };
2166
2167 let type_param_span = match (generics, bound_kind) {
2168 (Some((_, ref generics, _)), GenericKind::Param(ref param)) => {
2169 // Account for the case where `param` corresponds to `Self`,
2170 // which doesn't have the expected type argument.
2171 if !(generics.has_self && param.index == 0) {
2172 let type_param = generics.type_param(param, self.tcx);
2173 type_param.def_id.as_local().map(|def_id| {
2174 // Get the `hir::Param` to verify whether it already has any bounds.
2175 // We do this to avoid suggesting code that ends up as `T: 'a'b`,
2176 // instead we suggest `T: 'a + 'b` in that case.
2177 let id = hir.local_def_id_to_hir_id(def_id);
2178 let mut has_bounds = false;
2179 if let Node::GenericParam(param) = hir.get(id) {
2180 has_bounds = !param.bounds.is_empty();
2181 }
2182 let sp = hir.span(id);
2183 // `sp` only covers `T`, change it so that it covers
2184 // `T:` when appropriate
2185 let is_impl_trait = bound_kind.to_string().starts_with("impl ");
2186 let sp = if has_bounds && !is_impl_trait {
2187 sp.to(self
2188 .tcx
2189 .sess
2190 .source_map()
2191 .next_point(self.tcx.sess.source_map().next_point(sp)))
2192 } else {
2193 sp
2194 };
2195 (sp, has_bounds, is_impl_trait)
2196 })
2197 } else {
2198 None
2199 }
2200 }
2201 _ => None,
2202 };
2203 let new_lt = generics
2204 .as_ref()
2205 .and_then(|(parent_g, g, _)| {
2206 let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
2207 let mut lts_names = g
2208 .params
2209 .iter()
2210 .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
2211 .map(|p| p.name.as_str())
2212 .collect::<Vec<_>>();
2213 if let Some(g) = parent_g {
2214 lts_names.extend(
2215 g.params
2216 .iter()
2217 .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
2218 .map(|p| p.name.as_str()),
2219 );
2220 }
2221 let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
2222 possible.find(|candidate| !lts.contains(&candidate.as_str()))
2223 })
2224 .unwrap_or("'lt".to_string());
2225 let add_lt_sugg = generics
2226 .as_ref()
2227 .and_then(|(_, g, _)| g.params.first())
2228 .and_then(|param| param.def_id.as_local())
2229 .map(|def_id| {
2230 (
2231 hir.span(hir.local_def_id_to_hir_id(def_id)).shrink_to_lo(),
2232 format!("{}, ", new_lt),
2233 )
2234 });
2235
2236 let labeled_user_string = match bound_kind {
2237 GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
2238 GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
2239 };
2240
2241 if let Some(SubregionOrigin::CompareImplMethodObligation {
2242 span,
2243 impl_item_def_id,
2244 trait_item_def_id,
2245 }) = origin
2246 {
2247 return self.report_extra_impl_obligation(
2248 span,
2249 impl_item_def_id,
2250 trait_item_def_id,
2251 &format!("`{}: {}`", bound_kind, sub),
2252 );
2253 }
2254
2255 fn binding_suggestion<'tcx, S: fmt::Display>(
2256 err: &mut DiagnosticBuilder<'tcx>,
2257 type_param_span: Option<(Span, bool, bool)>,
2258 bound_kind: GenericKind<'tcx>,
2259 sub: S,
2260 ) {
2261 let msg = "consider adding an explicit lifetime bound";
2262 if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
2263 let suggestion = if is_impl_trait {
2264 format!("{} + {}", bound_kind, sub)
2265 } else {
2266 let tail = if has_lifetimes { " + " } else { "" };
2267 format!("{}: {}{}", bound_kind, sub, tail)
2268 };
2269 err.span_suggestion(
2270 sp,
2271 &format!("{}...", msg),
2272 suggestion,
2273 Applicability::MaybeIncorrect, // Issue #41966
2274 );
2275 } else {
2276 let consider = format!(
2277 "{} {}...",
2278 msg,
2279 if type_param_span.map_or(false, |(_, _, is_impl_trait)| is_impl_trait) {
2280 format!(" `{}` to `{}`", sub, bound_kind)
2281 } else {
2282 format!("`{}: {}`", bound_kind, sub)
2283 },
2284 );
2285 err.help(&consider);
2286 }
2287 }
2288
2289 let new_binding_suggestion =
2290 |err: &mut DiagnosticBuilder<'tcx>,
2291 type_param_span: Option<(Span, bool, bool)>,
2292 bound_kind: GenericKind<'tcx>| {
2293 let msg = "consider introducing an explicit lifetime bound";
2294 if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
2295 let suggestion = if is_impl_trait {
2296 (sp.shrink_to_hi(), format!(" + {}", new_lt))
2297 } else {
2298 let tail = if has_lifetimes { " +" } else { "" };
2299 (sp, format!("{}: {}{}", bound_kind, new_lt, tail))
2300 };
2301 let mut sugg =
2302 vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))];
2303 if let Some(lt) = add_lt_sugg {
2304 sugg.push(lt);
2305 sugg.rotate_right(1);
2306 }
2307 // `MaybeIncorrect` due to issue #41966.
2308 err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
2309 }
2310 };
2311
2312 #[derive(Debug)]
2313 enum SubOrigin<'hir> {
2314 GAT(&'hir hir::Generics<'hir>),
2315 Impl(&'hir hir::Generics<'hir>),
2316 Trait(&'hir hir::Generics<'hir>),
2317 Fn(&'hir hir::Generics<'hir>),
2318 Unknown,
2319 }
2320 let sub_origin = 'origin: {
2321 match *sub {
2322 ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
2323 let node = self.tcx.hir().get_if_local(def_id).unwrap();
2324 match node {
2325 Node::GenericParam(param) => {
2326 for h in self.tcx.hir().parent_iter(param.hir_id) {
2327 break 'origin match h.1 {
2328 Node::ImplItem(hir::ImplItem {
2329 kind: hir::ImplItemKind::TyAlias(..),
2330 generics,
2331 ..
2332 }) => SubOrigin::GAT(generics),
2333 Node::ImplItem(hir::ImplItem {
2334 kind: hir::ImplItemKind::Fn(..),
2335 generics,
2336 ..
2337 }) => SubOrigin::Fn(generics),
2338 Node::TraitItem(hir::TraitItem {
2339 kind: hir::TraitItemKind::Type(..),
2340 generics,
2341 ..
2342 }) => SubOrigin::GAT(generics),
2343 Node::TraitItem(hir::TraitItem {
2344 kind: hir::TraitItemKind::Fn(..),
2345 generics,
2346 ..
2347 }) => SubOrigin::Fn(generics),
2348 Node::Item(hir::Item {
2349 kind: hir::ItemKind::Trait(_, _, generics, _, _),
2350 ..
2351 }) => SubOrigin::Trait(generics),
2352 Node::Item(hir::Item {
2353 kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
2354 ..
2355 }) => SubOrigin::Impl(generics),
2356 Node::Item(hir::Item {
2357 kind: hir::ItemKind::Fn(_, generics, _),
2358 ..
2359 }) => SubOrigin::Fn(generics),
2360 _ => continue,
2361 };
2362 }
2363 }
2364 _ => {}
2365 }
2366 }
2367 _ => {}
2368 }
2369 SubOrigin::Unknown
2370 };
2371 debug!(?sub_origin);
2372
2373 let mut err = match (*sub, sub_origin) {
2374 // In the case of GATs, we have to be careful. If we a type parameter `T` on an impl,
2375 // but a lifetime `'a` on an associated type, then we might need to suggest adding
2376 // `where T: 'a`. Importantly, this is on the GAT span, not on the `T` declaration.
2377 (ty::ReEarlyBound(ty::EarlyBoundRegion { name: _, .. }), SubOrigin::GAT(generics)) => {
2378 // Does the required lifetime have a nice name we can print?
2379 let mut err = struct_span_err!(
2380 self.tcx.sess,
2381 span,
2382 E0309,
2383 "{} may not live long enough",
2384 labeled_user_string
2385 );
2386 let pred = format!("{}: {}", bound_kind, sub);
2387 let suggestion = format!(
2388 "{} {}",
2389 if !generics.where_clause.predicates.is_empty() { "," } else { " where" },
2390 pred,
2391 );
2392 err.span_suggestion(
2393 generics.where_clause.tail_span_for_suggestion(),
2394 "consider adding a where clause",
2395 suggestion,
2396 Applicability::MaybeIncorrect,
2397 );
2398 err
2399 }
2400 (
2401 ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
2402 | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }),
2403 _,
2404 ) => {
2405 // Does the required lifetime have a nice name we can print?
2406 let mut err = struct_span_err!(
2407 self.tcx.sess,
2408 span,
2409 E0309,
2410 "{} may not live long enough",
2411 labeled_user_string
2412 );
2413 // Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl
2414 // for the bound is not suitable for suggestions when `-Zverbose` is set because it
2415 // uses `Debug` output, so we handle it specially here so that suggestions are
2416 // always correct.
2417 binding_suggestion(&mut err, type_param_span, bound_kind, name);
2418 err
2419 }
2420
2421 (ty::ReStatic, _) => {
2422 // Does the required lifetime have a nice name we can print?
2423 let mut err = struct_span_err!(
2424 self.tcx.sess,
2425 span,
2426 E0310,
2427 "{} may not live long enough",
2428 labeled_user_string
2429 );
2430 binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
2431 err
2432 }
2433
2434 _ => {
2435 // If not, be less specific.
2436 let mut err = struct_span_err!(
2437 self.tcx.sess,
2438 span,
2439 E0311,
2440 "{} may not live long enough",
2441 labeled_user_string
2442 );
2443 note_and_explain_region(
2444 self.tcx,
2445 &mut err,
2446 &format!("{} must be valid for ", labeled_user_string),
2447 sub,
2448 "...",
2449 None,
2450 );
2451 if let Some(infer::RelateParamBound(_, t, _)) = origin {
2452 let return_impl_trait = self
2453 .in_progress_typeck_results
2454 .map(|typeck_results| typeck_results.borrow().hir_owner)
2455 .and_then(|owner| self.tcx.return_type_impl_trait(owner))
2456 .is_some();
2457 let t = self.resolve_vars_if_possible(t);
2458 match t.kind() {
2459 // We've got:
2460 // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
2461 // suggest:
2462 // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
2463 ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
2464 new_binding_suggestion(&mut err, type_param_span, bound_kind);
2465 }
2466 _ => {
2467 binding_suggestion(&mut err, type_param_span, bound_kind, new_lt);
2468 }
2469 }
2470 }
2471 err
2472 }
2473 };
2474
2475 if let Some(origin) = origin {
2476 self.note_region_origin(&mut err, &origin);
2477 }
2478 err
2479 }
2480
report_sub_sup_conflict( &self, var_origin: RegionVariableOrigin, sub_origin: SubregionOrigin<'tcx>, sub_region: Region<'tcx>, sup_origin: SubregionOrigin<'tcx>, sup_region: Region<'tcx>, )2481 fn report_sub_sup_conflict(
2482 &self,
2483 var_origin: RegionVariableOrigin,
2484 sub_origin: SubregionOrigin<'tcx>,
2485 sub_region: Region<'tcx>,
2486 sup_origin: SubregionOrigin<'tcx>,
2487 sup_region: Region<'tcx>,
2488 ) {
2489 let mut err = self.report_inference_failure(var_origin);
2490
2491 note_and_explain_region(
2492 self.tcx,
2493 &mut err,
2494 "first, the lifetime cannot outlive ",
2495 sup_region,
2496 "...",
2497 None,
2498 );
2499
2500 debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
2501 debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
2502 debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
2503 debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
2504 debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
2505
2506 if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
2507 (&sup_origin, &sub_origin)
2508 {
2509 debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
2510 debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
2511 debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
2512 debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
2513
2514 if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
2515 (self.values_str(sup_trace.values), self.values_str(sub_trace.values))
2516 {
2517 if sub_expected == sup_expected && sub_found == sup_found {
2518 note_and_explain_region(
2519 self.tcx,
2520 &mut err,
2521 "...but the lifetime must also be valid for ",
2522 sub_region,
2523 "...",
2524 None,
2525 );
2526 err.span_note(
2527 sup_trace.cause.span,
2528 &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
2529 );
2530
2531 err.note_expected_found(&"", sup_expected, &"", sup_found);
2532 err.emit();
2533 return;
2534 }
2535 }
2536 }
2537
2538 self.note_region_origin(&mut err, &sup_origin);
2539
2540 note_and_explain_region(
2541 self.tcx,
2542 &mut err,
2543 "but, the lifetime must be valid for ",
2544 sub_region,
2545 "...",
2546 None,
2547 );
2548
2549 self.note_region_origin(&mut err, &sub_origin);
2550 err.emit();
2551 }
2552
2553 /// Determine whether an error associated with the given span and definition
2554 /// should be treated as being caused by the implicit `From` conversion
2555 /// within `?` desugaring.
is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool2556 pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool {
2557 span.is_desugaring(DesugaringKind::QuestionMark)
2558 && self.tcx.is_diagnostic_item(sym::From, trait_def_id)
2559 }
2560 }
2561
2562 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
report_inference_failure( &self, var_origin: RegionVariableOrigin, ) -> DiagnosticBuilder<'tcx>2563 fn report_inference_failure(
2564 &self,
2565 var_origin: RegionVariableOrigin,
2566 ) -> DiagnosticBuilder<'tcx> {
2567 let br_string = |br: ty::BoundRegionKind| {
2568 let mut s = match br {
2569 ty::BrNamed(_, name) => name.to_string(),
2570 _ => String::new(),
2571 };
2572 if !s.is_empty() {
2573 s.push(' ');
2574 }
2575 s
2576 };
2577 let var_description = match var_origin {
2578 infer::MiscVariable(_) => String::new(),
2579 infer::PatternRegion(_) => " for pattern".to_string(),
2580 infer::AddrOfRegion(_) => " for borrow expression".to_string(),
2581 infer::Autoref(_) => " for autoref".to_string(),
2582 infer::Coercion(_) => " for automatic coercion".to_string(),
2583 infer::LateBoundRegion(_, br, infer::FnCall) => {
2584 format!(" for lifetime parameter {}in function call", br_string(br))
2585 }
2586 infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
2587 format!(" for lifetime parameter {}in generic type", br_string(br))
2588 }
2589 infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
2590 " for lifetime parameter {}in trait containing associated type `{}`",
2591 br_string(br),
2592 self.tcx.associated_item(def_id).ident
2593 ),
2594 infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{}`", name),
2595 infer::UpvarRegion(ref upvar_id, _) => {
2596 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
2597 format!(" for capture of `{}` by closure", var_name)
2598 }
2599 infer::Nll(..) => bug!("NLL variable found in lexical phase"),
2600 };
2601
2602 struct_span_err!(
2603 self.tcx.sess,
2604 var_origin.span(),
2605 E0495,
2606 "cannot infer an appropriate lifetime{} due to conflicting requirements",
2607 var_description
2608 )
2609 }
2610 }
2611
2612 enum FailureCode {
2613 Error0038(DefId),
2614 Error0317(&'static str),
2615 Error0580(&'static str),
2616 Error0308(&'static str),
2617 Error0644(&'static str),
2618 }
2619
2620 trait ObligationCauseExt<'tcx> {
as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode2621 fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode;
as_requirement_str(&self) -> &'static str2622 fn as_requirement_str(&self) -> &'static str;
2623 }
2624
2625 impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode2626 fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
2627 use self::FailureCode::*;
2628 use crate::traits::ObligationCauseCode::*;
2629 match self.code {
2630 CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
2631 CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
2632 MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
2633 Error0308(match source {
2634 hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
2635 _ => "`match` arms have incompatible types",
2636 })
2637 }
2638 IfExpression { .. } => Error0308("`if` and `else` have incompatible types"),
2639 IfExpressionWithNoElse => Error0317("`if` may be missing an `else` clause"),
2640 LetElse => Error0308("`else` clause of `let...else` does not diverge"),
2641 MainFunctionType => Error0580("`main` function has wrong type"),
2642 StartFunctionType => Error0308("`#[start]` function has wrong type"),
2643 IntrinsicType => Error0308("intrinsic has wrong type"),
2644 MethodReceiver => Error0308("mismatched `self` parameter type"),
2645
2646 // In the case where we have no more specific thing to
2647 // say, also take a look at the error code, maybe we can
2648 // tailor to that.
2649 _ => match terr {
2650 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
2651 Error0644("closure/generator type that references itself")
2652 }
2653 TypeError::IntrinsicCast => {
2654 Error0308("cannot coerce intrinsics to function pointers")
2655 }
2656 TypeError::ObjectUnsafeCoercion(did) => Error0038(*did),
2657 _ => Error0308("mismatched types"),
2658 },
2659 }
2660 }
2661
as_requirement_str(&self) -> &'static str2662 fn as_requirement_str(&self) -> &'static str {
2663 use crate::traits::ObligationCauseCode::*;
2664 match self.code {
2665 CompareImplMethodObligation { .. } => "method type is compatible with trait",
2666 CompareImplTypeObligation { .. } => "associated type is compatible with trait",
2667 ExprAssignable => "expression is assignable",
2668 IfExpression { .. } => "`if` and `else` have incompatible types",
2669 IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
2670 MainFunctionType => "`main` function has the correct type",
2671 StartFunctionType => "`#[start]` function has the correct type",
2672 IntrinsicType => "intrinsic has the correct type",
2673 MethodReceiver => "method receiver has the correct type",
2674 _ => "types are compatible",
2675 }
2676 }
2677 }
2678
2679 /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
2680 /// extra information about each type, but we only care about the category.
2681 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
2682 pub enum TyCategory {
2683 Closure,
2684 Opaque,
2685 Generator(hir::GeneratorKind),
2686 Foreign,
2687 }
2688
2689 impl TyCategory {
descr(&self) -> &'static str2690 fn descr(&self) -> &'static str {
2691 match self {
2692 Self::Closure => "closure",
2693 Self::Opaque => "opaque type",
2694 Self::Generator(gk) => gk.descr(),
2695 Self::Foreign => "foreign type",
2696 }
2697 }
2698
from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)>2699 pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
2700 match *ty.kind() {
2701 ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
2702 ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
2703 ty::Generator(def_id, ..) => {
2704 Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
2705 }
2706 ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
2707 _ => None,
2708 }
2709 }
2710 }
2711