diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2024-11-28 03:14:46 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-28 03:14:46 +0100 |
| commit | acf48fcb9d69e7c612efbca37dc4fbf4eb8ac2a9 (patch) | |
| tree | a2455ec44d83a5f07096ffc265a03a4ea4b935b9 | |
| parent | 09734ac3aff28e1089a1790567d25341c985af69 (diff) | |
| parent | 50fb40a987746e8847091ce354b649be4a44cde1 (diff) | |
| download | rust-acf48fcb9d69e7c612efbca37dc4fbf4eb8ac2a9.tar.gz rust-acf48fcb9d69e7c612efbca37dc4fbf4eb8ac2a9.zip | |
Rollup merge of #133368 - compiler-errors:codegen-select-unconstrained-params, r=lcnr
Delay a bug when encountering an impl with unconstrained generics in `codegen_select` Despite its name, `codegen_select` is what powers `Instance::try_resolve`, which is used in pre-codegen contexts to try to resolve a method where possible. One place that it's used is in the "recursion MIR lint" that detects recursive MIR bodies. If we encounter an impl in `codegen_select` that contains unconstrained generic parameters, we expect that impl to caused an error to be reported; however, there's no temporal guarantee that this error is reported *before* we call `codegen_select`. This is what a delayed bug is *for*, and this PR makes us use a delayed bug rather than asserting something about errors already having been emitted. Fixes #126646
| -rw-r--r-- | compiler/rustc_traits/src/codegen.rs | 21 | ||||
| -rw-r--r-- | tests/crashes/126646.rs | 18 | ||||
| -rw-r--r-- | tests/ui/traits/resolve-impl-before-constrain-check.rs | 20 | ||||
| -rw-r--r-- | tests/ui/traits/resolve-impl-before-constrain-check.stderr | 9 |
4 files changed, 44 insertions, 24 deletions
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 57225df0819..e5276e6d515 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -74,12 +74,21 @@ pub(crate) fn codegen_select_candidate<'tcx>( } let impl_source = infcx.resolve_vars_if_possible(impl_source); - let impl_source = infcx.tcx.erase_regions(impl_source); - if impl_source.has_infer() { - // Unused lifetimes on an impl get replaced with inference vars, but never resolved, - // causing the return value of a query to contain inference vars. We do not have a concept - // for this and will in fact ICE in stable hashing of the return value. So bail out instead. - infcx.tcx.dcx().has_errors().unwrap(); + let impl_source = tcx.erase_regions(impl_source); + if impl_source.has_non_region_infer() { + // Unused generic types or consts on an impl get replaced with inference vars, + // but never resolved, causing the return value of a query to contain inference + // vars. We do not have a concept for this and will in fact ICE in stable hashing + // of the return value. So bail out instead. + match impl_source { + ImplSource::UserDefined(impl_) => { + tcx.dcx().span_delayed_bug( + tcx.def_span(impl_.impl_def_id), + "this impl has unconstrained generic parameters", + ); + } + _ => unreachable!(), + } return Err(CodegenObligationError::FulfillmentError); } diff --git a/tests/crashes/126646.rs b/tests/crashes/126646.rs deleted file mode 100644 index 24e3530320a..00000000000 --- a/tests/crashes/126646.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: rust-lang/rust#126646 -mod foo { - pub trait Callable { - type Output; - fn call() -> Self::Output; - } - - impl<'a, V: ?Sized> Callable for &'a () { - type Output = (); - } -} -use foo::*; - -fn test<'a>() -> impl Sized { - <&'a () as Callable>::call() -} - -fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.rs b/tests/ui/traits/resolve-impl-before-constrain-check.rs new file mode 100644 index 00000000000..87f9c241e40 --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.rs @@ -0,0 +1,20 @@ +// Need a different module so we try to build the mir for `test` +// before analyzing `mod foo`. + +mod foo { + pub trait Callable { + fn call(); + } + + impl<V: ?Sized> Callable for () { + //~^ ERROR the type parameter `V` is not constrained by the impl trait, self type, or predicates + fn call() {} + } +} +use foo::*; + +fn test() -> impl Sized { + <() as Callable>::call() +} + +fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr new file mode 100644 index 00000000000..e8e569ba625 --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates + --> $DIR/resolve-impl-before-constrain-check.rs:9:10 + | +LL | impl<V: ?Sized> Callable for () { + | ^ unconstrained type parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0207`. |
