Skip to content

Add const generics #11688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 13 additions & 8 deletions crates/hir/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl HirDisplay for TypeParam {
}

let bounds = f.db.generic_predicates_for_param(self.id.parent(), self.id.into(), None);
let substs = TyBuilder::type_params_subst(f.db, self.id.parent());
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
let predicates: Vec<_> =
bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
let krate = self.id.parent().krate(f.db).id;
Expand Down Expand Up @@ -292,8 +292,9 @@ impl HirDisplay for ConstParam {
fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
let params = f.db.generic_params(def);
if params.lifetimes.is_empty()
&& params.type_or_consts.iter().all(|x| x.1.const_param().is_none())
&& params
.tocs
.type_or_consts
.iter()
.filter_map(|x| x.1.type_param())
.all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
Expand All @@ -315,7 +316,7 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
delim(f)?;
write!(f, "{}", lifetime.name)?;
}
for (_, ty) in params.tocs.iter() {
for (_, ty) in params.type_or_consts.iter() {
if let Some(name) = &ty.name() {
match ty {
TypeOrConstParamData::TypeParamData(ty) => {
Expand Down Expand Up @@ -348,7 +349,9 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
WherePredicateTypeTarget::TypeRef(_) => false,
WherePredicateTypeTarget::TypeOrConstParam(id) => params.tocs[*id].name().is_none(),
WherePredicateTypeTarget::TypeOrConstParam(id) => {
params.type_or_consts[*id].name().is_none()
}
};

let has_displayable_predicate = params
Expand All @@ -364,10 +367,12 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir

let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
WherePredicateTypeTarget::TypeOrConstParam(id) => match &params.tocs[*id].name() {
Some(name) => write!(f, "{}", name),
None => write!(f, "{{unnamed}}"),
},
WherePredicateTypeTarget::TypeOrConstParam(id) => {
match &params.type_or_consts[*id].name() {
Some(name) => write!(f, "{}", name),
None => write!(f, "{{unnamed}}"),
}
}
};

write!(f, "\nwhere")?;
Expand Down
68 changes: 50 additions & 18 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,19 @@ use hir_def::{
use hir_expand::{name::name, MacroCallKind};
use hir_ty::{
autoderef,
consteval::{eval_const, ComputedExpr, ConstEvalCtx, ConstEvalError, ConstExt},
consteval::{
eval_const, unknown_const_as_generic, ComputedExpr, ConstEvalCtx, ConstEvalError, ConstExt,
},
could_unify,
diagnostics::BodyValidationDiagnostic,
method_resolution::{self, TyFingerprint},
primitive::UintTy,
subst_prefix,
traits::FnTrait,
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution,
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind,
WhereClause,
DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind, QuantifiedWhereClause,
Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt,
TyKind, TyVariableKind, WhereClause,
};
use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
Expand Down Expand Up @@ -796,7 +798,7 @@ impl Field {
VariantDef::Union(it) => it.id.into(),
VariantDef::Variant(it) => it.parent.id.into(),
};
let substs = TyBuilder::type_params_subst(db, generic_def_id);
let substs = TyBuilder::placeholder_subst(db, generic_def_id);
let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
}
Expand Down Expand Up @@ -983,7 +985,10 @@ impl_from!(Struct, Union, Enum for Adt);
impl Adt {
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
let subst = db.generic_defaults(self.into());
subst.iter().any(|ty| ty.skip_binders().is_unknown())
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
GenericArgData::Ty(x) => x.is_unknown(),
_ => false,
})
}

/// Turns this ADT into a type. Any type parameters of the ADT will be
Expand Down Expand Up @@ -1680,7 +1685,10 @@ pub struct TypeAlias {
impl TypeAlias {
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
let subst = db.generic_defaults(self.id.into());
subst.iter().any(|ty| ty.skip_binders().is_unknown())
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
GenericArgData::Ty(x) => x.is_unknown(),
_ => false,
})
}

