Skip to content

Commit 20fa7cb

Browse files
bors[bot]HKalbasi
andauthored
Merge #11688
11688: Add const generics r=HKalbasi a=HKalbasi #7434 is not in this PR, so there is no evaluation of constants and no default const argument. But the rest (type inference and method resolution with chalk) should work. Chalk is pedantic about kind of generic arguments, and will panic in case of mixing type and const arguments. I tried to add test that, but I'm not sure if it covers all cases. Co-authored-by: hkalbasi <[email protected]>
2 parents 5e85158 + b301b04 commit 20fa7cb

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)