Skip to content

Commit 8f2a040

Browse files
committed
add implicit sized to impl Trait parameters
1 parent 72002b4 commit 8f2a040

File tree

2 files changed

+44
-25
lines changed

2 files changed

+44
-25
lines changed

crates/hir_ty/src/lower.rs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ pub(crate) fn generic_predicates_for_param_query(
996996
let ctx =
997997
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
998998
let generics = generics(db.upcast(), param_id.parent);
999+
// TODO(iDawer): add implicitly sized clauses?
9991000
resolver
10001001
.where_predicates_in_scope()
10011002
// we have to filter out all other predicates *first*, before attempting to lower them
@@ -1036,7 +1037,7 @@ pub(crate) fn trait_environment_query(
10361037
traits_in_scope
10371038
.push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id()));
10381039
}
1039-
let program_clause: chalk_ir::ProgramClause<Interner> = pred.clone().cast(&Interner);
1040+
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
10401041
clauses.push(program_clause.into_from_env_clause(&Interner));
10411042
}
10421043
}
@@ -1063,6 +1064,15 @@ pub(crate) fn trait_environment_query(
10631064
clauses.push(program_clause.into_from_env_clause(&Interner));
10641065
}
10651066

1067+
let subst = generics(db.upcast(), def).type_params_subst(db);
1068+
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
1069+
let implicitly_sized_clauses =
1070+
implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver).map(|pred| {
1071+
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
1072+
program_clause.into_from_env_clause(&Interner)
1073+
});
1074+
clauses.extend(implicitly_sized_clauses);
1075+
10661076
let krate = def.module(db.upcast()).krate();
10671077

10681078
let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses);
@@ -1085,34 +1095,43 @@ pub(crate) fn generic_predicates_query(
10851095
.flat_map(|pred| ctx.lower_where_predicate(pred, false).map(|p| make_binders(&generics, p)))
10861096
.collect::<Vec<_>>();
10871097

1088-
// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
1089-
// Exception is Self of a trait.
1090-
let is_trait_def = matches!(def, GenericDefId::TraitId(..));
1098+
let subst = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
10911099
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
1092-
let subtsts = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1093-
let generic_args = &subtsts.as_slice(&Interner)[is_trait_def as usize..];
1100+
let implicitly_sized_predicates =
1101+
implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
1102+
.map(|p| make_binders(&generics, crate::wrap_empty_binders(p)));
1103+
predicates.extend(implicitly_sized_predicates);
1104+
predicates.into()
1105+
}
1106+
1107+
/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
1108+
/// Exception is Self of a trait def.
1109+
fn implicitly_sized_clauses<'a>(
1110+
db: &dyn HirDatabase,
1111+
def: GenericDefId,
1112+
explicitly_unsized_tys: &'a FxHashSet<Ty>,
1113+
substitution: &'a Substitution,
1114+
resolver: &Resolver,
1115+
) -> impl Iterator<Item = WhereClause> + 'a {
1116+
let is_trait_def = matches!(def, GenericDefId::TraitId(..));
1117+
let generic_args = &substitution.as_slice(&Interner)[is_trait_def as usize..];
10941118
let sized_trait = resolver
10951119
.krate()
10961120
.and_then(|krate| db.lang_item(krate, "sized".into()))
10971121
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
1098-
let sized_predicates = sized_trait
1099-
.into_iter()
1100-
.flat_map(|sized_trait| {
1101-
let implicitly_sized_tys = generic_args
1102-
.iter()
1103-
.filter_map(|generic_arg| generic_arg.ty(&Interner))
1104-
.filter(|&self_ty| !explicitly_unsized_tys.contains(self_ty));
1105-
implicitly_sized_tys.map(move |self_ty| {
1106-
WhereClause::Implemented(TraitRef {
1107-
trait_id: sized_trait,
1108-
substitution: Substitution::from1(&Interner, self_ty.clone()),
1109-
})
1122+
1123+
sized_trait.into_iter().flat_map(move |sized_trait| {
1124+
let implicitly_sized_tys = generic_args
1125+
.iter()
1126+
.filter_map(|generic_arg| generic_arg.ty(&Interner))
1127+
.filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty));
1128+
implicitly_sized_tys.map(move |self_ty| {
1129+
WhereClause::Implemented(TraitRef {
1130+
trait_id: sized_trait,
1131+
substitution: Substitution::from1(&Interner, self_ty.clone()),
11101132
})
11111133
})
1112-
.map(|p| make_binders(&generics, crate::wrap_empty_binders(p)));
1113-
1114-
predicates.extend(sized_predicates);
1115-
predicates.into()
1134+
})
11161135
}
11171136

11181137
/// Resolve the default type params from generics

crates/hir_ty/src/tests/coercion.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,15 @@ fn test() {
398398

399399
#[test]
400400
fn coerce_unsize_apit() {
401-
// FIXME: #8984
402401
check(
403402
r#"
404403
//- minicore: coerce_unsized
405404
trait Foo {}
406405
407-
fn test(f: impl Foo) {
406+
fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
408407
let _: &dyn Foo = &f;
409-
//^^ expected &dyn Foo, got &impl Foo
408+
let _: &dyn Foo = g;
409+
//^ expected &dyn Foo, got &impl Foo
410410
}
411411
"#,
412412
);

0 commit comments

Comments
 (0)