Skip to content

Commit 0c14551

Browse files
authored
Rollup merge of #104697 - dingxiangfei2009:fix-euv-control-flow, r=oli-obk
Restore control flow on error in EUV cc `@Nilstrieb` Fix #104649 Since #98574 refactored a piece of scrutinee memory categorization out as a subroutine, there is a subtle change in handling match arms especially when the categorization process faults and bails. In the correct case, it is not supposed to continue to process the arms any more. This PR restores the original control flow in EUV. I promise to add a compile-fail test to demonstrate that this indeed fixes the issue after coming back from a nap.
2 parents d38a990 + 9cd12cd commit 0c14551

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
252252

253253
hir::ExprKind::Match(ref discr, arms, _) => {
254254
let discr_place = return_if_err!(self.mc.cat_expr(discr));
255-
self.maybe_read_scrutinee(
255+
return_if_err!(self.maybe_read_scrutinee(
256256
discr,
257257
discr_place.clone(),
258258
arms.iter().map(|arm| arm.pat),
259-
);
259+
));
260260

261261
// treatment of the discriminant is handled while walking the arms.
262262
for arm in arms {
@@ -390,15 +390,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
390390
discr: &Expr<'_>,
391391
discr_place: PlaceWithHirId<'tcx>,
392392
pats: impl Iterator<Item = &'t hir::Pat<'t>>,
393-
) {
393+
) -> Result<(), ()> {
394394
// Matching should not always be considered a use of the place, hence
395395
// discr does not necessarily need to be borrowed.
396396
// We only want to borrow discr if the pattern contain something other
397397
// than wildcards.
398398
let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self;
399399
let mut needs_to_be_read = false;
400400
for pat in pats {
401-
return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| {
401+
mc.cat_pattern(discr_place.clone(), pat, |place, pat| {
402402
match &pat.kind {
403403
PatKind::Binding(.., opt_sub_pat) => {
404404
// If the opt_sub_pat is None, than the binding does not count as
@@ -453,7 +453,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
453453
// examined
454454
}
455455
}
456-
}));
456+
})?
457457
}
458458

459459
if needs_to_be_read {
@@ -474,6 +474,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
474474
// that the discriminant has been initialized.
475475
self.walk_expr(discr);
476476
}
477+
Ok(())
477478
}
478479

479480
fn walk_local<F>(
@@ -490,7 +491,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
490491
f(self);
491492
if let Some(els) = els {
492493
// borrowing because we need to test the discriminant
493-
self.maybe_read_scrutinee(expr, expr_place.clone(), from_ref(pat).iter());
494+
return_if_err!(self.maybe_read_scrutinee(
495+
expr,
496+
expr_place.clone(),
497+
from_ref(pat).iter()
498+
));
494499
self.walk_block(els)
495500
}
496501
self.walk_irrefutable_pat(&expr_place, &pat);

compiler/rustc_hir_typeck/src/upvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2168,7 +2168,7 @@ fn determine_place_ancestry_relation<'tcx>(
21682168
place_a: &Place<'tcx>,
21692169
place_b: &Place<'tcx>,
21702170
) -> PlaceAncestryRelation {
2171-
// If Place A and Place B, don't start off from the same root variable, they are divergent.
2171+
// If Place A and Place B don't start off from the same root variable, they are divergent.
21722172
if place_a.base != place_b.base {
21732173
return PlaceAncestryRelation::Divergent;
21742174
}

src/test/ui/inference/issue-104649.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
type Result<T, E = Error> = ::std::result::Result<T, E>;
2+
struct Error;
3+
4+
trait ForEach {
5+
type Input;
6+
fn for_each<F, U>(self, f: F)
7+
where
8+
F: FnOnce(Self::Input) -> U;
9+
}
10+
11+
impl<T> ForEach for A<T> {
12+
type Input = T;
13+
fn for_each<F, U>(self, f: F)
14+
where
15+
F: FnOnce(Self::Input) -> U,
16+
{
17+
todo!()
18+
}
19+
}
20+
21+
struct A<T>(T);
22+
23+
fn main() {
24+
let a = A(Result::Ok(Result::Ok(()))); //~ ERROR type annotations needed
25+
a.for_each(|a: Result<_>| {
26+
let f = || match a {
27+
Ok(Ok(a)) => {}
28+
Ok(Err(a)) => {}
29+
Err(a) => {}
30+
};
31+
});
32+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), E>, Error>>`
2+
--> $DIR/issue-104649.rs:24:9
3+
|
4+
LL | let a = A(Result::Ok(Result::Ok(())));
5+
| ^
6+
|
7+
help: consider giving `a` an explicit type, where the type for type parameter `E` is specified
8+
|
9+
LL | let a: A<std::result::Result<std::result::Result<(), E>, Error>> = A(Result::Ok(Result::Ok(())));
10+
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)