pub fn module(self, db: &dyn HirDatabase) -> Module {
Expand Down Expand Up @@ -2047,7 +2055,7 @@ impl_from!(
impl GenericDef {
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
let generics = db.generic_params(self.into());
let ty_params = generics.tocs.iter().map(|(local_id, _)| {
let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
match toc.split(db) {
Either::Left(x) => GenericParam::ConstParam(x),
Expand All @@ -2067,7 +2075,7 @@ impl GenericDef {
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
let generics = db.generic_params(self.into());
generics
.tocs
.type_or_consts
.iter()
.map(|(local_id, _)| TypeOrConstParam {
id: TypeOrConstParamId { parent: self.into(), local_id },
Expand Down Expand Up @@ -2351,9 +2359,14 @@ impl TypeParam {
let resolver = self.id.parent().resolver(db.upcast());
let krate = self.id.parent().module(db.upcast()).krate();
let ty = params.get(local_idx)?.clone();
let subst = TyBuilder::type_params_subst(db, self.id.parent());
let subst = TyBuilder::placeholder_subst(db, self.id.parent());
let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
match ty.data(Interner) {
GenericArgData::Ty(x) => {
Some(Type::new_with_resolver_inner(db, krate, &resolver, x.clone()))
}
_ => None,
}
}
}

Expand Down Expand Up @@ -2389,7 +2402,7 @@ impl ConstParam {

pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent());
match params.tocs[self.id.local_id()].name() {
match params.type_or_consts[self.id.local_id()].name() {
Some(x) => x.clone(),
None => {
never!();
Expand Down Expand Up @@ -2421,7 +2434,7 @@ pub struct TypeOrConstParam {
impl TypeOrConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent);
match params.tocs[self.id.local_id].name() {
match params.type_or_consts[self.id.local_id].name() {
Some(n) => n.clone(),
_ => Name::missing(),
}
Expand All @@ -2437,12 +2450,12 @@ impl TypeOrConstParam {

pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
let params = db.generic_params(self.id.parent);
match &params.tocs[self.id.local_id] {
match &params.type_or_consts[self.id.local_id] {
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
Either::Right(TypeParam { id: self.id.into() })
Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
}
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
Either::Left(ConstParam { id: self.id.into() })
Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
}
}
}
Expand Down Expand Up @@ -2688,9 +2701,19 @@ impl Type {
}

pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
let mut it = args.iter().map(|t| t.ty.clone());
let trait_ref = TyBuilder::trait_ref(db, trait_.id)
.push(self.ty.clone())
.fill(args.iter().map(|t| t.ty.clone()))
.fill(|x| {
let r = it.next().unwrap();
match x {
ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
ParamKind::Const(ty) => {
// FIXME: this code is not covered in tests.
unknown_const_as_generic(ty.clone())
}
}
})
.build();

let goal = Canonical {
Expand All @@ -2707,9 +2730,18 @@ impl Type {
args: &[Type],
alias: TypeAlias,
) -> Option<Type> {
let mut args = args.iter();
let projection = TyBuilder::assoc_type_projection(db, alias.id)
.push(self.ty.clone())
.fill(args.iter().map(|t| t.ty.clone()))
.fill(|x| {
// FIXME: this code is not covered in tests.
match x {
ParamKind::Type => {
GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
}
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
}
})
.build();
let goal = hir_ty::make_canonical(
InEnvironment::new(
Expand Down
4 changes: 2 additions & 2 deletions crates/hir/src/semantics/source_to_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
let dyn_map = self.cache_for(container, src.file_id);
dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(|x| x.into())
dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(|x| TypeParamId::from_unchecked(x))
}

pub(super) fn lifetime_param_to_def(
Expand All @@ -297,7 +297,7 @@ impl SourceToDefCtx<'_, '_> {
) -> Option<ConstParamId> {
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
let dyn_map = self.cache_for(container, src.file_id);
dyn_map[keys::CONST_PARAM].get(&src.value).copied().map(|x| x.into())
dyn_map[keys::CONST_PARAM].get(&src.value).copied().map(|x| ConstParamId::from_unchecked(x))
}

pub(super) fn generic_param_to_def(
Expand Down
Loading