Skip to content

Commit b301b04

Browse files
committed
Add const generics
1 parent 5e85158 commit b301b04

32 files changed

+1272
-527
lines changed

Cargo.lock

+8-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir/src/display.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ impl HirDisplay for TypeParam {
256256
}
257257

258258
let bounds = f.db.generic_predicates_for_param(self.id.parent(), self.id.into(), None);
259-
let substs = TyBuilder::type_params_subst(f.db, self.id.parent());
259+
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
260260
let predicates: Vec<_> =
261261
bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
262262
let krate = self.id.parent().krate(f.db).id;
@@ -292,8 +292,9 @@ impl HirDisplay for ConstParam {
292292
fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
293293
let params = f.db.generic_params(def);
294294
if params.lifetimes.is_empty()
295+
&& params.type_or_consts.iter().all(|x| x.1.const_param().is_none())
295296
&& params
296-
.tocs
297+
.type_or_consts
297298
.iter()
298299
.filter_map(|x| x.1.type_param())
299300
.all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
@@ -315,7 +316,7 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
315316
delim(f)?;
316317
write!(f, "{}", lifetime.name)?;
317318
}
318-
for (_, ty) in params.tocs.iter() {
319+
for (_, ty) in params.type_or_consts.iter() {
319320
if let Some(name) = &ty.name() {
320321
match ty {
321322
TypeOrConstParamData::TypeParamData(ty) => {
@@ -348,7 +349,9 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir
348349
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
349350
let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
350351
WherePredicateTypeTarget::TypeRef(_) => false,
351-
WherePredicateTypeTarget::TypeOrConstParam(id) => params.tocs[*id].name().is_none(),
352+
WherePredicateTypeTarget::TypeOrConstParam(id) => {
353+
params.type_or_consts[*id].name().is_none()
354+
}
352355
};
353356

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

365368
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
366369
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
367-
WherePredicateTypeTarget::TypeOrConstParam(id) => match &params.tocs[*id].name() {
368-
Some(name) => write!(f, "{}", name),
369-
None => write!(f, "{{unnamed}}"),
370-
},
370+
WherePredicateTypeTarget::TypeOrConstParam(id) => {
371+
match &params.type_or_consts[*id].name() {
372+
Some(name) => write!(f, "{}", name),
373+
None => write!(f, "{{unnamed}}"),
374+
}
375+
}
371376
};
372377

373378
write!(f, "\nwhere")?;

crates/hir/src/lib.rs

+50-18
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,19 @@ use hir_def::{
5555
use hir_expand::{name::name, MacroCallKind};
5656
use hir_ty::{
5757
autoderef,
58-
consteval::{eval_const, ComputedExpr, ConstEvalCtx, ConstEvalError, ConstExt},
58+
consteval::{
59+
eval_const, unknown_const_as_generic, ComputedExpr, ConstEvalCtx, ConstEvalError, ConstExt,
60+
},
5961
could_unify,
6062
diagnostics::BodyValidationDiagnostic,
6163
method_resolution::{self, TyFingerprint},
6264
primitive::UintTy,
6365
subst_prefix,
6466
traits::FnTrait,
6567
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
66-
DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution,
67-
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind,
68-
WhereClause,
68+
DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind, QuantifiedWhereClause,
69+
Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt,
70+
TyKind, TyVariableKind, WhereClause,
6971
};
7072
use itertools::Itertools;
7173
use nameres::diagnostics::DefDiagnosticKind;
@@ -796,7 +798,7 @@ impl Field {
796798
VariantDef::Union(it) => it.id.into(),
797799
VariantDef::Variant(it) => it.parent.id.into(),
798800
};
799-
let substs = TyBuilder::type_params_subst(db, generic_def_id);
801+
let substs = TyBuilder::placeholder_subst(db, generic_def_id);
800802
let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
801803
Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
802804
}
@@ -983,7 +985,10 @@ impl_from!(Struct, Union, Enum for Adt);
983985
impl Adt {
984986
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
985987
let subst = db.generic_defaults(self.into());
986-
subst.iter().any(|ty| ty.skip_binders().is_unknown())
988+
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
989+
GenericArgData::Ty(x) => x.is_unknown(),
990+
_ => false,
991+
})
987992
}
988993

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

16861694
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -2047,7 +2055,7 @@ impl_from!(
20472055
impl GenericDef {
20482056
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
20492057
let generics = db.generic_params(self.into());
2050-
let ty_params = generics.tocs.iter().map(|(local_id, _)| {
2058+
let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
20512059
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
20522060
match toc.split(db) {
20532061
Either::Left(x) => GenericParam::ConstParam(x),
@@ -2067,7 +2075,7 @@ impl GenericDef {
20672075
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
20682076
let generics = db.generic_params(self.into());
20692077
generics
2070-
.tocs
2078+
.type_or_consts
20712079
.iter()
20722080
.map(|(local_id, _)| TypeOrConstParam {
20732081
id: TypeOrConstParamId { parent: self.into(), local_id },
@@ -2351,9 +2359,14 @@ impl TypeParam {
23512359
let resolver = self.id.parent().resolver(db.upcast());
23522360
let krate = self.id.parent().module(db.upcast()).krate();
23532361
let ty = params.get(local_idx)?.clone();
2354-
let subst = TyBuilder::type_params_subst(db, self.id.parent());
2362+
let subst = TyBuilder::placeholder_subst(db, self.id.parent());
23552363
let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
2356-
Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
2364+
match ty.data(Interner) {
2365+
GenericArgData::Ty(x) => {
2366+
Some(Type::new_with_resolver_inner(db, krate, &resolver, x.clone()))
2367+
}
2368+
_ => None,
2369+
}
23572370
}
23582371
}
23592372

@@ -2389,7 +2402,7 @@ impl ConstParam {
23892402

23902403
pub fn name(self, db: &dyn HirDatabase) -> Name {
23912404
let params = db.generic_params(self.id.parent());
2392-
match params.tocs[self.id.local_id()].name() {
2405+
match params.type_or_consts[self.id.local_id()].name() {
23932406
Some(x) => x.clone(),
23942407
None => {
23952408
never!();
@@ -2421,7 +2434,7 @@ pub struct TypeOrConstParam {
24212434
impl TypeOrConstParam {
24222435
pub fn name(self, db: &dyn HirDatabase) -> Name {
24232436
let params = db.generic_params(self.id.parent);
2424-
match params.tocs[self.id.local_id].name() {
2437+
match params.type_or_consts[self.id.local_id].name() {
24252438
Some(n) => n.clone(),
24262439
_ => Name::missing(),
24272440
}
@@ -2437,12 +2450,12 @@ impl TypeOrConstParam {
24372450

24382451
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
24392452
let params = db.generic_params(self.id.parent);
2440-
match &params.tocs[self.id.local_id] {
2453+
match &params.type_or_consts[self.id.local_id] {
24412454
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
2442-
Either::Right(TypeParam { id: self.id.into() })
2455+
Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
24432456
}
24442457
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
2445-
Either::Left(ConstParam { id: self.id.into() })
2458+
Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
24462459
}
24472460
}
24482461
}
@@ -2688,9 +2701,19 @@ impl Type {
26882701
}
26892702

26902703
pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
2704+
let mut it = args.iter().map(|t| t.ty.clone());
26912705
let trait_ref = TyBuilder::trait_ref(db, trait_.id)
26922706
.push(self.ty.clone())
2693-
.fill(args.iter().map(|t| t.ty.clone()))
2707+
.fill(|x| {
2708+
let r = it.next().unwrap();
2709+
match x {
2710+
ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
2711+
ParamKind::Const(ty) => {
2712+
// FIXME: this code is not covered in tests.
2713+
unknown_const_as_generic(ty.clone())
2714+
}
2715+
}
2716+
})
26942717
.build();
26952718

26962719
let goal = Canonical {
@@ -2707,9 +2730,18 @@ impl Type {
27072730
args: &[Type],
27082731
alias: TypeAlias,
27092732
) -> Option<Type> {
2733+
let mut args = args.iter();
27102734
let projection = TyBuilder::assoc_type_projection(db, alias.id)
27112735
.push(self.ty.clone())
2712-
.fill(args.iter().map(|t| t.ty.clone()))
2736+
.fill(|x| {
2737+
// FIXME: this code is not covered in tests.
2738+
match x {
2739+
ParamKind::Type => {
2740+
GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
2741+
}
2742+
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
2743+
}
2744+
})
27132745
.build();
27142746
let goal = hir_ty::make_canonical(
27152747
InEnvironment::new(

crates/hir/src/semantics/source_to_def.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ impl SourceToDefCtx<'_, '_> {
279279
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
280280
let container: ChildContainer = self.find_generic_param_container(src.syntax())?.into();
281281
let dyn_map = self.cache_for(container, src.file_id);
282-
dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(|x| x.into())
282+
dyn_map[keys::TYPE_PARAM].get(&src.value).copied().map(|x| TypeParamId::from_unchecked(x))
283283
}
284284

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

303303
pub(super) fn generic_param_to_def(

0 commit comments

Comments
 (0)