Skip to content

Commit d9242ff

Browse files
committed
When checking associated type bounds, use bound vars for GAT params in param_env
1 parent 9583fd1 commit d9242ff

File tree

3 files changed

+84
-12
lines changed

3 files changed

+84
-12
lines changed

compiler/rustc_middle/src/ty/subst.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
234234
})
235235
}
236236

237-
fn fill_item<F>(
237+
pub fn fill_item<F>(
238238
substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
239239
tcx: TyCtxt<'tcx>,
240240
defs: &ty::Generics,
@@ -249,7 +249,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
249249
Self::fill_single(substs, defs, mk_kind)
250250
}
251251

252-
fn fill_single<F>(
252+
pub fn fill_single<F>(
253253
substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
254254
defs: &ty::Generics,
255255
mk_kind: &mut F,

compiler/rustc_typeck/src/check/compare_method.rs

+67-10
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,7 @@ fn compare_type_predicate_entailment<'tcx>(
12251225
/// For default associated types the normalization is not possible (the value
12261226
/// from the impl could be overridden). We also can't normalize generic
12271227
/// associated types (yet) because they contain bound parameters.
1228+
#[tracing::instrument(level = "debug", skip(tcx))]
12281229
pub fn check_type_bounds<'tcx>(
12291230
tcx: TyCtxt<'tcx>,
12301231
trait_ty: &ty::AssocItem,
@@ -1238,10 +1239,57 @@ pub fn check_type_bounds<'tcx>(
12381239
// type Bar<C> =...
12391240
// }
12401241
//
1241-
// - `impl_substs` would be `[A, B, C]`
1242-
// - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from
1243-
// the *trait* with the generic associated type parameters.
1244-
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
1242+
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
1243+
// - `impl_ty_substs` would be `[A, B, ^0.0]`
1244+
// - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
1245+
// the *trait* with the generic associated type parameters (as bound vars).
1246+
let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id);
1247+
let mut substs = smallvec::SmallVec::with_capacity(defs.count());
1248+
if let Some(def_id) = defs.parent {
1249+
let parent_defs = tcx.generics_of(def_id);
1250+
InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| {
1251+
tcx.mk_param_from_def(param)
1252+
});
1253+
}
1254+
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
1255+
smallvec::SmallVec::with_capacity(defs.count());
1256+
InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
1257+
GenericParamDefKind::Type { .. } => {
1258+
let kind = ty::BoundTyKind::Param(param.name);
1259+
let bound_var = ty::BoundVariableKind::Ty(kind);
1260+
bound_vars.push(bound_var);
1261+
tcx.mk_ty(ty::Bound(
1262+
ty::INNERMOST,
1263+
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
1264+
))
1265+
.into()
1266+
}
1267+
GenericParamDefKind::Lifetime => {
1268+
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
1269+
let bound_var = ty::BoundVariableKind::Region(kind);
1270+
bound_vars.push(bound_var);
1271+
tcx.mk_region(ty::ReLateBound(
1272+
ty::INNERMOST,
1273+
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
1274+
))
1275+
.into()
1276+
}
1277+
GenericParamDefKind::Const { .. } => {
1278+
let bound_var = ty::BoundVariableKind::Const;
1279+
bound_vars.push(bound_var);
1280+
tcx.mk_const(ty::Const {
1281+
ty: tcx.type_of(param.def_id),
1282+
val: ty::ConstKind::Bound(
1283+
ty::INNERMOST,
1284+
ty::BoundVar::from_usize(bound_vars.len() - 1),
1285+
),
1286+
})
1287+
.into()
1288+
}
1289+
});
1290+
let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
1291+
let impl_ty_substs = tcx.intern_substs(&substs);
1292+
12451293
let rebased_substs =
12461294
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
12471295
let impl_ty_value = tcx.type_of(impl_ty.def_id);
@@ -1270,18 +1318,26 @@ pub fn check_type_bounds<'tcx>(
12701318
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
12711319
}
12721320
_ => predicates.push(
1273-
ty::Binder::dummy(ty::ProjectionPredicate {
1274-
projection_ty: ty::ProjectionTy {
1275-
item_def_id: trait_ty.def_id,
1276-
substs: rebased_substs,
1321+
ty::Binder::bind_with_vars(
1322+
ty::ProjectionPredicate {
1323+
projection_ty: ty::ProjectionTy {
1324+
item_def_id: trait_ty.def_id,
1325+
substs: rebased_substs,
1326+
},
1327+
ty: impl_ty_value,
12771328
},
1278-
ty: impl_ty_value,
1279-
})
1329+
bound_vars,
1330+
)
12801331
.to_predicate(tcx),
12811332
),
12821333
};
12831334
ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
12841335
};
1336+
debug!(?normalize_param_env);
1337+
1338+
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
1339+
let rebased_substs =
1340+
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
12851341

12861342
tcx.infer_ctxt().enter(move |infcx| {
12871343
let constness = impl_ty
@@ -1308,6 +1364,7 @@ pub fn check_type_bounds<'tcx>(
13081364
.explicit_item_bounds(trait_ty.def_id)
13091365
.iter()
13101366
.map(|&(bound, span)| {
1367+
debug!(?bound);
13111368
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
13121369
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
13131370

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
trait Family {
6+
type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
7+
}
8+
9+
struct I32;
10+
11+
impl Family for I32 {
12+
type Member<'a> = i32;
13+
}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)