Skip to content

Commit 096309e

Browse files
committed
Auto merge of #111919 - matthiaskrgr:rollup-8qcdp0q, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #111121 (Work around `rust-analyzer` false-positive type errors) - #111759 (Leverage the interval property to precompute borrow kill points.) - #111841 (Run AST validation on match guards correctly) - #111862 (Split out opaque collection from from `type_of`) - #111863 (Don't skip mir typeck if body has errors) - #111903 (Migrate GUI colors test to original CSS color format) r? `@ghost` `@rustbot` modify labels: rollup
2 parents c373194 + 0cc987f commit 096309e

File tree

15 files changed

+661
-428
lines changed

15 files changed

+661
-428
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -736,11 +736,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
736736
this.visit_expr(&arm.body);
737737
this.visit_pat(&arm.pat);
738738
walk_list!(this, visit_attribute, &arm.attrs);
739-
if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind {
739+
if let Some(guard) = &arm.guard {
740740
this.with_let_management(None, |this, _| {
741-
this.visit_expr(guard_expr)
741+
this.visit_expr(guard)
742742
});
743-
return;
744743
}
745744
}
746745
}

compiler/rustc_borrowck/src/dataflow.rs

+46-49
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
156156
&mut self,
157157
borrow_index: BorrowIndex,
158158
borrow_region: RegionVid,
159-
location: Location,
159+
first_location: Location,
160160
) {
161161
// We visit one BB at a time. The complication is that we may start in the
162-
// middle of the first BB visited (the one containing `location`), in which
162+
// middle of the first BB visited (the one containing `first_location`), in which
163163
// case we may have to later on process the first part of that BB if there
164164
// is a path back to its start.
165165

@@ -168,61 +168,58 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
168168
// `visited` once they are added to `stack`, before they are actually
169169
// processed, because this avoids the need to look them up again on
170170
// completion.
171-
self.visited.insert(location.block);
171+
self.visited.insert(first_location.block);
172172

173-
let mut first_lo = location.statement_index;
174-
let first_hi = self.body[location.block].statements.len();
173+
let first_block = first_location.block;
174+
let mut first_lo = first_location.statement_index;
175+
let first_hi = self.body[first_block].statements.len();
175176

176-
self.visit_stack.push(StackEntry { bb: location.block, lo: first_lo, hi: first_hi });
177+
self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
177178

178-
while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
179-
// If we process the first part of the first basic block (i.e. we encounter that block
180-
// for the second time), we no longer have to visit its successors again.
181-
let mut finished_early = bb == location.block && hi != first_hi;
182-
for i in lo..=hi {
183-
let location = Location { block: bb, statement_index: i };
179+
'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
180+
if let Some(kill_stmt) =
181+
self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
182+
{
183+
let kill_location = Location { block: bb, statement_index: kill_stmt };
184184
// If region does not contain a point at the location, then add to list and skip
185185
// successor locations.
186-
if !self.regioncx.region_contains(borrow_region, location) {
187-
debug!("borrow {:?} gets killed at {:?}", borrow_index, location);
188-
self.borrows_out_of_scope_at_location
189-
.entry(location)
190-
.or_default()
191-
.push(borrow_index);
192-
finished_early = true;
193-
break;
194-
}
186+
debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
187+
self.borrows_out_of_scope_at_location
188+
.entry(kill_location)
189+
.or_default()
190+
.push(borrow_index);
191+
continue 'preorder;
195192
}
196193

197-
if !finished_early {
198-
// Add successor BBs to the work list, if necessary.
199-
let bb_data = &self.body[bb];
200-
debug_assert!(hi == bb_data.statements.len());
201-
for succ_bb in bb_data.terminator().successors() {
202-
if !self.visited.insert(succ_bb) {
203-
if succ_bb == location.block && first_lo > 0 {
204-
// `succ_bb` has been seen before. If it wasn't
205-
// fully processed, add its first part to `stack`
206-
// for processing.
207-
self.visit_stack.push(StackEntry {
208-
bb: succ_bb,
209-
lo: 0,
210-
hi: first_lo - 1,
211-
});
212-
213-
// And update this entry with 0, to represent the
214-
// whole BB being processed.
215-
first_lo = 0;
216-
}
217-
} else {
218-
// succ_bb hasn't been seen before. Add it to
219-
// `stack` for processing.
220-
self.visit_stack.push(StackEntry {
221-
bb: succ_bb,
222-
lo: 0,
223-
hi: self.body[succ_bb].statements.len(),
224-
});
194+
// If we process the first part of the first basic block (i.e. we encounter that block
195+
// for the second time), we no longer have to visit its successors again.
196+
if bb == first_block && hi != first_hi {
197+
continue;
198+
}
199+
200+
// Add successor BBs to the work list, if necessary.
201+
let bb_data = &self.body[bb];
202+
debug_assert!(hi == bb_data.statements.len());
203+
for succ_bb in bb_data.terminator().successors() {
204+
if !self.visited.insert(succ_bb) {
205+
if succ_bb == first_block && first_lo > 0 {
206+
// `succ_bb` has been seen before. If it wasn't
207+
// fully processed, add its first part to `stack`
208+
// for processing.
209+
self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
210+
211+
// And update this entry with 0, to represent the
212+
// whole BB being processed.
213+
first_lo = 0;
225214
}
215+
} else {
216+
// succ_bb hasn't been seen before. Add it to
217+
// `stack` for processing.
218+
self.visit_stack.push(StackEntry {
219+
bb: succ_bb,
220+
lo: 0,
221+
hi: self.body[succ_bb].statements.len(),
222+
});
226223
}
227224
}
228225
}

compiler/rustc_borrowck/src/region_infer/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_infer::infer::outlives::test_type_match;
1212
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
1313
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
1414
use rustc_middle::mir::{
15-
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
15+
BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
1616
ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
1717
TerminatorKind,
1818
};
@@ -598,6 +598,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
598598
self.scc_values.contains(scc, p)
599599
}
600600

601+
/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
602+
///
603+
/// Panics if called before `solve()` executes.
604+
pub(crate) fn first_non_contained_inclusive(
605+
&self,
606+
r: RegionVid,
607+
block: BasicBlock,
608+
start: usize,
609+
end: usize,
610+
) -> Option<usize> {
611+
let scc = self.constraint_sccs.scc(r);
612+
self.scc_values.first_non_contained_inclusive(scc, block, start, end)
613+
}
614+
601615
/// Returns access to the value of `r` for debugging purposes.
602616
pub(crate) fn region_value_str(&self, r: RegionVid) -> String {
603617
let scc = self.constraint_sccs.scc(r);

compiler/rustc_borrowck/src/region_infer/values.rs

+16
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,22 @@ impl<N: Idx> RegionValues<N> {
283283
elem.contained_in_row(self, r)
284284
}
285285

286+
/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
287+
pub(crate) fn first_non_contained_inclusive(
288+
&self,
289+
r: N,
290+
block: BasicBlock,
291+
start: usize,
292+
end: usize,
293+
) -> Option<usize> {
294+
let row = self.points.row(r)?;
295+
let block = self.elements.entry_point(block);
296+
let start = block.plus(start);
297+
let end = block.plus(end);
298+
let first_unset = row.first_unset_in(start..=end)?;
299+
Some(first_unset.index() - block.index())
300+
}
301+
286302
/// `self[to] |= values[from]`, essentially: that is, take all the
287303
/// elements for the region `from` from `values` and add them to
288304
/// the region `to` in `self`.

compiler/rustc_borrowck/src/type_check/mod.rs

+9-27
Original file line numberDiff line numberDiff line change
@@ -183,17 +183,10 @@ pub(crate) fn type_check<'mir, 'tcx>(
183183
&mut borrowck_context,
184184
);
185185

186-
let errors_reported = {
187-
let mut verifier = TypeVerifier::new(&mut checker, promoted);
188-
verifier.visit_body(&body);
189-
verifier.errors_reported
190-
};
191-
192-
if !errors_reported {
193-
// if verifier failed, don't do further checks to avoid ICEs
194-
checker.typeck_mir(body);
195-
}
186+
let mut verifier = TypeVerifier::new(&mut checker, promoted);
187+
verifier.visit_body(&body);
196188

189+
checker.typeck_mir(body);
197190
checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
198191
checker.check_signature_annotation(&body);
199192

@@ -294,7 +287,6 @@ struct TypeVerifier<'a, 'b, 'tcx> {
294287
cx: &'a mut TypeChecker<'b, 'tcx>,
295288
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
296289
last_span: Span,
297-
errors_reported: bool,
298290
}
299291

300292
impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
@@ -383,13 +375,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
383375
};
384376
};
385377

386-
if !self.errors_reported {
387-
let promoted_body = &self.promoted[promoted];
388-
self.sanitize_promoted(promoted_body, location);
378+
let promoted_body = &self.promoted[promoted];
379+
self.sanitize_promoted(promoted_body, location);
389380

390-
let promoted_ty = promoted_body.return_ty();
391-
check_err(self, promoted_body, ty, promoted_ty);
392-
}
381+
let promoted_ty = promoted_body.return_ty();
382+
check_err(self, promoted_body, ty, promoted_ty);
393383
} else {
394384
self.cx.ascribe_user_type(
395385
constant.literal.ty(),
@@ -483,9 +473,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
483473
for local_decl in &body.local_decls {
484474
self.sanitize_type(local_decl, local_decl.ty);
485475
}
486-
if self.errors_reported {
487-
return;
488-
}
489476
self.super_body(body);
490477
}
491478
}
@@ -495,7 +482,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
495482
cx: &'a mut TypeChecker<'b, 'tcx>,
496483
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
497484
) -> Self {
498-
TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
485+
TypeVerifier { promoted, last_span: cx.body.span, cx }
499486
}
500487

501488
fn body(&self) -> &Body<'tcx> {
@@ -529,7 +516,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
529516
for elem in place.projection.iter() {
530517
if place_ty.variant_index.is_none() {
531518
if let Err(guar) = place_ty.ty.error_reported() {
532-
assert!(self.errors_reported);
533519
return PlaceTy::from_ty(self.tcx().ty_error(guar));
534520
}
535521
}
@@ -593,10 +579,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
593579

594580
self.visit_body(&promoted_body);
595581

596-
if !self.errors_reported {
597-
// if verifier failed, don't do further checks to avoid ICEs
598-
self.cx.typeck_mir(promoted_body);
599-
}
582+
self.cx.typeck_mir(promoted_body);
600583

601584
self.cx.body = parent_body;
602585
// Merge the outlives constraints back in, at the given location.
@@ -762,7 +745,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
762745
}
763746

764747
fn error(&mut self) -> Ty<'tcx> {
765-
self.errors_reported = true;
766748
self.tcx().ty_error_misc()
767749
}
768750

0 commit comments

Comments
 (0)