Skip to content

Commit 6c021cf

Browse files
authored
Rollup merge of #103827 - compiler-errors:rpitit-substs-compat, r=wesleywiser
Properly remap and check for substs compatibility in `confirm_impl_trait_in_trait_candidate` Fixes #103824
2 parents 83e73e0 + 0f632c8 commit 6c021cf

File tree

7 files changed

+127
-4
lines changed

7 files changed

+127
-4
lines changed

compiler/rustc_middle/src/ty/error.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,9 @@ impl<'tcx> TyCtxt<'tcx> {
430430
(ty::Projection(_), ty::Projection(_)) => {
431431
diag.note("an associated type was expected, but a different one was found");
432432
}
433-
(ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => {
433+
(ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
434+
if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
435+
{
434436
let generics = self.generics_of(body_owner_def_id);
435437
let p_span = self.def_span(generics.type_param(p, self).def_id);
436438
if !sp.contains(p_span) {

compiler/rustc_trait_selection/src/traits/project.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -2187,7 +2187,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
21872187
// Verify that the trait item and its implementation have compatible substs lists
21882188
fn check_substs_compatible<'tcx>(
21892189
tcx: TyCtxt<'tcx>,
2190-
assoc_ty: &ty::AssocItem,
2190+
assoc_item: &ty::AssocItem,
21912191
substs: ty::SubstsRef<'tcx>,
21922192
) -> bool {
21932193
fn check_substs_compatible_inner<'tcx>(
@@ -2219,7 +2219,10 @@ fn check_substs_compatible<'tcx>(
22192219
true
22202220
}
22212221

2222-
check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
2222+
let generics = tcx.generics_of(assoc_item.def_id);
2223+
// Chop off any additional substs (RPITIT) substs
2224+
let substs = &substs[0..generics.count().min(substs.len())];
2225+
check_substs_compatible_inner(tcx, generics, substs)
22232226
}
22242227

22252228
fn confirm_impl_trait_in_trait_candidate<'tcx>(
@@ -2248,11 +2251,27 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
22482251
};
22492252
}
22502253

2251-
let impl_fn_def_id = leaf_def.item.def_id;
22522254
// Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
22532255
// since `data.substs` are the impl substs.
22542256
let impl_fn_substs =
22552257
obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
2258+
let impl_fn_substs = translate_substs(
2259+
selcx.infcx(),
2260+
obligation.param_env,
2261+
data.impl_def_id,
2262+
impl_fn_substs,
2263+
leaf_def.defining_node,
2264+
);
2265+
2266+
if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) {
2267+
let err = tcx.ty_error_with_message(
2268+
obligation.cause.span,
2269+
"impl method and trait method have different parameters",
2270+
);
2271+
return Progress { term: err.into(), obligations };
2272+
}
2273+
2274+
let impl_fn_def_id = leaf_def.item.def_id;
22562275

22572276
let cause = ObligationCause::new(
22582277
obligation.cause.span,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(return_position_impl_trait_in_trait)]
2+
#![allow(incomplete_features)]
3+
4+
struct U;
5+
6+
trait Foo {
7+
fn bar(&self) -> impl Sized;
8+
}
9+
10+
impl Foo for U {
11+
fn bar<T>(&self) {}
12+
//~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters
13+
}
14+
15+
fn main() {
16+
U.bar();
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
2+
--> $DIR/generics-mismatch.rs:11:12
3+
|
4+
LL | fn bar(&self) -> impl Sized;
5+
| - expected 0 type parameters
6+
...
7+
LL | fn bar<T>(&self) {}
8+
| ^ found 1 type parameter
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0049`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not.
2+
// But we fixed an ICE anyways.
3+
4+
#![feature(specialization)]
5+
#![feature(return_position_impl_trait_in_trait)]
6+
#![allow(incomplete_features)]
7+
8+
trait Foo {
9+
fn bar(&self) -> impl Sized;
10+
}
11+
12+
default impl<U> Foo for U
13+
where
14+
U: Copy,
15+
{
16+
fn bar(&self) -> U {
17+
//~^ ERROR method `bar` has an incompatible type for trait
18+
*self
19+
}
20+
}
21+
22+
impl Foo for i32 {}
23+
24+
fn main() {
25+
1i32.bar();
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0053]: method `bar` has an incompatible type for trait
2+
--> $DIR/specialization-broken.rs:16:22
3+
|
4+
LL | default impl<U> Foo for U
5+
| - this type parameter
6+
...
7+
LL | fn bar(&self) -> U {
8+
| ^
9+
| |
10+
| expected associated type, found type parameter `U`
11+
| help: change the output type to match the trait: `impl Sized`
12+
|
13+
note: type in trait
14+
--> $DIR/specialization-broken.rs:9:22
15+
|
16+
LL | fn bar(&self) -> impl Sized;
17+
| ^^^^^^^^^^
18+
= note: expected fn pointer `fn(&U) -> impl Sized`
19+
found fn pointer `fn(&U) -> U`
20+
21+
error: aborting due to previous error
22+
23+
For more information about this error, try `rustc --explain E0053`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// check-pass
2+
3+
#![feature(specialization)]
4+
#![feature(return_position_impl_trait_in_trait)]
5+
#![allow(incomplete_features)]
6+
7+
trait Foo {
8+
fn bar(&self) -> impl Sized;
9+
}
10+
11+
impl<U> Foo for U
12+
where
13+
U: Copy,
14+
{
15+
fn bar(&self) -> U {
16+
*self
17+
}
18+
}
19+
20+
impl Foo for i32 {}
21+
22+
fn main() {
23+
let _: i32 = 1i32.bar();
24+
}

0 commit comments

Comments
 (0)