add implicit sized to impl Trait parameters

This commit is contained in:
Dawer 2021-06-10 16:57:58 +05:00
parent 72002b401d
commit 8f2a040d10
2 changed files with 44 additions and 25 deletions

View File

@ -996,6 +996,7 @@ pub(crate) fn generic_predicates_for_param_query(
let ctx = let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
let generics = generics(db.upcast(), param_id.parent); let generics = generics(db.upcast(), param_id.parent);
// TODO(iDawer): add implicitly sized clauses?
resolver resolver
.where_predicates_in_scope() .where_predicates_in_scope()
// we have to filter out all other predicates *first*, before attempting to lower them // we have to filter out all other predicates *first*, before attempting to lower them
@ -1036,7 +1037,7 @@ pub(crate) fn trait_environment_query(
traits_in_scope traits_in_scope
.push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id())); .push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id()));
} }
let program_clause: chalk_ir::ProgramClause<Interner> = pred.clone().cast(&Interner); let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
clauses.push(program_clause.into_from_env_clause(&Interner)); clauses.push(program_clause.into_from_env_clause(&Interner));
} }
} }
@ -1063,6 +1064,15 @@ pub(crate) fn trait_environment_query(
clauses.push(program_clause.into_from_env_clause(&Interner)); clauses.push(program_clause.into_from_env_clause(&Interner));
} }
let subst = generics(db.upcast(), def).type_params_subst(db);
let explicitly_unsized_tys = ctx.unsized_types.into_inner();
let implicitly_sized_clauses =
implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver).map(|pred| {
let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
program_clause.into_from_env_clause(&Interner)
});
clauses.extend(implicitly_sized_clauses);
let krate = def.module(db.upcast()).krate(); let krate = def.module(db.upcast()).krate();
let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses); let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses);
@ -1085,34 +1095,43 @@ pub(crate) fn generic_predicates_query(
.flat_map(|pred| ctx.lower_where_predicate(pred, false).map(|p| make_binders(&generics, p))) .flat_map(|pred| ctx.lower_where_predicate(pred, false).map(|p| make_binders(&generics, p)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. let subst = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
// Exception is Self of a trait.
let is_trait_def = matches!(def, GenericDefId::TraitId(..));
let explicitly_unsized_tys = ctx.unsized_types.into_inner(); let explicitly_unsized_tys = ctx.unsized_types.into_inner();
let subtsts = generics.bound_vars_subst(DebruijnIndex::INNERMOST); let implicitly_sized_predicates =
let generic_args = &subtsts.as_slice(&Interner)[is_trait_def as usize..]; implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
.map(|p| make_binders(&generics, crate::wrap_empty_binders(p)));
predicates.extend(implicitly_sized_predicates);
predicates.into()
}
/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
/// Exception is Self of a trait def.
fn implicitly_sized_clauses<'a>(
db: &dyn HirDatabase,
def: GenericDefId,
explicitly_unsized_tys: &'a FxHashSet<Ty>,
substitution: &'a Substitution,
resolver: &Resolver,
) -> impl Iterator<Item = WhereClause> + 'a {
let is_trait_def = matches!(def, GenericDefId::TraitId(..));
let generic_args = &substitution.as_slice(&Interner)[is_trait_def as usize..];
let sized_trait = resolver let sized_trait = resolver
.krate() .krate()
.and_then(|krate| db.lang_item(krate, "sized".into())) .and_then(|krate| db.lang_item(krate, "sized".into()))
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
let sized_predicates = sized_trait
.into_iter() sized_trait.into_iter().flat_map(move |sized_trait| {
.flat_map(|sized_trait| { let implicitly_sized_tys = generic_args
let implicitly_sized_tys = generic_args .iter()
.iter() .filter_map(|generic_arg| generic_arg.ty(&Interner))
.filter_map(|generic_arg| generic_arg.ty(&Interner)) .filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty));
.filter(|&self_ty| !explicitly_unsized_tys.contains(self_ty)); implicitly_sized_tys.map(move |self_ty| {
implicitly_sized_tys.map(move |self_ty| { WhereClause::Implemented(TraitRef {
WhereClause::Implemented(TraitRef { trait_id: sized_trait,
trait_id: sized_trait, substitution: Substitution::from1(&Interner, self_ty.clone()),
substitution: Substitution::from1(&Interner, self_ty.clone()),
})
}) })
}) })
.map(|p| make_binders(&generics, crate::wrap_empty_binders(p))); })
predicates.extend(sized_predicates);
predicates.into()
} }
/// Resolve the default type params from generics /// Resolve the default type params from generics

View File

@ -398,15 +398,15 @@ fn test() {
#[test] #[test]
fn coerce_unsize_apit() { fn coerce_unsize_apit() {
// FIXME: #8984
check( check(
r#" r#"
//- minicore: coerce_unsized //- minicore: coerce_unsized
trait Foo {} trait Foo {}
fn test(f: impl Foo) { fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
let _: &dyn Foo = &f; let _: &dyn Foo = &f;
//^^ expected &dyn Foo, got &impl Foo let _: &dyn Foo = g;
//^ expected &dyn Foo, got &impl Foo
} }
"#, "#,
); );