]> git.proxmox.com Git - rustc.git/blame - src/librustc_infer/infer/error_reporting/mod.rs
New upstream version 1.45.0+dfsg1
[rustc.git] / src / librustc_infer / infer / error_reporting / mod.rs
CommitLineData
1a4d82fc
JJ
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 basis of the system are the "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//!
3b2f2976 17//! Having a catalog of all the different reasons an error can arise is
1a4d82fc
JJ
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
abe05a73 48use super::lexical_region_resolve::RegionResolutionError;
0bf4aa26
XL
49use super::region_constraints::GenericKind;
50use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
9fa01778 51
ba9703b0 52use crate::infer;
dfeec247 53use crate::traits::error_reporting::report_object_safety_error;
60c5eb7d
XL
54use crate::traits::{
55 IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
56};
74b04a01 57
dfeec247
XL
58use rustc_data_structures::fx::{FxHashMap, FxHashSet};
59use rustc_errors::{pluralize, struct_span_err};
60use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
61use rustc_hir as hir;
62use rustc_hir::def_id::DefId;
f9f354fc 63use rustc_hir::{Item, ItemKind, Node};
ba9703b0
XL
64use rustc_middle::ty::error::TypeError;
65use rustc_middle::ty::{
66 self,
67 subst::{Subst, SubstsRef},
68 Region, Ty, TyCtxt, TypeFoldable,
69};
dfeec247 70use rustc_span::{DesugaringKind, Pos, Span};
60c5eb7d 71use rustc_target::spec::abi;
60c5eb7d 72use std::{cmp, fmt};
1a4d82fc 73
8bb4bdeb
XL
74mod note;
75
041b39d2 76mod need_type_info;
60c5eb7d 77pub use need_type_info::TypeAnnotationNeeded;
3b2f2976 78
ff7c6d11 79pub mod nice_region_error;
041b39d2 80
dfeec247
XL
81pub(super) fn note_and_explain_region(
82 tcx: TyCtxt<'tcx>,
dfeec247
XL
83 err: &mut DiagnosticBuilder<'_>,
84 prefix: &str,
85 region: ty::Region<'tcx>,
86 suffix: &str,
87) {
88 let (description, span) = match *region {
dfeec247
XL
89 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
90 msg_span_from_free_region(tcx, region)
91 }
62682a34 92
74b04a01
XL
93 ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), None),
94
95 // uh oh, hope no user ever sees THIS
96 ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
62682a34 97
74b04a01 98 ty::RePlaceholder(_) => ("any other region".to_string(), None),
0731742a 99
dfeec247
XL
100 // FIXME(#13998) RePlaceholder should probably print like
101 // ReFree rather than dumping Debug output on the user.
102 //
103 // We shouldn't really be having unification failures with ReVar
104 // and ReLateBound though.
105 ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
106 (format!("lifetime {:?}", region), None)
107 }
dfeec247 108 };
0531ce1d 109
dfeec247
XL
110 emit_msg_span(err, prefix, description, span, suffix);
111}
0531ce1d 112
dfeec247
XL
113pub(super) fn note_and_explain_free_region(
114 tcx: TyCtxt<'tcx>,
115 err: &mut DiagnosticBuilder<'_>,
116 prefix: &str,
117 region: ty::Region<'tcx>,
118 suffix: &str,
119) {
120 let (description, span) = msg_span_from_free_region(tcx, region);
0531ce1d 121
dfeec247
XL
122 emit_msg_span(err, prefix, description, span, suffix);
123}
0531ce1d 124
dfeec247
XL
125fn msg_span_from_free_region(
126 tcx: TyCtxt<'tcx>,
127 region: ty::Region<'tcx>,
128) -> (String, Option<Span>) {
129 match *region {
130 ty::ReEarlyBound(_) | ty::ReFree(_) => {
131 msg_span_from_early_bound_and_free_regions(tcx, region)
0531ce1d 132 }
dfeec247 133 ty::ReStatic => ("the static lifetime".to_owned(), None),
74b04a01
XL
134 ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), None),
135 ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), None),
dfeec247 136 _ => bug!("{:?}", region),
0531ce1d 137 }
dfeec247 138}
0531ce1d 139
dfeec247
XL
140fn msg_span_from_early_bound_and_free_regions(
141 tcx: TyCtxt<'tcx>,
142 region: ty::Region<'tcx>,
143) -> (String, Option<Span>) {
74b04a01 144 let sm = tcx.sess.source_map();
dfeec247
XL
145
146 let scope = region.free_region_binding_scope(tcx);
f9f354fc 147 let node = tcx.hir().as_local_hir_id(scope.expect_local());
dfeec247 148 let tag = match tcx.hir().find(node) {
ba9703b0 149 Some(Node::Block(_) | Node::Expr(_)) => "body",
dfeec247
XL
150 Some(Node::Item(it)) => item_scope_tag(&it),
151 Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
152 Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
153 _ => unreachable!(),
154 };
155 let (prefix, span) = match *region {
156 ty::ReEarlyBound(ref br) => {
ba9703b0 157 let mut sp = sm.guess_head_span(tcx.hir().span(node));
dfeec247
XL
158 if let Some(param) =
159 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
160 {
161 sp = param.span;
8faf50e0 162 }
dfeec247 163 (format!("the lifetime `{}` as defined on", br.name), sp)
62682a34 164 }
dfeec247 165 ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => {
ba9703b0 166 let mut sp = sm.guess_head_span(tcx.hir().span(node));
dfeec247
XL
167 if let Some(param) =
168 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
169 {
170 sp = param.span;
171 }
172 (format!("the lifetime `{}` as defined on", name), sp)
0531ce1d 173 }
dfeec247
XL
174 ty::ReFree(ref fr) => match fr.bound_region {
175 ty::BrAnon(idx) => {
176 (format!("the anonymous lifetime #{} defined on", idx + 1), tcx.hir().span(node))
177 }
178 _ => (
179 format!("the lifetime `{}` as defined on", region),
ba9703b0 180 sm.guess_head_span(tcx.hir().span(node)),
dfeec247
XL
181 ),
182 },
183 _ => bug!(),
184 };
185 let (msg, opt_span) = explain_span(tcx, tag, span);
186 (format!("{} {}", prefix, msg), opt_span)
187}
188
189fn emit_msg_span(
190 err: &mut DiagnosticBuilder<'_>,
191 prefix: &str,
192 description: String,
193 span: Option<Span>,
194 suffix: &str,
195) {
196 let message = format!("{}{}{}", prefix, description, suffix);
197
198 if let Some(span) = span {
199 err.span_note(span, &message);
200 } else {
201 err.note(&message);
0531ce1d 202 }
dfeec247 203}
0531ce1d 204
dfeec247
XL
205fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
206 match item.kind {
207 hir::ItemKind::Impl { .. } => "impl",
208 hir::ItemKind::Struct(..) => "struct",
209 hir::ItemKind::Union(..) => "union",
210 hir::ItemKind::Enum(..) => "enum",
211 hir::ItemKind::Trait(..) => "trait",
212 hir::ItemKind::Fn(..) => "function body",
213 _ => "item",
0531ce1d 214 }
dfeec247 215}
0531ce1d 216
dfeec247
XL
217fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
218 match item.kind {
ba9703b0 219 hir::TraitItemKind::Fn(..) => "method body",
dfeec247 220 hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
0531ce1d 221 }
dfeec247 222}
0531ce1d 223
dfeec247
XL
224fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
225 match item.kind {
ba9703b0 226 hir::ImplItemKind::Fn(..) => "method body",
dfeec247
XL
227 hir::ImplItemKind::Const(..)
228 | hir::ImplItemKind::OpaqueTy(..)
229 | hir::ImplItemKind::TyAlias(..) => "associated item",
0531ce1d 230 }
62682a34 231}
1a4d82fc 232
dfeec247
XL
233fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option<Span>) {
234 let lo = tcx.sess.source_map().lookup_char_pos(span.lo());
235 (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
236}
237
ba9703b0
XL
238pub fn unexpected_hidden_region_diagnostic(
239 tcx: TyCtxt<'tcx>,
ba9703b0
XL
240 span: Span,
241 hidden_ty: Ty<'tcx>,
242 hidden_region: ty::Region<'tcx>,
243) -> DiagnosticBuilder<'tcx> {
244 let mut err = struct_span_err!(
245 tcx.sess,
246 span,
247 E0700,
248 "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
249 );
250
251 // Explain the region we are capturing.
f9f354fc
XL
252 match hidden_region {
253 ty::ReEmpty(ty::UniverseIndex::ROOT) => {
254 // All lifetimes shorter than the function body are `empty` in
255 // lexical region resolution. The default explanation of "an empty
256 // lifetime" isn't really accurate here.
257 let message = format!(
258 "hidden type `{}` captures lifetime smaller than the function body",
259 hidden_ty
260 );
261 err.span_note(span, &message);
262 }
263 ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
264 // Assuming regionck succeeded (*), we ought to always be
265 // capturing *some* region from the fn header, and hence it
266 // ought to be free. So under normal circumstances, we will go
267 // down this path which gives a decent human readable
268 // explanation.
269 //
270 // (*) if not, the `tainted_by_errors` field would be set to
271 // `Some(ErrorReported)` in any case, so we wouldn't be here at all.
272 note_and_explain_free_region(
ba9703b0 273 tcx,
ba9703b0
XL
274 &mut err,
275 &format!("hidden type `{}` captures ", hidden_ty),
276 hidden_region,
277 "",
278 );
f9f354fc
XL
279 }
280 _ => {
281 // Ugh. This is a painful case: the hidden region is not one
282 // that we can easily summarize or explain. This can happen
283 // in a case like
284 // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
285 //
286 // ```
287 // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
288 // if condition() { a } else { b }
289 // }
290 // ```
291 //
292 // Here the captured lifetime is the intersection of `'a` and
293 // `'b`, which we can't quite express.
294
295 // We can at least report a really cryptic error for now.
296 note_and_explain_region(
297 tcx,
298 &mut err,
299 &format!("hidden type `{}` captures ", hidden_ty),
300 hidden_region,
301 "",
ba9703b0
XL
302 );
303 }
304 }
305
306 err
307}
308
dc9dc135 309impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
f9f354fc 310 pub fn report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>) {
ba9703b0 311 debug!("report_region_errors(): {} errors to start", errors.len());
abe05a73 312
54a0048b
SL
313 // try to pre-process the errors, which will group some of them
314 // together into a `ProcessedErrors` group:
32a655c1 315 let errors = self.process_errors(errors);
54a0048b 316
dfeec247 317 debug!("report_region_errors: {} errors after preprocessing", errors.len());
54a0048b 318
85aaf69f 319 for error in errors {
c30ab7b3 320 debug!("report_region_errors: error = {:?}", error);
1a4d82fc 321
ff7c6d11 322 if !self.try_report_nice_region_error(&error) {
abe05a73
XL
323 match error.clone() {
324 // These errors could indicate all manner of different
325 // problems with many different solutions. Rather
326 // than generate a "one size fits all" error, what we
327 // attempt to do is go through a number of specific
328 // scenarios and try to find the best way to present
329 // the error. If all of these fails, we fall back to a rather
330 // general bit of code that displays the error information
331 RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
0731742a 332 if sub.is_placeholder() || sup.is_placeholder() {
f9f354fc 333 self.report_placeholder_failure(origin, sub, sup).emit();
0731742a 334 } else {
f9f354fc 335 self.report_concrete_failure(origin, sub, sup).emit();
0731742a 336 }
abe05a73
XL
337 }
338
ff7c6d11
XL
339 RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
340 self.report_generic_bound_failure(
ff7c6d11
XL
341 origin.span(),
342 Some(origin),
343 param_ty,
344 sub,
345 );
abe05a73
XL
346 }
347
0531ce1d 348 RegionResolutionError::SubSupConflict(
0731742a 349 _,
0531ce1d
XL
350 var_origin,
351 sub_origin,
352 sub_r,
353 sup_origin,
354 sup_r,
355 ) => {
0731742a 356 if sub_r.is_placeholder() {
f9f354fc 357 self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
0731742a 358 } else if sup_r.is_placeholder() {
f9f354fc 359 self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
0731742a
XL
360 } else {
361 self.report_sub_sup_conflict(
f9f354fc 362 var_origin, sub_origin, sub_r, sup_origin, sup_r,
0731742a
XL
363 );
364 }
abe05a73 365 }
dc9dc135 366
74b04a01
XL
367 RegionResolutionError::UpperBoundUniverseConflict(
368 _,
369 _,
370 var_universe,
371 sup_origin,
372 sup_r,
373 ) => {
374 assert!(sup_r.is_placeholder());
375
376 // Make a dummy value for the "sub region" --
377 // this is the initial value of the
378 // placeholder. In practice, we expect more
379 // tailored errors that don't really use this
380 // value.
381 let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
382
f9f354fc 383 self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
74b04a01
XL
384 }
385
dc9dc135 386 RegionResolutionError::MemberConstraintFailure {
dc9dc135
XL
387 hidden_ty,
388 member_region,
74b04a01 389 span,
dc9dc135
XL
390 } => {
391 let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
ba9703b0 392 unexpected_hidden_region_diagnostic(
dc9dc135 393 self.tcx,
74b04a01 394 span,
dc9dc135
XL
395 hidden_ty,
396 member_region,
dfeec247
XL
397 )
398 .emit();
dc9dc135 399 }
abe05a73 400 }
1a4d82fc
JJ
401 }
402 }
403 }
404
405 // This method goes through all the errors and try to group certain types
406 // of error together, for the purpose of suggesting explicit lifetime
407 // parameters to the user. This is done so that we can have a more
408 // complete view of what lifetimes should be the same.
409 // If the return value is an empty vector, it means that processing
54a0048b
SL
410 // failed (so the return value of this method should not be used).
411 //
412 // The method also attempts to weed out messages that seem like
413 // duplicates that will be unhelpful to the end-user. But
414 // obviously it never weeds out ALL errors.
0531ce1d
XL
415 fn process_errors(
416 &self,
417 errors: &Vec<RegionResolutionError<'tcx>>,
418 ) -> Vec<RegionResolutionError<'tcx>> {
1a4d82fc 419 debug!("process_errors()");
54a0048b 420
32a655c1
SL
421 // We want to avoid reporting generic-bound failures if we can
422 // avoid it: these have a very high rate of being unhelpful in
423 // practice. This is because they are basically secondary
424 // checks that test the state of the region graph after the
425 // rest of inference is done, and the other kinds of errors
426 // indicate that the region constraint graph is internally
427 // inconsistent, so these test results are likely to be
428 // meaningless.
429 //
430 // Therefore, we filter them out of the list unless they are
431 // the only thing in the list.
432
433 let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
abe05a73 434 RegionResolutionError::GenericBoundFailure(..) => true,
0531ce1d 435 RegionResolutionError::ConcreteFailure(..)
dfeec247 436 | RegionResolutionError::SubSupConflict(..)
74b04a01 437 | RegionResolutionError::UpperBoundUniverseConflict(..)
dfeec247 438 | RegionResolutionError::MemberConstraintFailure { .. } => false,
32a655c1 439 };
1a4d82fc 440
ea8adc8c 441 let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
32a655c1
SL
442 errors.clone()
443 } else {
dfeec247 444 errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
ea8adc8c
XL
445 };
446
447 // sort the errors by span, for better error message stability.
448 errors.sort_by_key(|u| match *u {
abe05a73
XL
449 RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
450 RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
0731742a 451 RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
74b04a01 452 RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
dc9dc135 453 RegionResolutionError::MemberConstraintFailure { span, .. } => span,
ea8adc8c
XL
454 });
455 errors
1a4d82fc
JJ
456 }
457
e9174d1e 458 /// Adds a note if the types come from similarly named crates
0531ce1d
XL
459 fn check_and_note_conflicting_crates(
460 &self,
0bf4aa26 461 err: &mut DiagnosticBuilder<'_>,
0531ce1d 462 terr: &TypeError<'tcx>,
0531ce1d 463 ) {
532ac7d7 464 use hir::def_id::CrateNum;
ba9703b0 465 use rustc_hir::definitions::DisambiguatedDefPathData;
532ac7d7 466 use ty::print::Printer;
e74abb32 467 use ty::subst::GenericArg;
532ac7d7 468
dc9dc135
XL
469 struct AbsolutePathPrinter<'tcx> {
470 tcx: TyCtxt<'tcx>,
532ac7d7
XL
471 }
472
473 struct NonTrivialPath;
474
dc9dc135 475 impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
532ac7d7
XL
476 type Error = NonTrivialPath;
477
478 type Path = Vec<String>;
479 type Region = !;
480 type Type = !;
481 type DynExistential = !;
dc9dc135 482 type Const = !;
532ac7d7 483
dc9dc135 484 fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
532ac7d7
XL
485 self.tcx
486 }
487
dfeec247 488 fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
532ac7d7
XL
489 Err(NonTrivialPath)
490 }
491
dfeec247 492 fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
532ac7d7
XL
493 Err(NonTrivialPath)
494 }
495
496 fn print_dyn_existential(
497 self,
498 _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
499 ) -> Result<Self::DynExistential, Self::Error> {
500 Err(NonTrivialPath)
501 }
502
dfeec247 503 fn print_const(self, _ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
dc9dc135
XL
504 Err(NonTrivialPath)
505 }
506
dfeec247 507 fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
532ac7d7
XL
508 Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
509 }
510 fn path_qualified(
511 self,
512 _self_ty: Ty<'tcx>,
513 _trait_ref: Option<ty::TraitRef<'tcx>>,
514 ) -> Result<Self::Path, Self::Error> {
515 Err(NonTrivialPath)
516 }
517
518 fn path_append_impl(
519 self,
520 _print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
521 _disambiguated_data: &DisambiguatedDefPathData,
522 _self_ty: Ty<'tcx>,
523 _trait_ref: Option<ty::TraitRef<'tcx>>,
524 ) -> Result<Self::Path, Self::Error> {
525 Err(NonTrivialPath)
526 }
527 fn path_append(
528 self,
529 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
530 disambiguated_data: &DisambiguatedDefPathData,
531 ) -> Result<Self::Path, Self::Error> {
532 let mut path = print_prefix(self)?;
e74abb32 533 path.push(disambiguated_data.data.as_symbol().to_string());
532ac7d7
XL
534 Ok(path)
535 }
536 fn path_generic_args(
537 self,
538 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
e74abb32 539 _args: &[GenericArg<'tcx>],
532ac7d7
XL
540 ) -> Result<Self::Path, Self::Error> {
541 print_prefix(self)
542 }
543 }
544
0bf4aa26 545 let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
e9174d1e
SL
546 // Only external crates, if either is from a local
547 // module we could have false positives
548 if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
dfeec247
XL
549 let abs_path =
550 |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]);
532ac7d7 551
54a0048b 552 // We compare strings because DefPath can be different
e9174d1e 553 // for imported and non-imported crates
532ac7d7 554 let same_path = || -> Result<_, NonTrivialPath> {
dfeec247
XL
555 Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
556 || abs_path(did1)? == abs_path(did2)?)
532ac7d7
XL
557 };
558 if same_path().unwrap_or(false) {
ea8adc8c 559 let crate_name = self.tcx.crate_name(did1.krate);
60c5eb7d
XL
560 err.note(&format!(
561 "perhaps two different versions of crate `{}` are being used?",
562 crate_name
563 ));
e9174d1e
SL
564 }
565 }
566 };
567 match *terr {
568 TypeError::Sorts(ref exp_found) => {
569 // if they are both "path types", there's a chance of ambiguity
570 // due to different versions of the same crate
dfeec247
XL
571 if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
572 (&exp_found.expected.kind, &exp_found.found.kind)
0bf4aa26
XL
573 {
574 report_path_match(err, exp_adt.did, found_adt.did);
e9174d1e 575 }
0531ce1d 576 }
e9174d1e 577 TypeError::Traits(ref exp_found) => {
9cc50fc6 578 report_path_match(err, exp_found.expected, exp_found.found);
0531ce1d
XL
579 }
580 _ => (), // FIXME(#22750) handle traits and stuff
e9174d1e
SL
581 }
582 }
583
9fa01778
XL
584 fn note_error_origin(
585 &self,
586 err: &mut DiagnosticBuilder<'tcx>,
587 cause: &ObligationCause<'tcx>,
588 exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
589 ) {
476ff2be 590 match cause.code {
dfeec247
XL
591 ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
592 let ty = self.resolve_vars_if_possible(&root_ty);
593 if ty.is_suggestable() {
594 // don't show type `_`
595 err.span_label(span, format!("this expression has type `{}`", ty));
0731742a 596 }
9fa01778
XL
597 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
598 if ty.is_box() && ty.boxed_ty() == found {
599 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
600 err.span_suggestion(
601 span,
602 "consider dereferencing the boxed value",
603 format!("*{}", snippet),
604 Applicability::MachineApplicable,
605 );
606 }
607 }
608 }
0731742a 609 }
dfeec247
XL
610 ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
611 err.span_label(span, "expected due to this");
612 }
e1599b0c 613 ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
9fa01778
XL
614 source,
615 ref prior_arms,
616 last_ty,
dfeec247 617 scrut_hir_id,
9fa01778 618 ..
e1599b0c 619 }) => match source {
0531ce1d 620 hir::MatchSource::IfLetDesugar { .. } => {
9fa01778
XL
621 let msg = "`if let` arms have incompatible types";
622 err.span_label(cause.span, msg);
0bf4aa26 623 }
48663c56
XL
624 hir::MatchSource::TryDesugar => {
625 if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
dfeec247
XL
626 let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
627 let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
48663c56 628 let arg_expr = args.first().expect("try desugaring call w/out arg");
dfeec247
XL
629 self.in_progress_tables
630 .and_then(|tables| tables.borrow().expr_ty_opt(arg_expr))
48663c56 631 } else {
dfeec247 632 bug!("try desugaring w/out call expr as scrutinee");
48663c56
XL
633 };
634
dfeec247 635 match scrut_ty {
48663c56
XL
636 Some(ty) if expected == ty => {
637 let source_map = self.tcx.sess.source_map();
638 err.span_suggestion(
639 source_map.end_point(cause.span),
640 "try removing this `?`",
641 "".to_string(),
642 Applicability::MachineApplicable,
643 );
dfeec247
XL
644 }
645 _ => {}
48663c56
XL
646 }
647 }
648 }
5bcae85e 649 _ => {
416331ca
XL
650 // `last_ty` can be `!`, `expected` will have better info when present.
651 let t = self.resolve_vars_if_possible(&match exp_found {
652 Some(ty::error::ExpectedFound { expected, .. }) => expected,
653 _ => last_ty,
654 });
9fa01778
XL
655 let msg = "`match` arms have incompatible types";
656 err.span_label(cause.span, msg);
657 if prior_arms.len() <= 4 {
658 for sp in prior_arms {
dfeec247 659 err.span_label(*sp, format!("this is found to be of type `{}`", t));
9fa01778
XL
660 }
661 } else if let Some(sp) = prior_arms.last() {
416331ca
XL
662 err.span_label(
663 *sp,
664 format!("this and all prior arms are found to be of type `{}`", t),
665 );
ff7c6d11 666 }
5bcae85e
SL
667 }
668 },
e1599b0c 669 ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => {
0731742a 670 err.span_label(then, "expected because of this");
f9f354fc
XL
671 if let Some(sp) = outer {
672 err.span_label(sp, "`if` and `else` have incompatible types");
673 }
0731742a 674 if let Some(sp) = semicolon {
9fa01778 675 err.span_suggestion_short(
0731742a
XL
676 sp,
677 "consider removing this semicolon",
678 String::new(),
679 Applicability::MachineApplicable,
680 );
681 }
682 }
0531ce1d 683 _ => (),
5bcae85e
SL
684 }
685 }
686
cc61c64b
XL
687 /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
688 /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
689 /// populate `other_value` with `other_ty`.
690 ///
691 /// ```text
692 /// Foo<Bar<Qux>>
693 /// ^^^^--------^ this is highlighted
694 /// | |
695 /// | this type argument is exactly the same as the other type, not highlighted
696 /// this is highlighted
697 /// Bar<Qux>
698 /// -------- this type is the same as a type argument in the other type, not highlighted
699 /// ```
0531ce1d
XL
700 fn highlight_outer(
701 &self,
702 value: &mut DiagnosticStyledString,
703 other_value: &mut DiagnosticStyledString,
704 name: String,
532ac7d7 705 sub: ty::subst::SubstsRef<'tcx>,
0531ce1d 706 pos: usize,
48663c56 707 other_ty: Ty<'tcx>,
0531ce1d 708 ) {
cc61c64b
XL
709 // `value` and `other_value` hold two incomplete type representation for display.
710 // `name` is the path of both types being compared. `sub`
711 value.push_highlighted(name);
712 let len = sub.len();
713 if len > 0 {
714 value.push_highlighted("<");
715 }
716
b7449926 717 // Output the lifetimes for the first type
dfeec247
XL
718 let lifetimes = sub
719 .regions()
0531ce1d 720 .map(|lifetime| {
8faf50e0 721 let s = lifetime.to_string();
dfeec247 722 if s.is_empty() { "'_".to_string() } else { s }
0531ce1d
XL
723 })
724 .collect::<Vec<_>>()
725 .join(", ");
cc61c64b
XL
726 if !lifetimes.is_empty() {
727 if sub.regions().count() < len {
74b04a01 728 value.push_normal(lifetimes + ", ");
cc61c64b
XL
729 } else {
730 value.push_normal(lifetimes);
731 }
732 }
733
734 // Highlight all the type arguments that aren't at `pos` and compare the type argument at
735 // `pos` and `other_ty`.
736 for (i, type_arg) in sub.types().enumerate() {
737 if i == pos {
738 let values = self.cmp(type_arg, other_ty);
739 value.0.extend((values.0).0);
740 other_value.0.extend((values.1).0);
741 } else {
8faf50e0 742 value.push_highlighted(type_arg.to_string());
cc61c64b
XL
743 }
744
745 if len > 0 && i != len - 1 {
746 value.push_normal(", ");
747 }
cc61c64b
XL
748 }
749 if len > 0 {
750 value.push_highlighted(">");
751 }
752 }
753
754 /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
755 /// as that is the difference to the other type.
756 ///
757 /// For the following code:
758 ///
f9f354fc 759 /// ```no_run
cc61c64b
XL
760 /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
761 /// ```
762 ///
763 /// The type error output will behave in the following way:
764 ///
765 /// ```text
766 /// Foo<Bar<Qux>>
767 /// ^^^^--------^ this is highlighted
768 /// | |
769 /// | this type argument is exactly the same as the other type, not highlighted
770 /// this is highlighted
771 /// Bar<Qux>
772 /// -------- this type is the same as a type argument in the other type, not highlighted
773 /// ```
0531ce1d
XL
774 fn cmp_type_arg(
775 &self,
776 mut t1_out: &mut DiagnosticStyledString,
777 mut t2_out: &mut DiagnosticStyledString,
778 path: String,
532ac7d7 779 sub: ty::subst::SubstsRef<'tcx>,
0531ce1d 780 other_path: String,
48663c56 781 other_ty: Ty<'tcx>,
0531ce1d 782 ) -> Option<()> {
cc61c64b 783 for (i, ta) in sub.types().enumerate() {
48663c56 784 if ta == other_ty {
cc61c64b
XL
785 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
786 return Some(());
787 }
e74abb32 788 if let &ty::Adt(def, _) = &ta.kind {
ba9703b0 789 let path_ = self.tcx.def_path_str(def.did);
cc61c64b
XL
790 if path_ == other_path {
791 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
792 return Some(());
793 }
794 }
795 }
796 None
797 }
798
9fa01778 799 /// Adds a `,` to the type representation only if it is appropriate.
0531ce1d
XL
800 fn push_comma(
801 &self,
802 value: &mut DiagnosticStyledString,
803 other_value: &mut DiagnosticStyledString,
804 len: usize,
805 pos: usize,
806 ) {
cc61c64b
XL
807 if len > 0 && pos != len - 1 {
808 value.push_normal(", ");
809 other_value.push_normal(", ");
810 }
811 }
812
8faf50e0 813 /// For generic types with parameters with defaults, remove the parameters corresponding to
532ac7d7 814 /// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
8faf50e0
XL
815 fn strip_generic_default_params(
816 &self,
817 def_id: DefId,
532ac7d7
XL
818 substs: ty::subst::SubstsRef<'tcx>,
819 ) -> SubstsRef<'tcx> {
8faf50e0
XL
820 let generics = self.tcx.generics_of(def_id);
821 let mut num_supplied_defaults = 0;
dfeec247
XL
822 let mut type_params = generics
823 .params
824 .iter()
825 .rev()
826 .filter_map(|param| match param.kind {
827 ty::GenericParamDefKind::Lifetime => None,
828 ty::GenericParamDefKind::Type { has_default, .. } => {
829 Some((param.def_id, has_default))
830 }
831 ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
832 })
833 .peekable();
8faf50e0
XL
834 let has_default = {
835 let has_default = type_params.peek().map(|(_, has_default)| has_default);
836 *has_default.unwrap_or(&false)
837 };
838 if has_default {
839 let types = substs.types().rev();
840 for ((def_id, has_default), actual) in type_params.zip(types) {
841 if !has_default {
842 break;
843 }
844 if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual {
845 break;
846 }
847 num_supplied_defaults += 1;
848 }
849 }
850 let len = generics.params.len();
851 let mut generics = generics.clone();
852 generics.params.truncate(len - num_supplied_defaults);
853 substs.truncate_to(self.tcx, &generics)
854 }
855
60c5eb7d
XL
856 /// Given two `fn` signatures highlight only sub-parts that are different.
857 fn cmp_fn_sig(
858 &self,
859 sig1: &ty::PolyFnSig<'tcx>,
860 sig2: &ty::PolyFnSig<'tcx>,
861 ) -> (DiagnosticStyledString, DiagnosticStyledString) {
862 let get_lifetimes = |sig| {
dfeec247 863 use rustc_hir::def::Namespace;
60c5eb7d
XL
864 let mut s = String::new();
865 let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
866 .name_all_regions(sig)
867 .unwrap();
868 let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();
dfeec247 869 (if lts.is_empty() { String::new() } else { format!("for<{}> ", lts.join(", ")) }, sig)
60c5eb7d
XL
870 };
871
872 let (lt1, sig1) = get_lifetimes(sig1);
873 let (lt2, sig2) = get_lifetimes(sig2);
874
875 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
876 let mut values = (
877 DiagnosticStyledString::normal("".to_string()),
878 DiagnosticStyledString::normal("".to_string()),
879 );
880
881 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
882 // ^^^^^^
883 values.0.push(sig1.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety);
884 values.1.push(sig2.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety);
885
886 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
887 // ^^^^^^^^^^
888 if sig1.abi != abi::Abi::Rust {
889 values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi);
890 }
891 if sig2.abi != abi::Abi::Rust {
892 values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi);
893 }
894
895 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
896 // ^^^^^^^^
897 let lifetime_diff = lt1 != lt2;
898 values.0.push(lt1, lifetime_diff);
899 values.1.push(lt2, lifetime_diff);
900
901 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
902 // ^^^
903 values.0.push_normal("fn(");
904 values.1.push_normal("fn(");
905
906 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
907 // ^^^^^
908 let len1 = sig1.inputs().len();
909 let len2 = sig2.inputs().len();
910 if len1 == len2 {
911 for (i, (l, r)) in sig1.inputs().iter().zip(sig2.inputs().iter()).enumerate() {
912 let (x1, x2) = self.cmp(l, r);
913 (values.0).0.extend(x1.0);
914 (values.1).0.extend(x2.0);
915 self.push_comma(&mut values.0, &mut values.1, len1, i);
916 }
917 } else {
918 for (i, l) in sig1.inputs().iter().enumerate() {
919 values.0.push_highlighted(l.to_string());
920 if i != len1 - 1 {
921 values.0.push_highlighted(", ");
922 }
923 }
924 for (i, r) in sig2.inputs().iter().enumerate() {
925 values.1.push_highlighted(r.to_string());
926 if i != len2 - 1 {
927 values.1.push_highlighted(", ");
928 }
929 }
930 }
931
932 if sig1.c_variadic {
933 if len1 > 0 {
934 values.0.push_normal(", ");
935 }
936 values.0.push("...", !sig2.c_variadic);
937 }
938 if sig2.c_variadic {
939 if len2 > 0 {
940 values.1.push_normal(", ");
941 }
942 values.1.push("...", !sig1.c_variadic);
943 }
944
945 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
946 // ^
947 values.0.push_normal(")");
948 values.1.push_normal(")");
949
950 // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
951 // ^^^^^^^^
952 let output1 = sig1.output();
953 let output2 = sig2.output();
954 let (x1, x2) = self.cmp(output1, output2);
955 if !output1.is_unit() {
956 values.0.push_normal(" -> ");
957 (values.0).0.extend(x1.0);
958 }
959 if !output2.is_unit() {
960 values.1.push_normal(" -> ");
961 (values.1).0.extend(x2.0);
962 }
963 values
964 }
965
9fa01778 966 /// Compares two given types, eliding parts that are the same between them and highlighting
cc61c64b 967 /// relevant differences, and return two representation of those types for highlighted printing.
0531ce1d 968 fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) {
e74abb32
XL
969 debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind, t2, t2.kind);
970
971 // helper functions
48663c56 972 fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
e74abb32 973 match (&a.kind, &b.kind) {
ff7c6d11 974 (a, b) if *a == *b => true,
b7449926 975 (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
ba9703b0
XL
976 | (
977 &ty::Infer(ty::InferTy::IntVar(_)),
978 &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)),
979 )
b7449926 980 | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
ba9703b0
XL
981 | (
982 &ty::Infer(ty::InferTy::FloatVar(_)),
983 &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
984 ) => true,
ff7c6d11
XL
985 _ => false,
986 }
987 }
988
0531ce1d 989 fn push_ty_ref<'tcx>(
f9f354fc 990 region: &ty::Region<'tcx>,
94b46f34
XL
991 ty: Ty<'tcx>,
992 mutbl: hir::Mutability,
0531ce1d
XL
993 s: &mut DiagnosticStyledString,
994 ) {
f9f354fc 995 let mut r = region.to_string();
532ac7d7
XL
996 if r == "'_" {
997 r.clear();
998 } else {
999 r.push(' ');
1000 }
60c5eb7d 1001 s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str()));
8faf50e0 1002 s.push_normal(ty.to_string());
ff7c6d11
XL
1003 }
1004
e74abb32
XL
1005 // process starts here
1006 match (&t1.kind, &t2.kind) {
b7449926 1007 (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
8faf50e0
XL
1008 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
1009 let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
cc61c64b 1010 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
ba9703b0
XL
1011 let path1 = self.tcx.def_path_str(def1.did);
1012 let path2 = self.tcx.def_path_str(def2.did);
cc61c64b
XL
1013 if def1.did == def2.did {
1014 // Easy case. Replace same types with `_` to shorten the output and highlight
1015 // the differing ones.
1016 // let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
1017 // Foo<Bar, _>
1018 // Foo<Quz, _>
1019 // --- ^ type argument elided
1020 // |
1021 // highlighted in output
1022 values.0.push_normal(path1);
1023 values.1.push_normal(path2);
1024
8faf50e0
XL
1025 // Avoid printing out default generic parameters that are common to both
1026 // types.
1027 let len1 = sub_no_defaults_1.len();
1028 let len2 = sub_no_defaults_2.len();
1029 let common_len = cmp::min(len1, len2);
1030 let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
1031 let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
0bf4aa26
XL
1032 let common_default_params = remainder1
1033 .iter()
1034 .rev()
1035 .zip(remainder2.iter().rev())
1036 .filter(|(a, b)| a == b)
1037 .count();
8faf50e0 1038 let len = sub1.len() - common_default_params;
e74abb32 1039 let consts_offset = len - sub1.consts().count();
8faf50e0 1040
cc61c64b 1041 // Only draw `<...>` if there're lifetime/type arguments.
cc61c64b
XL
1042 if len > 0 {
1043 values.0.push_normal("<");
1044 values.1.push_normal("<");
1045 }
1046
0bf4aa26 1047 fn lifetime_display(lifetime: Region<'_>) -> String {
8faf50e0 1048 let s = lifetime.to_string();
dfeec247 1049 if s.is_empty() { "'_".to_string() } else { s }
cc61c64b
XL
1050 }
1051 // At one point we'd like to elide all lifetimes here, they are irrelevant for
1052 // all diagnostics that use this output
1053 //
1054 // Foo<'x, '_, Bar>
1055 // Foo<'y, '_, Qux>
1056 // ^^ ^^ --- type arguments are not elided
1057 // | |
1058 // | elided as they were the same
1059 // not elided, they were different, but irrelevant
1060 let lifetimes = sub1.regions().zip(sub2.regions());
1061 for (i, lifetimes) in lifetimes.enumerate() {
1062 let l1 = lifetime_display(lifetimes.0);
1063 let l2 = lifetime_display(lifetimes.1);
60c5eb7d 1064 if lifetimes.0 == lifetimes.1 {
cc61c64b
XL
1065 values.0.push_normal("'_");
1066 values.1.push_normal("'_");
1067 } else {
1068 values.0.push_highlighted(l1);
1069 values.1.push_highlighted(l2);
1070 }
1071 self.push_comma(&mut values.0, &mut values.1, len, i);
1072 }
1073
1074 // We're comparing two types with the same path, so we compare the type
1075 // arguments for both. If they are the same, do not highlight and elide from the
1076 // output.
1077 // Foo<_, Bar>
1078 // Foo<_, Qux>
1079 // ^ elided type as this type argument was the same in both sides
1080 let type_arguments = sub1.types().zip(sub2.types());
8faf50e0 1081 let regions_len = sub1.regions().count();
e74abb32
XL
1082 let num_display_types = consts_offset - regions_len;
1083 for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
cc61c64b
XL
1084 let i = i + regions_len;
1085 if ta1 == ta2 {
1086 values.0.push_normal("_");
1087 values.1.push_normal("_");
1088 } else {
1089 let (x1, x2) = self.cmp(ta1, ta2);
1090 (values.0).0.extend(x1.0);
1091 (values.1).0.extend(x2.0);
1092 }
1093 self.push_comma(&mut values.0, &mut values.1, len, i);
1094 }
1095
e74abb32
XL
1096 // Do the same for const arguments, if they are equal, do not highlight and
1097 // elide them from the output.
1098 let const_arguments = sub1.consts().zip(sub2.consts());
1099 for (i, (ca1, ca2)) in const_arguments.enumerate() {
1100 let i = i + consts_offset;
1101 if ca1 == ca2 {
1102 values.0.push_normal("_");
1103 values.1.push_normal("_");
1104 } else {
1105 values.0.push_highlighted(ca1.to_string());
1106 values.1.push_highlighted(ca2.to_string());
1107 }
1108 self.push_comma(&mut values.0, &mut values.1, len, i);
1109 }
1110
cc61c64b
XL
1111 // Close the type argument bracket.
1112 // Only draw `<...>` if there're lifetime/type arguments.
1113 if len > 0 {
1114 values.0.push_normal(">");
1115 values.1.push_normal(">");
1116 }
1117 values
1118 } else {
1119 // Check for case:
1120 // let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
1121 // Foo<Bar<Qux>
1122 // ------- this type argument is exactly the same as the other type
1123 // Bar<Qux>
dfeec247
XL
1124 if self
1125 .cmp_type_arg(
1126 &mut values.0,
1127 &mut values.1,
1128 path1.clone(),
1129 sub_no_defaults_1,
1130 path2.clone(),
1131 &t2,
1132 )
1133 .is_some()
0531ce1d 1134 {
cc61c64b
XL
1135 return values;
1136 }
1137 // Check for case:
1138 // let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
1139 // Bar<Qux>
1140 // Foo<Bar<Qux>>
1141 // ------- this type argument is exactly the same as the other type
dfeec247
XL
1142 if self
1143 .cmp_type_arg(
1144 &mut values.1,
1145 &mut values.0,
1146 path2,
1147 sub_no_defaults_2,
1148 path1,
1149 &t1,
1150 )
1151 .is_some()
0531ce1d 1152 {
cc61c64b
XL
1153 return values;
1154 }
1155
e74abb32
XL
1156 // We can't find anything in common, highlight relevant part of type path.
1157 // let x: foo::bar::Baz<Qux> = y:<foo::bar::Bar<Zar>>();
1158 // foo::bar::Baz<Qux>
1159 // foo::bar::Bar<Zar>
1160 // -------- this part of the path is different
1161
1162 let t1_str = t1.to_string();
1163 let t2_str = t2.to_string();
1164 let min_len = t1_str.len().min(t2_str.len());
1165
1166 const SEPARATOR: &str = "::";
1167 let separator_len = SEPARATOR.len();
dfeec247
XL
1168 let split_idx: usize = t1_str
1169 .split(SEPARATOR)
1170 .zip(t2_str.split(SEPARATOR))
1171 .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
1172 .map(|(mod_str, _)| mod_str.len() + separator_len)
1173 .sum();
1174
1175 debug!(
1176 "cmp: separator_len={}, split_idx={}, min_len={}",
e74abb32
XL
1177 separator_len, split_idx, min_len
1178 );
1179
1180 if split_idx >= min_len {
1181 // paths are identical, highlight everything
1182 (
1183 DiagnosticStyledString::highlighted(t1_str),
dfeec247 1184 DiagnosticStyledString::highlighted(t2_str),
e74abb32
XL
1185 )
1186 } else {
1187 let (common, uniq1) = t1_str.split_at(split_idx);
1188 let (_, uniq2) = t2_str.split_at(split_idx);
1189 debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
1190
1191 values.0.push_normal(common);
1192 values.0.push_highlighted(uniq1);
1193 values.1.push_normal(common);
1194 values.1.push_highlighted(uniq2);
1195
1196 values
1197 }
cc61c64b
XL
1198 }
1199 }
ff7c6d11 1200
0531ce1d 1201 // When finding T != &T, highlight only the borrow
b7449926 1202 (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => {
ff7c6d11 1203 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
94b46f34 1204 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
8faf50e0 1205 values.1.push_normal(t2.to_string());
ff7c6d11
XL
1206 values
1207 }
b7449926 1208 (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => {
ff7c6d11 1209 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
8faf50e0 1210 values.0.push_normal(t1.to_string());
94b46f34 1211 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
ff7c6d11
XL
1212 values
1213 }
1214
1215 // When encountering &T != &mut T, highlight only the borrow
0bf4aa26
XL
1216 (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2))
1217 if equals(&ref_ty1, &ref_ty2) =>
1218 {
ff7c6d11 1219 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
94b46f34
XL
1220 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1221 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
ff7c6d11
XL
1222 values
1223 }
1224
60c5eb7d
XL
1225 // When encountering tuples of the same size, highlight only the differing types
1226 (&ty::Tuple(substs1), &ty::Tuple(substs2)) if substs1.len() == substs2.len() => {
dfeec247
XL
1227 let mut values =
1228 (DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("("));
60c5eb7d
XL
1229 let len = substs1.len();
1230 for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() {
1231 let (x1, x2) = self.cmp(left, right);
1232 (values.0).0.extend(x1.0);
1233 (values.1).0.extend(x2.0);
1234 self.push_comma(&mut values.0, &mut values.1, len, i);
1235 }
dfeec247
XL
1236 if len == 1 {
1237 // Keep the output for single element tuples as `(ty,)`.
60c5eb7d
XL
1238 values.0.push_normal(",");
1239 values.1.push_normal(",");
1240 }
1241 values.0.push_normal(")");
1242 values.1.push_normal(")");
1243 values
1244 }
1245
1246 (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
1247 let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
1248 let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
1249 let mut values = self.cmp_fn_sig(&sig1, &sig2);
1250 let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
1251 let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
1252 let same_path = path1 == path2;
1253 values.0.push(path1, !same_path);
1254 values.1.push(path2, !same_path);
1255 values
1256 }
1257
1258 (ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
1259 let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
1260 let mut values = self.cmp_fn_sig(&sig1, sig2);
1261 values.0.push_normal(format!(
1262 " {{{}}}",
dfeec247
XL
1263 self.tcx.def_path_str_with_substs(*did1, substs1)
1264 ));
60c5eb7d
XL
1265 values
1266 }
1267
1268 (ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
1269 let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
1270 let mut values = self.cmp_fn_sig(sig1, &sig2);
1271 values.1.push_normal(format!(
1272 " {{{}}}",
dfeec247
XL
1273 self.tcx.def_path_str_with_substs(*did2, substs2)
1274 ));
60c5eb7d
XL
1275 values
1276 }
1277
dfeec247 1278 (ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2),
60c5eb7d 1279
cc61c64b
XL
1280 _ => {
1281 if t1 == t2 {
1282 // The two types are the same, elide and don't highlight.
dfeec247 1283 (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
cc61c64b
XL
1284 } else {
1285 // We couldn't find anything in common, highlight everything.
0531ce1d 1286 (
8faf50e0
XL
1287 DiagnosticStyledString::highlighted(t1.to_string()),
1288 DiagnosticStyledString::highlighted(t2.to_string()),
0531ce1d 1289 )
cc61c64b
XL
1290 }
1291 }
1292 }
1293 }
1294
0531ce1d
XL
1295 pub fn note_type_err(
1296 &self,
1297 diag: &mut DiagnosticBuilder<'tcx>,
1298 cause: &ObligationCause<'tcx>,
1299 secondary_span: Option<(Span, String)>,
1300 mut values: Option<ValuePairs<'tcx>>,
1301 terr: &TypeError<'tcx>,
1302 ) {
dfeec247 1303 let span = cause.span(self.tcx);
f9f354fc 1304 debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
dfeec247 1305
ff7c6d11
XL
1306 // For some types of errors, expected-found does not make
1307 // sense, so just ignore the values we were given.
ba9703b0
XL
1308 if let TypeError::CyclicTy(_) = terr {
1309 values = None;
ff7c6d11 1310 }
dfeec247
XL
1311 struct OpaqueTypesVisitor<'tcx> {
1312 types: FxHashMap<TyCategory, FxHashSet<Span>>,
1313 expected: FxHashMap<TyCategory, FxHashSet<Span>>,
1314 found: FxHashMap<TyCategory, FxHashSet<Span>>,
1315 ignore_span: Span,
1316 tcx: TyCtxt<'tcx>,
1317 }
1318
1319 impl<'tcx> OpaqueTypesVisitor<'tcx> {
1320 fn visit_expected_found(
1321 tcx: TyCtxt<'tcx>,
1322 expected: Ty<'tcx>,
1323 found: Ty<'tcx>,
1324 ignore_span: Span,
1325 ) -> Self {
1326 let mut types_visitor = OpaqueTypesVisitor {
1327 types: Default::default(),
1328 expected: Default::default(),
1329 found: Default::default(),
1330 ignore_span,
1331 tcx,
1332 };
1333 // The visitor puts all the relevant encountered types in `self.types`, but in
1334 // here we want to visit two separate types with no relation to each other, so we
1335 // move the results from `types` to `expected` or `found` as appropriate.
1336 expected.visit_with(&mut types_visitor);
1337 std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
1338 found.visit_with(&mut types_visitor);
1339 std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
1340 types_visitor
1341 }
1342
1343 fn report(&self, err: &mut DiagnosticBuilder<'_>) {
1344 self.add_labels_for_types(err, "expected", &self.expected);
1345 self.add_labels_for_types(err, "found", &self.found);
1346 }
1347
1348 fn add_labels_for_types(
1349 &self,
1350 err: &mut DiagnosticBuilder<'_>,
1351 target: &str,
1352 types: &FxHashMap<TyCategory, FxHashSet<Span>>,
1353 ) {
1354 for (key, values) in types.iter() {
1355 let count = values.len();
1356 let kind = key.descr();
1357 for sp in values {
1358 err.span_label(
1359 *sp,
1360 format!(
1361 "{}{}{} {}{}",
1362 if sp.is_desugaring(DesugaringKind::Async) {
1363 "the `Output` of this `async fn`'s "
1364 } else if count == 1 {
1365 "the "
1366 } else {
1367 ""
1368 },
1369 if count > 1 { "one of the " } else { "" },
1370 target,
1371 kind,
1372 pluralize!(count),
1373 ),
1374 );
1375 }
1376 }
1377 }
1378 }
1379
1380 impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
1381 fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
1382 if let Some((kind, def_id)) = TyCategory::from_ty(t) {
1383 let span = self.tcx.def_span(def_id);
1384 // Avoid cluttering the output when the "found" and error span overlap:
1385 //
1386 // error[E0308]: mismatched types
1387 // --> $DIR/issue-20862.rs:2:5
1388 // |
1389 // LL | |y| x + y
1390 // | ^^^^^^^^^
1391 // | |
1392 // | the found closure
1393 // | expected `()`, found closure
1394 // |
1395 // = note: expected unit type `()`
1396 // found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
1397 if !self.ignore_span.overlaps(span) {
1398 self.types.entry(kind).or_default().insert(span);
1399 }
1400 }
1401 t.super_visit_with(self)
1402 }
1403 }
1404
e74abb32 1405 debug!("note_type_err(diag={:?})", diag);
abe05a73
XL
1406 let (expected_found, exp_found, is_simple_error) = match values {
1407 None => (None, None, false),
8bb4bdeb 1408 Some(values) => {
abe05a73 1409 let (is_simple_error, exp_found) = match values {
8bb4bdeb 1410 ValuePairs::Types(exp_found) => {
dfeec247
XL
1411 let is_simple_err =
1412 exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
1413 OpaqueTypesVisitor::visit_expected_found(
1414 self.tcx,
1415 exp_found.expected,
1416 exp_found.found,
1417 span,
1418 )
1419 .report(diag);
abe05a73
XL
1420
1421 (is_simple_err, Some(exp_found))
8bb4bdeb 1422 }
abe05a73 1423 _ => (false, None),
8bb4bdeb
XL
1424 };
1425 let vals = match self.values_str(&values) {
1426 Some((expected, found)) => Some((expected, found)),
1427 None => {
1428 // Derived error. Cancel the emitter.
e1599b0c 1429 diag.cancel();
0531ce1d 1430 return;
8bb4bdeb
XL
1431 }
1432 };
abe05a73 1433 (vals, exp_found, is_simple_error)
5bcae85e
SL
1434 }
1435 };
1436
e74abb32
XL
1437 // Ignore msg for object safe coercion
1438 // since E0038 message will be printed
1439 match terr {
1440 TypeError::ObjectUnsafeCoercion(_) => {}
1441 _ => {
1442 diag.span_label(span, terr.to_string());
1443 if let Some((sp, msg)) = secondary_span {
1444 diag.span_label(sp, msg);
1445 }
1446 }
1447 };
5bcae85e 1448 if let Some((expected, found)) = expected_found {
60c5eb7d
XL
1449 let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string());
1450 let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string());
1451 match (&terr, expected == found) {
1452 (TypeError::Sorts(values), extra) => {
1453 let sort_string = |ty: Ty<'tcx>| match (extra, &ty.kind) {
1454 (true, ty::Opaque(def_id, _)) => format!(
1455 " (opaque type at {})",
dfeec247
XL
1456 self.tcx
1457 .sess
1458 .source_map()
60c5eb7d
XL
1459 .mk_substr_filename(self.tcx.def_span(*def_id)),
1460 ),
1461 (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
1462 (false, _) => "".to_string(),
1463 };
dfeec247
XL
1464 if !(values.expected.is_simple_text() && values.found.is_simple_text())
1465 || (exp_found.map_or(false, |ef| {
60c5eb7d
XL
1466 // This happens when the type error is a subset of the expectation,
1467 // like when you have two references but one is `usize` and the other
1468 // is `f32`. In those cases we still want to show the `note`. If the
1469 // value from `ef` is `Infer(_)`, then we ignore it.
1470 if !ef.expected.is_ty_infer() {
1471 ef.expected != values.expected
1472 } else if !ef.found.is_ty_infer() {
1473 ef.found != values.found
1474 } else {
1475 false
1476 }
dfeec247
XL
1477 }))
1478 {
60c5eb7d
XL
1479 diag.note_expected_found_extra(
1480 &expected_label,
1481 expected,
1482 &found_label,
1483 found,
1484 &sort_string(values.expected),
1485 &sort_string(values.found),
1486 );
1487 }
8bb4bdeb 1488 }
60c5eb7d 1489 (TypeError::ObjectUnsafeCoercion(_), _) => {
e74abb32
XL
1490 diag.note_unsuccessfull_coercion(found, expected);
1491 }
60c5eb7d 1492 (_, _) => {
e74abb32
XL
1493 debug!(
1494 "note_type_err: exp_found={:?}, expected={:?} found={:?}",
1495 exp_found, expected, found
1496 );
60c5eb7d
XL
1497 if !is_simple_error || terr.must_include_note() {
1498 diag.note_expected_found(&expected_label, expected, &found_label, found);
abe05a73 1499 }
9e0c209e 1500 }
5bcae85e
SL
1501 }
1502 }
60c5eb7d
XL
1503 if let Some(exp_found) = exp_found {
1504 self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
1505 }
5bcae85e 1506
60c5eb7d
XL
1507 // In some (most?) cases cause.body_id points to actual body, but in some cases
1508 // it's a actual definition. According to the comments (e.g. in
1509 // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
1510 // is relied upon by some other code. This might (or might not) need cleanup.
dfeec247
XL
1511 let body_owner_def_id =
1512 self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
60c5eb7d
XL
1513 self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
1514 });
1515 self.check_and_note_conflicting_crates(diag, terr);
f9f354fc 1516 self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
abe05a73
XL
1517
1518 // It reads better to have the error origin as the final
1519 // thing.
f9f354fc 1520 self.note_error_origin(diag, cause, exp_found);
5bcae85e
SL
1521 }
1522
0731742a 1523 /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
60c5eb7d 1524 /// suggests it.
0731742a
XL
1525 fn suggest_as_ref_where_appropriate(
1526 &self,
1527 span: Span,
1528 exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1529 diag: &mut DiagnosticBuilder<'tcx>,
1530 ) {
ba9703b0
XL
1531 if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
1532 (&exp_found.expected.kind, &exp_found.found.kind)
1533 {
1534 if let ty::Adt(found_def, found_substs) = found_ty.kind {
1535 let path_str = format!("{:?}", exp_def);
1536 if exp_def == &found_def {
1537 let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
0731742a 1538 `.as_ref()`";
ba9703b0 1539 let result_msg = "you can convert from `&Result<T, E>` to \
0731742a 1540 `Result<&T, &E>` using `.as_ref()`";
ba9703b0
XL
1541 let have_as_ref = &[
1542 ("std::option::Option", opt_msg),
1543 ("core::option::Option", opt_msg),
1544 ("std::result::Result", result_msg),
1545 ("core::result::Result", result_msg),
1546 ];
1547 if let Some(msg) = have_as_ref
1548 .iter()
f9f354fc 1549 .find_map(|(path, msg)| (&path_str == path).then_some(msg))
ba9703b0
XL
1550 {
1551 let mut show_suggestion = true;
1552 for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) {
1553 match exp_ty.kind {
1554 ty::Ref(_, exp_ty, _) => {
1555 match (&exp_ty.kind, &found_ty.kind) {
1556 (_, ty::Param(_))
1557 | (_, ty::Infer(_))
1558 | (ty::Param(_), _)
1559 | (ty::Infer(_), _) => {}
1560 _ if ty::TyS::same_type(exp_ty, found_ty) => {}
1561 _ => show_suggestion = false,
1562 };
0731742a 1563 }
ba9703b0
XL
1564 ty::Param(_) | ty::Infer(_) => {}
1565 _ => show_suggestion = false,
0731742a
XL
1566 }
1567 }
ba9703b0
XL
1568 if let (Ok(snippet), true) =
1569 (self.tcx.sess.source_map().span_to_snippet(span), show_suggestion)
1570 {
1571 diag.span_suggestion(
1572 span,
1573 msg,
1574 format!("{}.as_ref()", snippet),
1575 Applicability::MachineApplicable,
1576 );
1577 }
0731742a
XL
1578 }
1579 }
1580 }
0731742a
XL
1581 }
1582 }
1583
0531ce1d
XL
1584 pub fn report_and_explain_type_error(
1585 &self,
1586 trace: TypeTrace<'tcx>,
1587 terr: &TypeError<'tcx>,
1588 ) -> DiagnosticBuilder<'tcx> {
dfeec247 1589 debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
abe05a73 1590
48663c56 1591 let span = trace.cause.span(self.tcx);
ff7c6d11
XL
1592 let failure_code = trace.cause.as_failure_code(terr);
1593 let mut diag = match failure_code {
e74abb32 1594 FailureCode::Error0038(did) => {
74b04a01 1595 let violations = self.tcx.object_safety_violations(did);
dfeec247 1596 report_object_safety_error(self.tcx, span, did, violations)
e74abb32 1597 }
ff7c6d11 1598 FailureCode::Error0317(failure_str) => {
c30ab7b3 1599 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
32a655c1 1600 }
ff7c6d11 1601 FailureCode::Error0580(failure_str) => {
32a655c1
SL
1602 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
1603 }
ff7c6d11 1604 FailureCode::Error0308(failure_str) => {
c30ab7b3 1605 struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
32a655c1 1606 }
ff7c6d11
XL
1607 FailureCode::Error0644(failure_str) => {
1608 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
1609 }
c30ab7b3 1610 };
476ff2be 1611 self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
5bcae85e 1612 diag
1a4d82fc
JJ
1613 }
1614
0531ce1d
XL
1615 fn values_str(
1616 &self,
1617 values: &ValuePairs<'tcx>,
1618 ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
1a4d82fc 1619 match *values {
cc61c64b 1620 infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
0531ce1d 1621 infer::Regions(ref exp_found) => self.expected_found_str(exp_found),
48663c56 1622 infer::Consts(ref exp_found) => self.expected_found_str(exp_found),
60c5eb7d
XL
1623 infer::TraitRefs(ref exp_found) => {
1624 let pretty_exp_found = ty::error::ExpectedFound {
1625 expected: exp_found.expected.print_only_trait_path(),
dfeec247 1626 found: exp_found.found.print_only_trait_path(),
60c5eb7d
XL
1627 };
1628 self.expected_found_str(&pretty_exp_found)
dfeec247 1629 }
60c5eb7d
XL
1630 infer::PolyTraitRefs(ref exp_found) => {
1631 let pretty_exp_found = ty::error::ExpectedFound {
1632 expected: exp_found.expected.print_only_trait_path(),
dfeec247 1633 found: exp_found.found.print_only_trait_path(),
60c5eb7d
XL
1634 };
1635 self.expected_found_str(&pretty_exp_found)
dfeec247 1636 }
1a4d82fc
JJ
1637 }
1638 }
1639
0531ce1d
XL
1640 fn expected_found_str_ty(
1641 &self,
1642 exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1643 ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
dc9dc135 1644 let exp_found = self.resolve_vars_if_possible(exp_found);
cc61c64b
XL
1645 if exp_found.references_error() {
1646 return None;
1647 }
1648
1649 Some(self.cmp(exp_found.expected, exp_found.found))
1650 }
1651
1652 /// Returns a string of the form "expected `{}`, found `{}`".
5bcae85e 1653 fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
1a4d82fc 1654 &self,
0531ce1d
XL
1655 exp_found: &ty::error::ExpectedFound<T>,
1656 ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
dc9dc135 1657 let exp_found = self.resolve_vars_if_possible(exp_found);
5bcae85e 1658 if exp_found.references_error() {
1a4d82fc
JJ
1659 return None;
1660 }
1661
0531ce1d 1662 Some((
8faf50e0
XL
1663 DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
1664 DiagnosticStyledString::highlighted(exp_found.found.to_string()),
0531ce1d 1665 ))
1a4d82fc
JJ
1666 }
1667
0531ce1d
XL
1668 pub fn report_generic_bound_failure(
1669 &self,
0531ce1d
XL
1670 span: Span,
1671 origin: Option<SubregionOrigin<'tcx>>,
1672 bound_kind: GenericKind<'tcx>,
1673 sub: Region<'tcx>,
1674 ) {
f9f354fc 1675 self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
8faf50e0
XL
1676 }
1677
1678 pub fn construct_generic_bound_failure(
1679 &self,
8faf50e0
XL
1680 span: Span,
1681 origin: Option<SubregionOrigin<'tcx>>,
1682 bound_kind: GenericKind<'tcx>,
1683 sub: Region<'tcx>,
0bf4aa26 1684 ) -> DiagnosticBuilder<'a> {
f9f354fc 1685 let hir = &self.tcx.hir();
ea8adc8c
XL
1686 // Attempt to obtain the span of the parameter so we can
1687 // suggest adding an explicit lifetime bound to it.
f9f354fc
XL
1688 let generics =
1689 self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
1690 let hir_id = hir.as_local_hir_id(table_owner);
1691 let parent_id = hir.get_parent_item(hir_id);
1692 (
1693 // Parent item could be a `mod`, so we check the HIR before calling:
1694 if let Some(Node::Item(Item {
1695 kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
1696 ..
1697 })) = hir.find(parent_id)
1698 {
1699 Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id()))
ea8adc8c
XL
1700 } else {
1701 None
f9f354fc
XL
1702 },
1703 self.tcx.generics_of(table_owner.to_def_id()),
1704 )
1705 });
1706 let type_param_span = match (generics, bound_kind) {
1707 (Some((_, ref generics)), GenericKind::Param(ref param)) => {
1708 // Account for the case where `param` corresponds to `Self`,
1709 // which doesn't have the expected type argument.
1710 if !(generics.has_self && param.index == 0) {
1711 let type_param = generics.type_param(param, self.tcx);
1712 type_param.def_id.as_local().map(|def_id| {
1713 // Get the `hir::Param` to verify whether it already has any bounds.
1714 // We do this to avoid suggesting code that ends up as `T: 'a'b`,
1715 // instead we suggest `T: 'a + 'b` in that case.
1716 let id = hir.as_local_hir_id(def_id);
1717 let mut has_bounds = false;
1718 if let Node::GenericParam(param) = hir.get(id) {
1719 has_bounds = !param.bounds.is_empty();
1720 }
1721 let sp = hir.span(id);
1722 // `sp` only covers `T`, change it so that it covers
1723 // `T:` when appropriate
1724 let is_impl_trait = bound_kind.to_string().starts_with("impl ");
1725 let sp = if has_bounds && !is_impl_trait {
1726 sp.to(self
1727 .tcx
1728 .sess
1729 .source_map()
1730 .next_point(self.tcx.sess.source_map().next_point(sp)))
1731 } else {
1732 sp
1733 };
1734 (sp, has_bounds, is_impl_trait)
1735 })
1736 } else {
1737 None
1738 }
ea8adc8c
XL
1739 }
1740 _ => None,
1741 };
f9f354fc
XL
1742 let new_lt = generics
1743 .as_ref()
1744 .and_then(|(parent_g, g)| {
1745 let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect();
1746 let mut lts_names = g
1747 .params
1748 .iter()
1749 .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
1750 .map(|p| p.name.as_str())
1751 .collect::<Vec<_>>();
1752 if let Some(g) = parent_g {
1753 lts_names.extend(
1754 g.params
1755 .iter()
1756 .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
1757 .map(|p| p.name.as_str()),
1758 );
1759 }
1760 let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
1761 possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str()))
1762 })
1763 .unwrap_or("'lt".to_string());
1764 let add_lt_sugg = generics
1765 .as_ref()
1766 .and_then(|(_, g)| g.params.first())
1767 .and_then(|param| param.def_id.as_local())
1768 .map(|def_id| {
1769 (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))
1770 });
1a4d82fc
JJ
1771
1772 let labeled_user_string = match bound_kind {
0531ce1d
XL
1773 GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
1774 GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
1a4d82fc
JJ
1775 };
1776
ff7c6d11 1777 if let Some(SubregionOrigin::CompareImplMethodObligation {
0531ce1d
XL
1778 span,
1779 item_name,
1780 impl_item_def_id,
1781 trait_item_def_id,
1782 }) = origin
1783 {
8faf50e0 1784 return self.report_extra_impl_obligation(
0531ce1d
XL
1785 span,
1786 item_name,
1787 impl_item_def_id,
1788 trait_item_def_id,
1789 &format!("`{}: {}`", bound_kind, sub),
8faf50e0 1790 );
c30ab7b3
SL
1791 }
1792
0531ce1d
XL
1793 fn binding_suggestion<'tcx, S: fmt::Display>(
1794 err: &mut DiagnosticBuilder<'tcx>,
0731742a 1795 type_param_span: Option<(Span, bool, bool)>,
0531ce1d
XL
1796 bound_kind: GenericKind<'tcx>,
1797 sub: S,
1798 ) {
74b04a01 1799 let msg = "consider adding an explicit lifetime bound";
0731742a
XL
1800 if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
1801 let suggestion = if is_impl_trait {
1802 format!("{} + {}", bound_kind, sub)
1803 } else {
1804 let tail = if has_lifetimes { " + " } else { "" };
1805 format!("{}: {}{}", bound_kind, sub, tail)
1806 };
74b04a01 1807 err.span_suggestion(
0bf4aa26 1808 sp,
74b04a01 1809 &format!("{}...", msg),
0bf4aa26
XL
1810 suggestion,
1811 Applicability::MaybeIncorrect, // Issue #41966
94b46f34 1812 );
ea8adc8c 1813 } else {
74b04a01
XL
1814 let consider = format!(
1815 "{} {}...",
1816 msg,
1817 if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
1818 format!(" `{}` to `{}`", sub, bound_kind)
1819 } else {
1820 format!("`{}: {}`", bound_kind, sub)
1821 },
1822 );
0731742a 1823 err.help(&consider);
ea8adc8c
XL
1824 }
1825 }
1826
f9f354fc
XL
1827 let new_binding_suggestion =
1828 |err: &mut DiagnosticBuilder<'tcx>,
1829 type_param_span: Option<(Span, bool, bool)>,
1830 bound_kind: GenericKind<'tcx>| {
1831 let msg = "consider introducing an explicit lifetime bound";
1832 if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
1833 let suggestion = if is_impl_trait {
1834 (sp.shrink_to_hi(), format!(" + {}", new_lt))
1835 } else {
1836 let tail = if has_lifetimes { " +" } else { "" };
1837 (sp, format!("{}: {}{}", bound_kind, new_lt, tail))
1838 };
1839 let mut sugg =
1840 vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))];
1841 if let Some(lt) = add_lt_sugg {
1842 sugg.push(lt);
1843 sugg.rotate_right(1);
1844 }
1845 // `MaybeIncorrect` due to issue #41966.
1846 err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
1847 }
1848 };
1849
9e0c209e 1850 let mut err = match *sub {
dfeec247
XL
1851 ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
1852 | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }) => {
1a4d82fc 1853 // Does the required lifetime have a nice name we can print?
0531ce1d
XL
1854 let mut err = struct_span_err!(
1855 self.tcx.sess,
1856 span,
1857 E0309,
1858 "{} may not live long enough",
1859 labeled_user_string
1860 );
74b04a01 1861 // Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl
dfeec247
XL
1862 // for the bound is not suitable for suggestions when `-Zverbose` is set because it
1863 // uses `Debug` output, so we handle it specially here so that suggestions are
1864 // always correct.
1865 binding_suggestion(&mut err, type_param_span, bound_kind, name);
9cc50fc6 1866 err
1a4d82fc
JJ
1867 }
1868
1869 ty::ReStatic => {
1870 // Does the required lifetime have a nice name we can print?
0531ce1d
XL
1871 let mut err = struct_span_err!(
1872 self.tcx.sess,
1873 span,
1874 E0310,
1875 "{} may not live long enough",
1876 labeled_user_string
1877 );
ea8adc8c 1878 binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
9cc50fc6 1879 err
1a4d82fc
JJ
1880 }
1881
1882 _ => {
1883 // If not, be less specific.
0531ce1d
XL
1884 let mut err = struct_span_err!(
1885 self.tcx.sess,
1886 span,
1887 E0311,
1888 "{} may not live long enough",
1889 labeled_user_string
1890 );
dfeec247
XL
1891 note_and_explain_region(
1892 self.tcx,
9cc50fc6 1893 &mut err,
c34b1796 1894 &format!("{} must be valid for ", labeled_user_string),
1a4d82fc 1895 sub,
0531ce1d
XL
1896 "...",
1897 );
f9f354fc
XL
1898 if let Some(infer::RelateParamBound(_, t)) = origin {
1899 let t = self.resolve_vars_if_possible(&t);
1900 match t.kind {
1901 // We've got:
1902 // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
1903 // suggest:
1904 // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
1905 ty::Closure(_, _substs) | ty::Opaque(_, _substs) => {
1906 new_binding_suggestion(&mut err, type_param_span, bound_kind);
1907 }
1908 _ => {
1909 binding_suggestion(&mut err, type_param_span, bound_kind, new_lt);
1910 }
1911 }
1912 }
9cc50fc6 1913 err
1a4d82fc 1914 }
9cc50fc6 1915 };
e9174d1e 1916
ff7c6d11
XL
1917 if let Some(origin) = origin {
1918 self.note_region_origin(&mut err, &origin);
1919 }
8faf50e0 1920 err
1a4d82fc
JJ
1921 }
1922
0531ce1d
XL
1923 fn report_sub_sup_conflict(
1924 &self,
0531ce1d
XL
1925 var_origin: RegionVariableOrigin,
1926 sub_origin: SubregionOrigin<'tcx>,
1927 sub_region: Region<'tcx>,
1928 sup_origin: SubregionOrigin<'tcx>,
1929 sup_region: Region<'tcx>,
1930 ) {
9cc50fc6 1931 let mut err = self.report_inference_failure(var_origin);
1a4d82fc 1932
dfeec247
XL
1933 note_and_explain_region(
1934 self.tcx,
0531ce1d 1935 &mut err,
1a4d82fc
JJ
1936 "first, the lifetime cannot outlive ",
1937 sup_region,
0531ce1d
XL
1938 "...",
1939 );
1a4d82fc 1940
f9f354fc
XL
1941 debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
1942 debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
1943 debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
1944 debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
1945 debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
1946
ba9703b0
XL
1947 if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
1948 (&sup_origin, &sub_origin)
1949 {
ba9703b0
XL
1950 debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
1951 debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
1952 debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
1953 debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
1954
1955 if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
1956 (self.values_str(&sup_trace.values), self.values_str(&sub_trace.values))
1957 {
1958 if sub_expected == sup_expected && sub_found == sup_found {
1959 note_and_explain_region(
1960 self.tcx,
ba9703b0
XL
1961 &mut err,
1962 "...but the lifetime must also be valid for ",
1963 sub_region,
1964 "...",
1965 );
1966 err.span_note(
1967 sup_trace.cause.span,
1968 &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
1969 );
dfeec247 1970
ba9703b0
XL
1971 err.note_expected_found(&"", sup_expected, &"", sup_found);
1972 err.emit();
1973 return;
2c00a5a8
XL
1974 }
1975 }
2c00a5a8
XL
1976 }
1977
9cc50fc6 1978 self.note_region_origin(&mut err, &sup_origin);
1a4d82fc 1979
dfeec247
XL
1980 note_and_explain_region(
1981 self.tcx,
0531ce1d 1982 &mut err,
1a4d82fc
JJ
1983 "but, the lifetime must be valid for ",
1984 sub_region,
0531ce1d
XL
1985 "...",
1986 );
1a4d82fc 1987
9cc50fc6
SL
1988 self.note_region_origin(&mut err, &sub_origin);
1989 err.emit();
1a4d82fc 1990 }
1a4d82fc
JJ
1991}
1992
dc9dc135 1993impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
0531ce1d
XL
1994 fn report_inference_failure(
1995 &self,
1996 var_origin: RegionVariableOrigin,
1997 ) -> DiagnosticBuilder<'tcx> {
62682a34 1998 let br_string = |br: ty::BoundRegion| {
532ac7d7
XL
1999 let mut s = match br {
2000 ty::BrNamed(_, name) => name.to_string(),
2001 _ => String::new(),
2002 };
62682a34
SL
2003 if !s.is_empty() {
2004 s.push_str(" ");
2005 }
2006 s
2007 };
1a4d82fc 2008 let var_description = match var_origin {
b7449926 2009 infer::MiscVariable(_) => String::new(),
1a4d82fc
JJ
2010 infer::PatternRegion(_) => " for pattern".to_string(),
2011 infer::AddrOfRegion(_) => " for borrow expression".to_string(),
1a4d82fc
JJ
2012 infer::Autoref(_) => " for autoref".to_string(),
2013 infer::Coercion(_) => " for automatic coercion".to_string(),
2014 infer::LateBoundRegion(_, br, infer::FnCall) => {
0531ce1d 2015 format!(" for lifetime parameter {}in function call", br_string(br))
1a4d82fc
JJ
2016 }
2017 infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
62682a34 2018 format!(" for lifetime parameter {}in generic type", br_string(br))
1a4d82fc 2019 }
0531ce1d
XL
2020 infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
2021 " for lifetime parameter {}in trait containing associated type `{}`",
2022 br_string(br),
8faf50e0 2023 self.tcx.associated_item(def_id).ident
0531ce1d
XL
2024 ),
2025 infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{}`", name),
1a4d82fc 2026 infer::BoundRegionInCoherence(name) => {
0531ce1d 2027 format!(" for lifetime parameter `{}` in coherence check", name)
1a4d82fc
JJ
2028 }
2029 infer::UpvarRegion(ref upvar_id, _) => {
dc9dc135 2030 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
ea8adc8c 2031 format!(" for capture of `{}` by closure", var_name)
1a4d82fc 2032 }
abe05a73 2033 infer::NLL(..) => bug!("NLL variable found in lexical phase"),
1a4d82fc
JJ
2034 };
2035
0531ce1d
XL
2036 struct_span_err!(
2037 self.tcx.sess,
2038 var_origin.span(),
2039 E0495,
2040 "cannot infer an appropriate lifetime{} \
2041 due to conflicting requirements",
2042 var_description
2043 )
1a4d82fc 2044 }
1a4d82fc
JJ
2045}
2046
ff7c6d11 2047enum FailureCode {
e74abb32 2048 Error0038(DefId),
ff7c6d11
XL
2049 Error0317(&'static str),
2050 Error0580(&'static str),
2051 Error0308(&'static str),
2052 Error0644(&'static str),
2053}
2054
74b04a01
XL
2055trait ObligationCauseExt<'tcx> {
2056 fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode;
2057 fn as_requirement_str(&self) -> &'static str;
2058}
2059
2060impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
ff7c6d11
XL
2061 fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
2062 use self::FailureCode::*;
9fa01778 2063 use crate::traits::ObligationCauseCode::*;
476ff2be 2064 match self.code {
ff7c6d11 2065 CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
dfeec247
XL
2066 CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
2067 MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
e1599b0c 2068 Error0308(match source {
dfeec247
XL
2069 hir::MatchSource::IfLetDesugar { .. } => {
2070 "`if let` arms have incompatible types"
2071 }
e1599b0c
XL
2072 hir::MatchSource::TryDesugar => {
2073 "try expression alternatives have incompatible types"
2074 }
dfeec247
XL
2075 _ => "`match` arms have incompatible types",
2076 })
2077 }
2078 IfExpression { .. } => Error0308("`if` and `else` have incompatible types"),
2079 IfExpressionWithNoElse => Error0317("`if` may be missing an `else` clause"),
2080 MainFunctionType => Error0580("`main` function has wrong type"),
2081 StartFunctionType => Error0308("`#[start]` function has wrong type"),
ff7c6d11 2082 IntrinsicType => Error0308("intrinsic has wrong type"),
e1599b0c 2083 MethodReceiver => Error0308("mismatched `self` parameter type"),
ff7c6d11
XL
2084
2085 // In the case where we have no more specific thing to
2086 // say, also take a look at the error code, maybe we can
2087 // tailor to that.
2088 _ => match terr {
0531ce1d
XL
2089 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
2090 Error0644("closure/generator type that references itself")
2091 }
e1599b0c
XL
2092 TypeError::IntrinsicCast => {
2093 Error0308("cannot coerce intrinsics to function pointers")
2094 }
dfeec247 2095 TypeError::ObjectUnsafeCoercion(did) => Error0038(*did),
0531ce1d
XL
2096 _ => Error0308("mismatched types"),
2097 },
476ff2be
SL
2098 }
2099 }
2100
2101 fn as_requirement_str(&self) -> &'static str {
9fa01778 2102 use crate::traits::ObligationCauseCode::*;
476ff2be
SL
2103 match self.code {
2104 CompareImplMethodObligation { .. } => "method type is compatible with trait",
dfeec247 2105 CompareImplTypeObligation { .. } => "associated type is compatible with trait",
476ff2be 2106 ExprAssignable => "expression is assignable",
e1599b0c 2107 MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
0531ce1d 2108 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
dfeec247 2109 _ => "`match` arms have compatible types",
476ff2be 2110 },
dfeec247
XL
2111 IfExpression { .. } => "`if` and `else` have incompatible types",
2112 IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
476ff2be 2113 MainFunctionType => "`main` function has the correct type",
dfeec247 2114 StartFunctionType => "`#[start]` function has the correct type",
476ff2be
SL
2115 IntrinsicType => "intrinsic has the correct type",
2116 MethodReceiver => "method receiver has the correct type",
2117 _ => "types are compatible",
2118 }
2119 }
2120}
dfeec247
XL
2121
2122/// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
2123/// extra information about each type, but we only care about the category.
2124#[derive(Clone, Copy, PartialEq, Eq, Hash)]
ba9703b0 2125pub enum TyCategory {
dfeec247
XL
2126 Closure,
2127 Opaque,
2128 Generator,
2129 Foreign,
2130}
2131
2132impl TyCategory {
2133 fn descr(&self) -> &'static str {
2134 match self {
2135 Self::Closure => "closure",
2136 Self::Opaque => "opaque type",
2137 Self::Generator => "generator",
2138 Self::Foreign => "foreign type",
2139 }
2140 }
2141
2142 pub fn from_ty(ty: Ty<'_>) -> Option<(Self, DefId)> {
2143 match ty.kind {
2144 ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
2145 ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
2146 ty::Generator(def_id, ..) => Some((Self::Generator, def_id)),
2147 ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
2148 _ => None,
2149 }
2150 }
2151}