Skip to content

Commit 5a853d0

Browse files
authoredJul 25, 2024
Rollup merge of #128171 - compiler-errors:arg-compat, r=oli-obk
Make sure that args are compatible in `resolve_associated_item` Implements a similar check to the one that we have in projection for GATs (#102488, #123240), where we check that the args of an impl item are compatible before returning it. This is done in `resolve_assoc_item`, which is backing `Instance::resolve`, so this is conceptually generalizing the check from GATs to methods/assoc consts. This is important to make sure that the inliner will only visit and substitute MIR bodies that are compatible w/ their trait definitions. This shouldn't happen in codegen, but there are a few ways to get the inliner to be invoked (via calls to `optimized_mir`) before codegen, namely polymorphization and CTFE. Fixes #121957 Fixes #120792 Fixes #120793 Fixes #121063
2 parents 606c9fc + 40d132f commit 5a853d0

11 files changed

+108
-130
lines changed
 

‎compiler/rustc_ty_utils/src/instance.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,22 @@ fn resolve_associated_item<'tcx>(
191191

192192
// Any final impl is required to define all associated items.
193193
if !leaf_def.item.defaultness(tcx).has_value() {
194-
let guard = tcx.dcx().span_delayed_bug(
194+
let guar = tcx.dcx().span_delayed_bug(
195195
tcx.def_span(leaf_def.item.def_id),
196196
"missing value for assoc item in impl",
197197
);
198-
return Err(guard);
198+
return Err(guar);
199+
}
200+
201+
// Make sure that we're projecting to an item that has compatible args.
202+
// This may happen if we are resolving an instance before codegen, such
203+
// as during inlining. This check is also done in projection.
204+
if !tcx.check_args_compatible(leaf_def.item.def_id, args) {
205+
let guar = tcx.dcx().span_delayed_bug(
206+
tcx.def_span(leaf_def.item.def_id),
207+
"missing value for assoc item in impl",
208+
);
209+
return Err(guar);
199210
}
200211

201212
let args = tcx.erase_regions(args);

‎tests/crashes/120792.rs

-25
This file was deleted.

‎tests/crashes/120793-2.rs

-22
This file was deleted.

‎tests/crashes/120793.rs

-21
This file was deleted.

‎tests/crashes/121063.rs

-20
This file was deleted.

‎tests/crashes/121957-1.rs

-20
This file was deleted.

‎tests/crashes/121957-2.rs

-20
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// This test demonstrates an ICE that may occur when we try to resolve the instance
2+
// of a impl that has different generics than the trait it's implementing. This ensures
3+
// we first check that the args are compatible before resolving the body, just like
4+
// we do in projection before substituting a GAT.
5+
//
6+
// When polymorphization is enabled, we check the optimized MIR for unused parameters.
7+
// This will invoke the inliner, leading to this ICE.
8+
9+
//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes
10+
11+
trait Trait {
12+
fn foo<'a, K: 'a>(self, _: K);
13+
}
14+
15+
impl Trait for () {
16+
#[inline]
17+
fn foo<K>(self, _: K) {
18+
//~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration
19+
todo!();
20+
}
21+
}
22+
23+
pub fn qux<T>() {
24+
().foo(());
25+
}
26+
27+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
2+
--> $DIR/inline-incorrect-early-bound.rs:17:11
3+
|
4+
LL | fn foo<'a, K: 'a>(self, _: K);
5+
| -----------
6+
| | |
7+
| | this bound might be missing in the impl
8+
| lifetimes in impl do not match this method in trait
9+
...
10+
LL | fn foo<K>(self, _: K) {
11+
| ^^^ lifetimes do not match method in trait
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0195`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This test demonstrates an ICE that may occur when we try to resolve the instance
2+
// of a impl that has different generics than the trait it's implementing. This ensures
3+
// we first check that the args are compatible before resolving the body, just like
4+
// we do in projection before substituting a GAT.
5+
//
6+
// Const traits aren't the only way to achieve this ICE, but it's a convenient way
7+
// to ensure the inliner is called.
8+
9+
//@ compile-flags: -Znext-solver -Zinline-mir=yes
10+
11+
#![feature(const_trait_impl, effects)]
12+
//~^ WARN the feature `effects` is incomplete
13+
14+
trait Trait {
15+
fn foo(self);
16+
}
17+
18+
impl Trait for () {
19+
#[inline]
20+
fn foo<T>(self) {
21+
//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
22+
todo!();
23+
}
24+
}
25+
26+
const fn foo() {
27+
().foo();
28+
}
29+
30+
const UWU: () = foo();
31+
32+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/inline-incorrect-early-bound-in-ctfe.rs:11:30
3+
|
4+
LL | #![feature(const_trait_impl, effects)]
5+
| ^^^^^^^
6+
|
7+
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
11+
--> $DIR/inline-incorrect-early-bound-in-ctfe.rs:20:12
12+
|
13+
LL | fn foo(self);
14+
| - expected 0 type parameters
15+
...
16+
LL | fn foo<T>(self) {
17+
| ^ found 1 type parameter
18+
19+
error: aborting due to 1 previous error; 1 warning emitted
20+
21+
For more information about this error, try `rustc --explain E0049`.

0 commit comments

Comments
 (0)