diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index aa968a1e40f3e..23150fab72f44 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -49,7 +49,7 @@ impl<'tcx> UniverseInfo<'tcx> { UniverseInfo::RelateTys { expected, found } } - pub(crate) fn report_error( + pub(crate) fn report_erroneous_element( &self, mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion, @@ -68,7 +68,7 @@ impl<'tcx> UniverseInfo<'tcx> { mbcx.buffer_error(err); } UniverseInfo::TypeOp(ref type_op_info) => { - type_op_info.report_error(mbcx, placeholder, error_element, cause); + type_op_info.report_erroneous_element(mbcx, placeholder, error_element, cause); } UniverseInfo::Other => { // FIXME: This error message isn't great, but it doesn't show @@ -145,8 +145,11 @@ pub(crate) trait TypeOpInfo<'tcx> { error_region: Option>, ) -> Option>; + /// Constraints require that `error_element` appear in the + /// values of `placeholder`, but this cannot be proven to + /// hold. Report an error. #[instrument(level = "debug", skip(self, mbcx))] - fn report_error( + fn report_erroneous_element( &self, mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion, @@ -190,12 +193,7 @@ pub(crate) trait TypeOpInfo<'tcx> { let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region); debug!(?nice_error); - - if let Some(nice_error) = nice_error { - mbcx.buffer_error(nice_error); - } else { - mbcx.buffer_error(self.fallback_error(tcx, span)); - } + mbcx.buffer_error(nice_error.unwrap_or_else(|| self.fallback_error(tcx, span))); } } @@ -450,7 +448,8 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( ty::ReVar(vid) => universe_of_region(vid), _ => ty::UniverseIndex::ROOT, }; - let matches = + // Are the two regions the same? + let regions_the_same = |a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) { (RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound, _ => a_region == b_region, @@ -459,7 +458,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint { Constraint::RegSubReg(sub, sup) if ((exact && sup == placeholder_region) - || (!exact && matches(sup, placeholder_region))) + || (!exact && regions_the_same(sup, placeholder_region))) && sup != sub => { Some((sub, cause.clone())) @@ -468,23 +467,21 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( if (exact && sup == placeholder_region && !universe_of_region(vid).can_name(placeholder_universe)) - || (!exact && matches(sup, placeholder_region)) => + || (!exact && regions_the_same(sup, placeholder_region)) => { Some((ty::Region::new_var(infcx.tcx, vid), cause.clone())) } _ => None, }; - let mut info = region_constraints - .constraints - .iter() - .find_map(|(constraint, cause)| check(constraint, cause, true)); - if info.is_none() { - info = region_constraints + + let mut find_culprit = |exact_match: bool| { + region_constraints .constraints .iter() - .find_map(|(constraint, cause)| check(constraint, cause, false)); - } - let (sub_region, cause) = info?; + .find_map(|(constraint, cause)| check(constraint, cause, exact_match)) + }; + + let (sub_region, cause) = find_culprit(true).or_else(|| find_culprit(false))?; debug!(?sub_region, "cause = {:#?}", cause); let error = match (error_region, *sub_region) { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 6b11f1a3681ff..b2056ccc8c60b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -404,7 +404,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let universe = placeholder.universe; let universe_info = self.regioncx.universe_info(universe); - universe_info.report_error(self, placeholder, error_element, cause); + universe_info.report_erroneous_element(self, placeholder, error_element, cause); } RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index a80d74d9e370a..eebce11da58f7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1623,30 +1623,23 @@ impl<'tcx> RegionInferenceContext<'tcx> { let longer_fr_scc = self.constraint_sccs.scc(longer_fr); debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,); - for error_element in self.scc_values.elements_contained_in(longer_fr_scc) { - match error_element { - RegionElement::Location(_) | RegionElement::RootUniversalRegion(_) => {} - // If we have some bound universal region `'a`, then the only - // elements it can contain is itself -- we don't know anything - // else about it! - RegionElement::PlaceholderRegion(placeholder1) => { - if placeholder == placeholder1 { - continue; - } - } - } - + // If we have some bound universal region `'a`, then the only + // elements it can contain is itself -- we don't know anything + // else about it! + if let Some(error_element) = self + .scc_values + .elements_contained_in(longer_fr_scc) + .find(|e| *e != RegionElement::PlaceholderRegion(placeholder)) + { + // Stop after the first error, it gets too noisy otherwise, and does not provide more information. errors_buffer.push(RegionErrorKind::BoundUniversalRegionError { longer_fr, error_element, placeholder, }); - - // Stop after the first error, it gets too noisy otherwise, and does not provide more - // information. - break; + } else { + debug!("check_bound_universal_region: all bounds satisfied"); } - debug!("check_bound_universal_region: all bounds satisfied"); } #[instrument(level = "debug", skip(self, infcx, errors_buffer))] @@ -2066,7 +2059,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { constraint.category }; - match category { + let interest = match category { // Returns usually provide a type to blame and have specially written diagnostics, // so prioritize them. ConstraintCategory::Return(_) => 0, @@ -2118,9 +2111,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { // specific, and are not used for relations that would make sense to blame. ConstraintCategory::BoringNoLocation => 6, // Do not blame internal constraints. - ConstraintCategory::Internal => 7, - ConstraintCategory::IllegalUniverse => 8, - } + ConstraintCategory::IllegalUniverse => 7, + ConstraintCategory::Internal => 8, + }; + + debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}"); + + interest }; let best_choice = if blame_source { diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index d9ac5b5cb132a..f1427218cdb02 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -21,7 +21,7 @@ rustc_index::newtype_index! { /// An individual element in a region value -- the value of a /// particular region variable consists of a set of these elements. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub(crate) enum RegionElement { /// A point in the control-flow graph. Location(Location),