Skip to content

Commit 820f06b

Browse files
committed
Auto merge of #116097 - jackh726:higher-ranked-lifetime-error-backup, r=compiler-errors
Try to use approximate placeholder regions when outputting an AscribeUserType error in borrowck Fixes #114866 Hi from GOSIM :)
2 parents 0ea7ddc + 35dd0c9 commit 820f06b

File tree

6 files changed

+80
-13
lines changed

6 files changed

+80
-13
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

+38-12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use rustc_infer::infer::RegionVariableOrigin;
1010
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
1111
use rustc_infer::traits::ObligationCause;
1212
use rustc_middle::ty::error::TypeError;
13+
use rustc_middle::ty::RePlaceholder;
14+
use rustc_middle::ty::Region;
1315
use rustc_middle::ty::RegionVid;
1416
use rustc_middle::ty::UniverseIndex;
1517
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -205,6 +207,8 @@ trait TypeOpInfo<'tcx> {
205207
let span = cause.span;
206208
let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
207209

210+
debug!(?nice_error);
211+
208212
if let Some(nice_error) = nice_error {
209213
mbcx.buffer_error(nice_error);
210214
} else {
@@ -404,19 +408,41 @@ fn try_extract_error_from_region_constraints<'tcx>(
404408
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
405409
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
406410
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
407-
let (sub_region, cause) =
408-
region_constraints.constraints.iter().find_map(|(constraint, cause)| {
409-
match *constraint {
410-
Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
411-
Some((sub, cause.clone()))
412-
}
413-
// FIXME: Should this check the universe of the var?
414-
Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
415-
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
416-
}
417-
_ => None,
411+
let matches =
412+
|a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
413+
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
414+
_ => a_region == b_region,
415+
};
416+
let check = |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| {
417+
match *constraint {
418+
Constraint::RegSubReg(sub, sup)
419+
if ((exact && sup == placeholder_region)
420+
|| (!exact && matches(sup, placeholder_region)))
421+
&& sup != sub =>
422+
{
423+
Some((sub, cause.clone()))
424+
}
425+
// FIXME: Should this check the universe of the var?
426+
Constraint::VarSubReg(vid, sup)
427+
if ((exact && sup == placeholder_region)
428+
|| (!exact && matches(sup, placeholder_region))) =>
429+
{
430+
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
418431
}
419-
})?;
432+
_ => None,
433+
}
434+
};
435+
let mut info = region_constraints
436+
.constraints
437+
.iter()
438+
.find_map(|(constraint, cause)| check(constraint, cause, true));
439+
if info.is_none() {
440+
info = region_constraints
441+
.constraints
442+
.iter()
443+
.find_map(|(constraint, cause)| check(constraint, cause, false));
444+
}
445+
let (sub_region, cause) = info?;
420446

421447
debug!(?sub_region, "cause = {:#?}", cause);
422448
let error = match (error_region, *sub_region) {

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ impl<'tcx> RegionErrors<'tcx> {
9595
}
9696
}
9797

98+
impl std::fmt::Debug for RegionErrors<'_> {
99+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100+
f.debug_tuple("RegionErrors").field(&self.0).finish()
101+
}
102+
}
103+
98104
#[derive(Clone, Debug)]
99105
pub(crate) enum RegionErrorKind<'tcx> {
100106
/// A generic bound failure for a type test (`T: 'a`).

compiler/rustc_borrowck/src/region_infer/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ pub(crate) struct AppliedMemberConstraint {
151151
pub(crate) member_constraint_index: NllMemberConstraintIndex,
152152
}
153153

154+
#[derive(Debug)]
154155
pub(crate) struct RegionDefinition<'tcx> {
155156
/// What kind of variable is this -- a free region? existential
156157
/// variable? etc. (See the `NllRegionVariableOrigin` for more
@@ -687,6 +688,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
687688
&mut errors_buffer,
688689
);
689690

691+
debug!(?errors_buffer);
692+
debug!(?outlives_requirements);
693+
690694
// In Polonius mode, the errors about missing universal region relations are in the output
691695
// and need to be emitted or propagated. Otherwise, we need to check whether the
692696
// constraints were too strong, and if so, emit or propagate those errors.
@@ -700,10 +704,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
700704
self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer);
701705
}
702706

707+
debug!(?errors_buffer);
708+
703709
if errors_buffer.is_empty() {
704710
self.check_member_constraints(infcx, &mut errors_buffer);
705711
}
706712

713+
debug!(?errors_buffer);
714+
707715
let outlives_requirements = outlives_requirements.unwrap_or_default();
708716

709717
if outlives_requirements.is_empty() {
@@ -1457,6 +1465,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
14571465
errors_buffer: &mut RegionErrors<'tcx>,
14581466
) {
14591467
for (fr, fr_definition) in self.definitions.iter_enumerated() {
1468+
debug!(?fr, ?fr_definition);
14601469
match fr_definition.origin {
14611470
NllRegionVariableOrigin::FreeRegion => {
14621471
// Go through each of the universal regions `fr` and check that

compiler/rustc_borrowck/src/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12021202
self.infcx.tcx
12031203
}
12041204

1205-
#[instrument(skip(self, body, location), level = "debug")]
1205+
#[instrument(skip(self, body), level = "debug")]
12061206
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
12071207
let tcx = self.tcx();
12081208
debug!("stmt kind: {:?}", stmt.kind);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn assert_all<F, T>(_f: F)
2+
where
3+
F: FnMut(&String) -> T,
4+
{
5+
}
6+
7+
fn id(x: &String) -> &String {
8+
x
9+
}
10+
11+
fn main() {
12+
assert_all::<_, &String>(id);
13+
//~^ mismatched types
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/higher-ranked-lifetime-error.rs:12:5
3+
|
4+
LL | assert_all::<_, &String>(id);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
6+
|
7+
= note: expected reference `&String`
8+
found reference `&String`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)