Properly remap and check for substs compatibility in `confirm_impl_trait_in_trait_candidate`
Fixes #103824
(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) {
// 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>(
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>(
};
}
- 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,
--- /dev/null
+#![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();
+}
--- /dev/null
+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`.
--- /dev/null
+// 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();
+}
--- /dev/null
+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`.
--- /dev/null
+// 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();
+}