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
This commit is contained in:
Guillaume Gomez 2024-11-28 03:14:46 +01:00 committed by GitHub
commit acf48fcb9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 24 deletions

View File

@ -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.resolve_vars_if_possible(impl_source);
let impl_source = infcx.tcx.erase_regions(impl_source); let impl_source = tcx.erase_regions(impl_source);
if impl_source.has_infer() { if impl_source.has_non_region_infer() {
// Unused lifetimes on an impl get replaced with inference vars, but never resolved, // Unused generic types or consts on an impl get replaced with inference vars,
// causing the return value of a query to contain inference vars. We do not have a concept // but never resolved, causing the return value of a query to contain inference
// for this and will in fact ICE in stable hashing of the return value. So bail out instead. // vars. We do not have a concept for this and will in fact ICE in stable hashing
infcx.tcx.dcx().has_errors().unwrap(); // 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); return Err(CodegenObligationError::FulfillmentError);
} }

View File

@ -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() {}

View File

@ -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() {}

View File

@ -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`.