Skip to content

Commit 1305c9c

Browse files
committed
Fix ICE in ParamConst::find_ty_from_env when handling None values
1 parent e0883a2 commit 1305c9c

File tree

12 files changed

+335
-10
lines changed

12 files changed

+335
-10
lines changed

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
653653
param_env: ty::ParamEnv<'tcx>,
654654
placeholder: Self::PlaceholderConst,
655655
) -> Ty<'tcx> {
656-
placeholder.find_const_ty_from_env(param_env)
656+
placeholder.find_const_ty_from_env_unwrap(param_env)
657657
}
658658

659659
fn anonymize_bound_vars<T: TypeFoldable<TyCtxt<'tcx>>>(

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ pub struct Placeholder<T> {
846846
pub bound: T,
847847
}
848848
impl Placeholder<BoundVar> {
849-
pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
849+
pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Option<Ty<'tcx>> {
850850
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
851851
// `ConstArgHasType` are never desugared to be higher ranked.
852852
match clause.kind().skip_binder() {
@@ -864,10 +864,18 @@ impl Placeholder<BoundVar> {
864864
}
865865
});
866866

867-
let ty = candidates.next().unwrap();
868-
assert!(candidates.next().is_none());
867+
let ty = candidates.next();
868+
if ty.is_some() {
869+
assert!(candidates.next().is_none());
870+
}
869871
ty
870872
}
873+
874+
/// Same as `find_const_ty_from_env` but unwraps the result.
875+
/// This will panic if no type is found for the const parameter.
876+
pub fn find_const_ty_from_env_unwrap<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
877+
self.find_const_ty_from_env(env).unwrap()
878+
}
871879
}
872880

873881
pub type PlaceholderRegion = Placeholder<BoundRegion>;

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ impl ParamConst {
342342
}
343343

344344
#[instrument(level = "debug")]
345-
pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
345+
pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Option<Ty<'tcx>> {
346346
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
347347
// `ConstArgHasType` are never desugared to be higher ranked.
348348
match clause.kind().skip_binder() {
@@ -358,10 +358,19 @@ impl ParamConst {
358358
}
359359
});
360360

361-
let ty = candidates.next().unwrap();
362-
assert!(candidates.next().is_none());
361+
let ty = candidates.next();
362+
if ty.is_some() {
363+
assert!(candidates.next().is_none());
364+
}
363365
ty
364366
}
367+
368+
/// Same as `find_ty_from_env` but unwraps the result.
369+
/// This will panic if no type is found for the const parameter.
370+
#[instrument(level = "debug")]
371+
pub fn find_ty_from_env_unwrap<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
372+
self.find_ty_from_env(env).unwrap()
373+
}
365374
}
366375

367376
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]

compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,15 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>(
3636
ty::ConstKind::Unevaluated(uv) => {
3737
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
3838
}
39-
ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env),
39+
ty::ConstKind::Param(param_ct) => {
40+
match param_ct.find_ty_from_env(obligation.param_env) {
41+
Some(ty) => ty,
42+
None => {
43+
// If we can't find the type, use error type
44+
Ty::new_misc_error(infcx.tcx)
45+
}
46+
}
47+
},
4048
ty::ConstKind::Value(cv) => cv.ty,
4149
kind => span_bug!(
4250
obligation.cause.span,

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,15 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
503503
}
504504
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
505505
ty::ConstKind::Param(param_ct) => {
506-
param_ct.find_ty_from_env(obligation.param_env)
506+
match param_ct.find_ty_from_env(obligation.param_env) {
507+
Some(ty) => ty,
508+
None => {
509+
// If we can't find the type, return an error
510+
return ProcessResult::Error(FulfillmentErrorCode::Select(
511+
SelectionError::Unimplemented
512+
));
513+
}
514+
}
507515
}
508516
};
509517

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
972972
}
973973
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
974974
ty::ConstKind::Param(param_ct) => {
975-
param_ct.find_ty_from_env(obligation.param_env)
975+
match param_ct.find_ty_from_env(obligation.param_env) {
976+
Some(ty) => ty,
977+
None => {
978+
// If we can't find the type, return an error
979+
return Ok(EvaluatedToErr);
980+
}
981+
}
976982
}
977983
};
978984

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Test for issue #139314
2+
// This test ensures that the compiler properly reports an error
3+
// instead of panicking with "called `Option::unwrap()` on a `None` value"
4+
// when processing async functions with const parameters.
5+
6+
//@ edition:2018
7+
//@ error-pattern: the trait bound
8+
9+
async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
10+
func(iter.map(|x| x + 1))
11+
}
12+
13+
fn main() {
14+
// Just make sure the function compiles, we don't need to call it
15+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>: Copy` is not satisfied
2+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:10:10
3+
|
4+
LL | func(iter.map(|x| x + 1))
5+
| ---- ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>`
10+
note: required by a bound in `func`
11+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40
12+
|
13+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
14+
| ^^^^ required by this bound in `func`
15+
help: consider removing this method call, as the receiver has type `T` and `T: Copy` trivially holds
16+
|
17+
LL - func(iter.map(|x| x + 1))
18+
LL + func(iter)
19+
|
20+
21+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>: Copy` is not satisfied
22+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:10:5
23+
|
24+
LL | func(iter.map(|x| x + 1))
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
26+
|
27+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>`
28+
note: required by a bound in `func`
29+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40
30+
|
31+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
32+
| ^^^^ required by this bound in `func`
33+
34+
error[E0277]: the trait bound `impl Future<Output = impl Clone>: Clone` is not satisfied
35+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:94
36+
|
37+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
38+
| ______________________________________________________________________________________________^
39+
LL | | func(iter.map(|x| x + 1))
40+
LL | | }
41+
| |_^ the trait `Clone` is not implemented for `impl Future<Output = impl Clone>`
42+
43+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>: Copy` is not satisfied
44+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:94
45+
|
46+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
47+
| ______________________________________________________________________________________________^
48+
LL | | func(iter.map(|x| x + 1))
49+
LL | | }
50+
| |_^ unsatisfied trait bound
51+
|
52+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>`
53+
note: required by a bound in `func`
54+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40
55+
|
56+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
57+
| ^^^^ required by this bound in `func`
58+
59+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>: Copy` is not satisfied
60+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:1
61+
|
62+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
64+
|
65+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-regression.rs:10:19: 10:22}>`
66+
note: required by a bound in `func`
67+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40
68+
|
69+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
70+
| ^^^^ required by this bound in `func`
71+
72+
error[E0277]: the trait bound `impl Future<Output = impl Clone>: Clone` is not satisfied
73+
--> $DIR/issue-139314-option-unwrap-none-regression.rs:9:74
74+
|
75+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
76+
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = impl Clone>`
77+
78+
error: aborting due to 6 previous errors
79+
80+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Test for issue #139314
2+
// This test ensures that the compiler doesn't panic with
3+
// "called `Option::unwrap()` on a `None` value" when processing
4+
// async functions with const parameters.
5+
6+
//@ edition:2018
7+
//@ error-pattern: the trait bound
8+
9+
// This is a simplified version of the test case that caused the ICE
10+
async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
11+
func(iter.map(|x| x + 1))
12+
}
13+
14+
fn main() {
15+
// Just make sure the function compiles, we don't need to call it
16+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>: Copy` is not satisfied
2+
--> $DIR/issue-139314-option-unwrap-none-test.rs:11:10
3+
|
4+
LL | func(iter.map(|x| x + 1))
5+
| ---- ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>`
10+
note: required by a bound in `func`
11+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:40
12+
|
13+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
14+
| ^^^^ required by this bound in `func`
15+
help: consider removing this method call, as the receiver has type `T` and `T: Copy` trivially holds
16+
|
17+
LL - func(iter.map(|x| x + 1))
18+
LL + func(iter)
19+
|
20+
21+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>: Copy` is not satisfied
22+
--> $DIR/issue-139314-option-unwrap-none-test.rs:11:5
23+
|
24+
LL | func(iter.map(|x| x + 1))
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
26+
|
27+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>`
28+
note: required by a bound in `func`
29+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:40
30+
|
31+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
32+
| ^^^^ required by this bound in `func`
33+
34+
error[E0277]: the trait bound `impl Future<Output = impl Clone>: Clone` is not satisfied
35+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:94
36+
|
37+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
38+
| ______________________________________________________________________________________________^
39+
LL | | func(iter.map(|x| x + 1))
40+
LL | | }
41+
| |_^ the trait `Clone` is not implemented for `impl Future<Output = impl Clone>`
42+
43+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>: Copy` is not satisfied
44+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:94
45+
|
46+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
47+
| ______________________________________________________________________________________________^
48+
LL | | func(iter.map(|x| x + 1))
49+
LL | | }
50+
| |_^ unsatisfied trait bound
51+
|
52+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>`
53+
note: required by a bound in `func`
54+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:40
55+
|
56+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
57+
| ^^^^ required by this bound in `func`
58+
59+
error[E0277]: the trait bound `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>: Copy` is not satisfied
60+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:1
61+
|
62+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
64+
|
65+
= help: the trait `Copy` is not implemented for `Map<T, {closure@$DIR/issue-139314-option-unwrap-none-test.rs:11:19: 11:22}>`
66+
note: required by a bound in `func`
67+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:40
68+
|
69+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
70+
| ^^^^ required by this bound in `func`
71+
72+
error[E0277]: the trait bound `impl Future<Output = impl Clone>: Clone` is not satisfied
73+
--> $DIR/issue-139314-option-unwrap-none-test.rs:10:74
74+
|
75+
LL | async fn func<T: Iterator<Item = u8> + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone {
76+
| ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = impl Clone>`
77+
78+
error: aborting due to 6 previous errors
79+
80+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)