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
This commit is contained in:
Manish Goregaokar 2022-11-08 21:03:54 -05:00 committed by GitHub
commit 6c021cf07d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 127 additions and 4 deletions

View File

@ -430,7 +430,9 @@ pub fn note_and_explain_type_err(
(ty::Projection(_), ty::Projection(_)) => {
diag.note("an associated type was expected, but a different one was found");
}
(ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => {
(ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
{
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
if !sp.contains(p_span) {

View File

@ -2187,7 +2187,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
// Verify that the trait item and its implementation have compatible substs lists
fn check_substs_compatible<'tcx>(
tcx: TyCtxt<'tcx>,
assoc_ty: &ty::AssocItem,
assoc_item: &ty::AssocItem,
substs: ty::SubstsRef<'tcx>,
) -> bool {
fn check_substs_compatible_inner<'tcx>(
@ -2219,7 +2219,10 @@ fn check_substs_compatible_inner<'tcx>(
true
}
check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
let generics = tcx.generics_of(assoc_item.def_id);
// Chop off any additional substs (RPITIT) substs
let substs = &substs[0..generics.count().min(substs.len())];
check_substs_compatible_inner(tcx, generics, substs)
}
fn confirm_impl_trait_in_trait_candidate<'tcx>(
@ -2248,11 +2251,27 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
};
}
let impl_fn_def_id = leaf_def.item.def_id;
// Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
// since `data.substs` are the impl substs.
let impl_fn_substs =
obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
let impl_fn_substs = translate_substs(
selcx.infcx(),
obligation.param_env,
data.impl_def_id,
impl_fn_substs,
leaf_def.defining_node,
);
if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) {
let err = tcx.ty_error_with_message(
obligation.cause.span,
"impl method and trait method have different parameters",
);
return Progress { term: err.into(), obligations };
}
let impl_fn_def_id = leaf_def.item.def_id;
let cause = ObligationCause::new(
obligation.cause.span,

View File

@ -0,0 +1,17 @@
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
struct U;
trait Foo {
fn bar(&self) -> impl Sized;
}
impl Foo for U {
fn bar<T>(&self) {}
//~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters
}
fn main() {
U.bar();
}

View File

@ -0,0 +1,12 @@
error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/generics-mismatch.rs:11:12
|
LL | fn bar(&self) -> impl Sized;
| - expected 0 type parameters
...
LL | fn bar<T>(&self) {}
| ^ found 1 type parameter
error: aborting due to previous error
For more information about this error, try `rustc --explain E0049`.

View File

@ -0,0 +1,26 @@
// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not.
// But we fixed an ICE anyways.
#![feature(specialization)]
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
trait Foo {
fn bar(&self) -> impl Sized;
}
default impl<U> Foo for U
where
U: Copy,
{
fn bar(&self) -> U {
//~^ ERROR method `bar` has an incompatible type for trait
*self
}
}
impl Foo for i32 {}
fn main() {
1i32.bar();
}

View File

@ -0,0 +1,23 @@
error[E0053]: method `bar` has an incompatible type for trait
--> $DIR/specialization-broken.rs:16:22
|
LL | default impl<U> Foo for U
| - this type parameter
...
LL | fn bar(&self) -> U {
| ^
| |
| expected associated type, found type parameter `U`
| help: change the output type to match the trait: `impl Sized`
|
note: type in trait
--> $DIR/specialization-broken.rs:9:22
|
LL | fn bar(&self) -> impl Sized;
| ^^^^^^^^^^
= note: expected fn pointer `fn(&U) -> impl Sized`
found fn pointer `fn(&U) -> U`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0053`.

View File

@ -0,0 +1,24 @@
// check-pass
#![feature(specialization)]
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
trait Foo {
fn bar(&self) -> impl Sized;
}
impl<U> Foo for U
where
U: Copy,
{
fn bar(&self) -> U {
*self
}
}
impl Foo for i32 {}
fn main() {
let _: i32 = 1i32.bar();
}