1 use errors::DiagnosticBuilder;
2 use crate::hir::def_id::DefId;
3 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
4 use crate::infer::lexical_region_resolve::RegionResolutionError;
5 use crate::infer::ValuePairs;
6 use crate::infer::{SubregionOrigin, TypeTrace};
7 use crate::traits::{ObligationCause, ObligationCauseCode};
9 use crate::ty::error::ExpectedFound;
10 use crate::ty::subst::Substs;
11 use crate::util::common::ErrorReported;
12 use crate::util::ppaux::RegionHighlightMode;
14 impl NiceRegionError<'me, 'gcx, 'tcx> {
15 /// When given a `ConcreteFailure` for a function with arguments containing a named region and
16 /// an anonymous region, emit a descriptive diagnostic error.
17 pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> {
19 ///////////////////////////////////////////////////////////////////////////
20 // NB. The ordering of cases in this match is very
21 // sensitive, because we are often matching against
22 // specific cases and then using an `_` to match all
25 ///////////////////////////////////////////////////////////////////////////
26 // Check for errors from comparing trait failures -- first
27 // with two placeholders, then with one.
28 Some(RegionResolutionError::SubSupConflict(
31 SubregionOrigin::Subtype(TypeTrace {
33 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
35 sub_placeholder @ ty::RePlaceholder(_),
37 sup_placeholder @ ty::RePlaceholder(_),
38 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
39 Some(self.tcx().mk_region(ty::ReVar(*vid))),
41 Some(sub_placeholder),
42 Some(sup_placeholder),
48 Some(RegionResolutionError::SubSupConflict(
51 SubregionOrigin::Subtype(TypeTrace {
53 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
55 sub_placeholder @ ty::RePlaceholder(_),
58 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
59 Some(self.tcx().mk_region(ty::ReVar(*vid))),
61 Some(sub_placeholder),
68 Some(RegionResolutionError::SubSupConflict(
71 SubregionOrigin::Subtype(TypeTrace {
73 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
77 sup_placeholder @ ty::RePlaceholder(_),
78 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
79 Some(self.tcx().mk_region(ty::ReVar(*vid))),
82 Some(*sup_placeholder),
88 Some(RegionResolutionError::SubSupConflict(
93 SubregionOrigin::Subtype(TypeTrace {
95 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
97 sup_placeholder @ ty::RePlaceholder(_),
98 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
99 Some(self.tcx().mk_region(ty::ReVar(*vid))),
102 Some(*sup_placeholder),
108 Some(RegionResolutionError::ConcreteFailure(
109 SubregionOrigin::Subtype(TypeTrace {
111 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
113 sub_region @ ty::RePlaceholder(_),
114 sup_region @ ty::RePlaceholder(_),
115 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
125 Some(RegionResolutionError::ConcreteFailure(
126 SubregionOrigin::Subtype(TypeTrace {
128 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
130 sub_region @ ty::RePlaceholder(_),
132 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
142 Some(RegionResolutionError::ConcreteFailure(
143 SubregionOrigin::Subtype(TypeTrace {
145 values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
148 sup_region @ ty::RePlaceholder(_),
149 )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
163 // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
164 // --> /home/nmatsakis/tmp/foo.rs:12:5
166 // 12 | all::<&'static u32>();
167 // | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
169 // = note: Due to a where-clause on the function `all`,
170 // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
171 // = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
172 fn try_report_placeholders_trait(
174 vid: Option<ty::Region<'tcx>>,
175 cause: &ObligationCause<'tcx>,
176 sub_placeholder: Option<ty::Region<'tcx>>,
177 sup_placeholder: Option<ty::Region<'tcx>>,
179 expected_substs: &'tcx Substs<'tcx>,
180 actual_substs: &'tcx Substs<'tcx>,
183 "try_report_placeholders_trait(\
185 sub_placeholder={:?}, \
186 sup_placeholder={:?}, \
188 expected_substs={:?}, \
189 actual_substs={:?})",
190 vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
193 let mut err = self.tcx().sess.struct_span_err(
194 cause.span(&self.tcx()),
196 "implementation of `{}` is not general enough",
197 self.tcx().item_path_str(trait_def_id),
202 ObligationCauseCode::ItemObligation(def_id) => {
204 "Due to a where-clause on `{}`,",
205 self.tcx().item_path_str(def_id),
211 let expected_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
212 def_id: trait_def_id,
213 substs: expected_substs,
215 let actual_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
216 def_id: trait_def_id,
217 substs: actual_substs,
220 // Search the expected and actual trait references to see (a)
221 // whether the sub/sup placeholders appear in them (sometimes
222 // you have a trait ref like `T: Foo<fn(&u8)>`, where the
223 // placeholder was created as part of an inner type) and (b)
224 // whether the inference variable appears. In each case,
225 // assign a counter value in each case if so.
227 let mut has_sub = None;
228 let mut has_sup = None;
230 let mut actual_has_vid = None;
231 let mut expected_has_vid = None;
233 self.tcx().for_each_free_region(&expected_trait_ref, |r| {
234 if Some(r) == sub_placeholder && has_sub.is_none() {
235 has_sub = Some(counter);
237 } else if Some(r) == sup_placeholder && has_sup.is_none() {
238 has_sup = Some(counter);
242 if Some(r) == vid && expected_has_vid.is_none() {
243 expected_has_vid = Some(counter);
248 self.tcx().for_each_free_region(&actual_trait_ref, |r| {
249 if Some(r) == vid && actual_has_vid.is_none() {
250 actual_has_vid = Some(counter);
255 let actual_self_ty_has_vid = self
257 .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
259 let expected_self_ty_has_vid = self
261 .any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
263 let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
266 "try_report_placeholders_trait: actual_has_vid={:?}",
270 "try_report_placeholders_trait: expected_has_vid={:?}",
273 debug!("try_report_placeholders_trait: has_sub={:?}", has_sub);
274 debug!("try_report_placeholders_trait: has_sup={:?}", has_sup);
276 "try_report_placeholders_trait: actual_self_ty_has_vid={:?}",
277 actual_self_ty_has_vid
280 "try_report_placeholders_trait: expected_self_ty_has_vid={:?}",
281 expected_self_ty_has_vid
284 self.explain_actual_impl_that_was_found(
302 /// Add notes with details about the expected and actual trait refs, with attention to cases
303 /// when placeholder regions are involved: either the trait or the self type containing
304 /// them needs to be mentioned the closest to the placeholders.
305 /// This makes the error messages read better, however at the cost of some complexity
306 /// due to the number of combinations we have to deal with.
307 fn explain_actual_impl_that_was_found(
309 err: &mut DiagnosticBuilder<'_>,
310 sub_placeholder: Option<ty::Region<'tcx>>,
311 sup_placeholder: Option<ty::Region<'tcx>>,
312 has_sub: Option<usize>,
313 has_sup: Option<usize>,
314 expected_trait_ref: ty::TraitRef<'_>,
315 actual_trait_ref: ty::TraitRef<'_>,
316 vid: Option<ty::Region<'tcx>>,
317 expected_has_vid: Option<usize>,
318 actual_has_vid: Option<usize>,
319 any_self_ty_has_vid: bool,
321 // The weird thing here with the `maybe_highlighting_region` calls and the
322 // the match inside is meant to be like this:
324 // - The match checks whether the given things (placeholders, etc) appear
325 // in the types are about to print
326 // - Meanwhile, the `maybe_highlighting_region` calls set up
327 // highlights so that, if they do appear, we will replace
328 // them `'0` and whatever. (This replacement takes place
329 // inside the closure given to `maybe_highlighting_region`.)
331 // There is some duplication between the calls -- i.e., the
332 // `maybe_highlighting_region` checks if (e.g.) `has_sub` is
333 // None, an then we check again inside the closure, but this
334 // setup sort of minimized the number of calls and so form.
336 RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
337 RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
338 match (has_sub, has_sup) {
339 (Some(n1), Some(n2)) => {
340 if any_self_ty_has_vid {
342 "`{}` would have to be implemented for the type `{}`, \
343 for any two lifetimes `'{}` and `'{}`",
345 expected_trait_ref.self_ty(),
346 std::cmp::min(n1, n2),
347 std::cmp::max(n1, n2),
351 "`{}` must implement `{}`, \
352 for any two lifetimes `'{}` and `'{}`",
353 expected_trait_ref.self_ty(),
355 std::cmp::min(n1, n2),
356 std::cmp::max(n1, n2),
360 (Some(n), _) | (_, Some(n)) => {
361 if any_self_ty_has_vid {
363 "`{}` would have to be implemented for the type `{}`, \
364 for any lifetime `'{}`",
366 expected_trait_ref.self_ty(),
371 "`{}` must implement `{}`, for any lifetime `'{}`",
372 expected_trait_ref.self_ty(),
378 (None, None) => RegionHighlightMode::maybe_highlighting_region(
382 if let Some(n) = expected_has_vid {
384 "`{}` would have to be implemented for the type `{}`, \
385 for some specific lifetime `'{}`",
387 expected_trait_ref.self_ty(),
391 if any_self_ty_has_vid {
393 "`{}` would have to be implemented for the type `{}`",
395 expected_trait_ref.self_ty(),
399 "`{}` must implement `{}`",
400 expected_trait_ref.self_ty(),
411 RegionHighlightMode::maybe_highlighting_region(
414 || match actual_has_vid {
416 if any_self_ty_has_vid {
418 "but `{}` is actually implemented for the type `{}`, \
419 for some specific lifetime `'{}`",
421 actual_trait_ref.self_ty(),
426 "but `{}` actually implements `{}`, for some specific lifetime `'{}`",
427 actual_trait_ref.self_ty(),
436 "but `{}` is actually implemented for the type `{}`",
438 actual_trait_ref.self_ty(),