Skip to content

Commit 5d58451

Browse files
authored
Rollup merge of #102488 - compiler-errors:gat-compatibility, r=oli-obk
Check generic argument compatibility when projecting assoc ty Fixes #102114
2 parents b9ff789 + ee713f3 commit 5d58451

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

compiler/rustc_trait_selection/src/traits/project.rs

+40-2
Original file line numberDiff line numberDiff line change
@@ -2146,10 +2146,10 @@ fn confirm_impl_candidate<'cx, 'tcx>(
21462146
} else {
21472147
ty.map_bound(|ty| ty.into())
21482148
};
2149-
if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
2149+
if !check_substs_compatible(tcx, &assoc_ty.item, substs) {
21502150
let err = tcx.ty_error_with_message(
21512151
obligation.cause.span,
2152-
"impl item and trait item have different parameter counts",
2152+
"impl item and trait item have different parameters",
21532153
);
21542154
Progress { term: err.into(), obligations: nested }
21552155
} else {
@@ -2158,6 +2158,44 @@ fn confirm_impl_candidate<'cx, 'tcx>(
21582158
}
21592159
}
21602160

2161+
// Verify that the trait item and its implementation have compatible substs lists
2162+
fn check_substs_compatible<'tcx>(
2163+
tcx: TyCtxt<'tcx>,
2164+
assoc_ty: &ty::AssocItem,
2165+
substs: ty::SubstsRef<'tcx>,
2166+
) -> bool {
2167+
fn check_substs_compatible_inner<'tcx>(
2168+
tcx: TyCtxt<'tcx>,
2169+
generics: &'tcx ty::Generics,
2170+
args: &'tcx [ty::GenericArg<'tcx>],
2171+
) -> bool {
2172+
if generics.count() != args.len() {
2173+
return false;
2174+
}
2175+
2176+
let (parent_args, own_args) = args.split_at(generics.parent_count);
2177+
2178+
if let Some(parent) = generics.parent
2179+
&& let parent_generics = tcx.generics_of(parent)
2180+
&& !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
2181+
return false;
2182+
}
2183+
2184+
for (param, arg) in std::iter::zip(&generics.params, own_args) {
2185+
match (&param.kind, arg.unpack()) {
2186+
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
2187+
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
2188+
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
2189+
_ => return false,
2190+
}
2191+
}
2192+
2193+
true
2194+
}
2195+
2196+
check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
2197+
}
2198+
21612199
fn confirm_impl_trait_in_trait_candidate<'tcx>(
21622200
selcx: &mut SelectionContext<'_, 'tcx>,
21632201
obligation: &ProjectionTyObligation<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait A {
2+
type B<'b>;
3+
fn a() -> Self::B<'static>;
4+
}
5+
6+
struct C;
7+
8+
struct Wrapper<T>(T);
9+
10+
impl A for C {
11+
type B<T> = Wrapper<T>;
12+
//~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters
13+
fn a() -> Self::B<'static> {}
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
2+
--> $DIR/issue-102114.rs:11:12
3+
|
4+
LL | type B<'b>;
5+
| -- expected 0 type parameters
6+
...
7+
LL | type B<T> = Wrapper<T>;
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`.

0 commit comments

Comments
 (0)