diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 618a65a018644..9f2b6b968c027 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -653,7 +653,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, placeholder: Self::PlaceholderConst, ) -> Ty<'tcx> { - placeholder.find_const_ty_from_env(param_env) + placeholder.find_const_ty_from_env_unwrap(param_env) } fn anonymize_bound_vars>>( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 255d464d26541..1e508b635ad7f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -846,7 +846,7 @@ pub struct Placeholder { pub bound: T, } impl Placeholder { - pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Option> { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. match clause.kind().skip_binder() { @@ -864,10 +864,18 @@ impl Placeholder { } }); - let ty = candidates.next().unwrap(); - assert!(candidates.next().is_none()); + let ty = candidates.next(); + if ty.is_some() { + assert!(candidates.next().is_none()); + } ty } + + /// Same as `find_const_ty_from_env` but unwraps the result. + /// This will panic if no type is found for the const parameter. + pub fn find_const_ty_from_env_unwrap<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + self.find_const_ty_from_env(env).unwrap() + } } pub type PlaceholderRegion = Placeholder; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74a94d8278453..aea48ac1f03dc 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -342,7 +342,7 @@ impl ParamConst { } #[instrument(level = "debug")] - pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Option> { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. match clause.kind().skip_binder() { @@ -358,10 +358,19 @@ impl ParamConst { } }); - let ty = candidates.next().unwrap(); - assert!(candidates.next().is_none()); + let ty = candidates.next(); + if ty.is_some() { + assert!(candidates.next().is_none()); + } ty } + + /// Same as `find_ty_from_env` but unwraps the result. + /// This will panic if no type is found for the const parameter. + #[instrument(level = "debug")] + pub fn find_ty_from_env_unwrap<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + self.find_ty_from_env(env).unwrap() + } } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 3a939df25e07b..b33cd3d1bc662 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -36,7 +36,15 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( ty::ConstKind::Unevaluated(uv) => { infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) } - ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env), + ty::ConstKind::Param(param_ct) => { + match param_ct.find_ty_from_env(obligation.param_env) { + Some(ty) => ty, + None => { + // If we can't find the type, use error type + Ty::new_misc_error(infcx.tcx) + } + } + }, ty::ConstKind::Value(cv) => cv.ty, kind => span_bug!( obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e98a240a53f52..07a4ee6d39254 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -503,7 +503,15 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), ty::ConstKind::Param(param_ct) => { - param_ct.find_ty_from_env(obligation.param_env) + match param_ct.find_ty_from_env(obligation.param_env) { + Some(ty) => ty, + None => { + // If we can't find the type, return an error + return ProcessResult::Error(FulfillmentErrorCode::Select( + SelectionError::Unimplemented + )); + } + } } }; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0679dbf1296af..bacabdda47fee 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -972,7 +972,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), ty::ConstKind::Param(param_ct) => { - param_ct.find_ty_from_env(obligation.param_env) + match param_ct.find_ty_from_env(obligation.param_env) { + Some(ty) => ty, + None => { + // If we can't find the type, return an error + return Ok(EvaluatedToErr); + } + } } }; diff --git a/tests/ui/async-await/issue-139314-option-unwrap-none-regression.rs b/tests/ui/async-await/issue-139314-option-unwrap-none-regression.rs new file mode 100644 index 0000000000000..0c168c74287b1 --- /dev/null +++ b/tests/ui/async-await/issue-139314-option-unwrap-none-regression.rs @@ -0,0 +1,15 @@ +// Test for issue #139314 +// This test ensures that the compiler properly reports an error +// instead of panicking with "called `Option::unwrap()` on a `None` value" +// when processing async functions with const parameters. + +//@ edition:2018 +//@ error-pattern: the trait bound + +async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + func(iter.map(|x| x + 1)) +} + +fn main() { + // Just make sure the function compiles, we don't need to call it +} diff --git a/tests/ui/async-await/issue-139314-option-unwrap-none-regression.stderr b/tests/ui/async-await/issue-139314-option-unwrap-none-regression.stderr new file mode 100644 index 0000000000000..9e6018842354f --- /dev/null +++ b/tests/ui/async-await/issue-139314-option-unwrap-none-regression.stderr @@ -0,0 +1,80 @@ +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-regression.rs:10:10 + | +LL | func(iter.map(|x| x + 1)) + | ---- ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` +help: consider removing this method call, as the receiver has type `T` and `T: Copy` trivially holds + | +LL - func(iter.map(|x| x + 1)) +LL + func(iter) + | + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-regression.rs:10:5 + | +LL | func(iter.map(|x| x + 1)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:94 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ______________________________________________________________________________________________^ +LL | | func(iter.map(|x| x + 1)) +LL | | } + | |_^ the trait `Clone` is not implemented for `impl Future` + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:94 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ______________________________________________________________________________________________^ +LL | | func(iter.map(|x| x + 1)) +LL | | } + | |_^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:1 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-regression.rs:9:74 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-139314-option-unwrap-none-test.rs b/tests/ui/async-await/issue-139314-option-unwrap-none-test.rs new file mode 100644 index 0000000000000..0526d449436ae --- /dev/null +++ b/tests/ui/async-await/issue-139314-option-unwrap-none-test.rs @@ -0,0 +1,16 @@ +// Test for issue #139314 +// This test ensures that the compiler doesn't panic with +// "called `Option::unwrap()` on a `None` value" when processing +// async functions with const parameters. + +//@ edition:2018 +//@ error-pattern: the trait bound + +// This is a simplified version of the test case that caused the ICE +async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + func(iter.map(|x| x + 1)) +} + +fn main() { + // Just make sure the function compiles, we don't need to call it +} diff --git a/tests/ui/async-await/issue-139314-option-unwrap-none-test.stderr b/tests/ui/async-await/issue-139314-option-unwrap-none-test.stderr new file mode 100644 index 0000000000000..5c1b0ca105c33 --- /dev/null +++ b/tests/ui/async-await/issue-139314-option-unwrap-none-test.stderr @@ -0,0 +1,80 @@ +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-test.rs:11:10 + | +LL | func(iter.map(|x| x + 1)) + | ---- ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` +help: consider removing this method call, as the receiver has type `T` and `T: Copy` trivially holds + | +LL - func(iter.map(|x| x + 1)) +LL + func(iter) + | + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-test.rs:11:5 + | +LL | func(iter.map(|x| x + 1)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:94 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ______________________________________________________________________________________________^ +LL | | func(iter.map(|x| x + 1)) +LL | | } + | |_^ the trait `Clone` is not implemented for `impl Future` + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:94 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ______________________________________________________________________________________________^ +LL | | func(iter.map(|x| x + 1)) +LL | | } + | |_^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:1 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/issue-139314-option-unwrap-none-test.rs:10:74 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-139314-option-unwrap-none.rs b/tests/ui/async-await/issue-139314-option-unwrap-none.rs new file mode 100644 index 0000000000000..c4e150b252a7b --- /dev/null +++ b/tests/ui/async-await/issue-139314-option-unwrap-none.rs @@ -0,0 +1,15 @@ +// Test for issue #139314 +// This test ensures that the compiler doesn't panic with +// "called `Option::unwrap()` on a `None` value" when processing +// async functions with const parameters. + +//@ edition:2018 +//@ error-pattern: the trait bound + +async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + func(iter.map(|x| x + 1)) +} + +fn main() { + // Just make sure the function compiles, we don't need to call it +} diff --git a/tests/ui/async-await/issue-139314-option-unwrap-none.stderr b/tests/ui/async-await/issue-139314-option-unwrap-none.stderr new file mode 100644 index 0000000000000..50570965118cd --- /dev/null +++ b/tests/ui/async-await/issue-139314-option-unwrap-none.stderr @@ -0,0 +1,80 @@ +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none.rs:10:10 + | +LL | func(iter.map(|x| x + 1)) + | ---- ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` +help: consider removing this method call, as the receiver has type `T` and `T: Copy` trivially holds + | +LL - func(iter.map(|x| x + 1)) +LL + func(iter) + | + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none.rs:10:5 + | +LL | func(iter.map(|x| x + 1)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/issue-139314-option-unwrap-none.rs:9:94 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ______________________________________________________________________________________________^ +LL | | func(iter.map(|x| x + 1)) +LL | | } + | |_^ the trait `Clone` is not implemented for `impl Future` + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none.rs:9:94 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ______________________________________________________________________________________________^ +LL | | func(iter.map(|x| x + 1)) +LL | | } + | |_^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `Map: Copy` is not satisfied + --> $DIR/issue-139314-option-unwrap-none.rs:9:1 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: the trait `Copy` is not implemented for `Map` +note: required by a bound in `func` + --> $DIR/issue-139314-option-unwrap-none.rs:9:40 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^ required by this bound in `func` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/issue-139314-option-unwrap-none.rs:9:74 + | +LL | async fn func + Copy, const N: usize>(iter: T) -> impl for<'a1> Clone { + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`.