Skip to content

Commit 0829960

Browse files
Merge #8327
8327: Move `Ty` creation methods out of `Ty` (Chalk move preparation) r=flodiebold a=flodiebold When we'll move to using `chalk_ir::Ty` (#8313), we won't be able to have our own inherent methods on `Ty` anymore, so we need to move the helpers elsewhere. This adds a `TyBuilder` that allows easily constructing `Ty` and related types (`TraitRef`, `ProjectionTy`, `Substitution`). It also replaces `SubstsBuilder`. `TyBuilder` can construct different things based on its type parameter; e.g. if it has an `AdtId`, we're constructing an ADT type, but if it has a `TraitId`, we're constructing a `TraitRef`. The common thing for all of them is that we need to build a `Substitution`, so the API stays the same for all of them except at the beginning and end. We also use `TyBuilder` to house various one-shot methods for constructing types, e.g. `TyBuilder::unit()`. Co-authored-by: Florian Diebold <[email protected]>
2 parents c9bcbf9 + cde3857 commit 0829960

File tree

20 files changed

+423
-373
lines changed

20 files changed

+423
-373
lines changed

crates/hir/src/display.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use syntax::ast::{self, NameOwner};
1313

1414
use crate::{
1515
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam,
16-
Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant,
16+
Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant,
1717
};
1818

1919
impl HirDisplay for Function {
@@ -234,7 +234,7 @@ impl HirDisplay for TypeParam {
234234
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
235235
write!(f, "{}", self.name(f.db))?;
236236
let bounds = f.db.generic_predicates_for_param(self.id);
237-
let substs = Substitution::type_params(f.db, self.id.parent);
237+
let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
238238
let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
239239
if !(predicates.is_empty() || f.omit_verbose_types()) {
240240
write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;

crates/hir/src/lib.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ use hir_ty::{
5555
autoderef, could_unify,
5656
method_resolution::{self, TyFingerprint},
5757
primitive::UintTy,
58-
to_assoc_type_id,
5958
traits::{FnTrait, Solution, SolutionVariables},
6059
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
61-
DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar,
62-
Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause,
60+
DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Substitution,
61+
TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, TyVariableKind, WhereClause,
6362
};
6463
use itertools::Itertools;
6564
use rustc_hash::FxHashSet;
@@ -515,7 +514,7 @@ impl Field {
515514
VariantDef::Union(it) => it.id.into(),
516515
VariantDef::Variant(it) => it.parent.id.into(),
517516
};
518-
let substs = Substitution::type_params(db, generic_def_id);
517+
let substs = TyBuilder::type_params_subst(db, generic_def_id);
519518
let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
520519
Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
521520
}
@@ -1129,7 +1128,7 @@ pub struct BuiltinType {
11291128
impl BuiltinType {
11301129
pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
11311130
let resolver = module.id.resolver(db.upcast());
1132-
Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner))
1131+
Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
11331132
.expect("crate not present in resolver")
11341133
}
11351134

@@ -1502,7 +1501,7 @@ impl TypeParam {
15021501
let resolver = self.id.parent.resolver(db.upcast());
15031502
let krate = self.id.parent.module(db.upcast()).krate();
15041503
let ty = params.get(local_idx)?.clone();
1505-
let subst = Substitution::type_params(db, self.id.parent);
1504+
let subst = TyBuilder::type_params_subst(db, self.id.parent);
15061505
let ty = ty.subst(&subst.prefix(local_idx));
15071506
Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
15081507
}
@@ -1703,10 +1702,9 @@ impl Type {
17031702
fn from_def(
17041703
db: &dyn HirDatabase,
17051704
krate: CrateId,
1706-
def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>,
1705+
def: impl HasResolver + Into<TyDefId>,
17071706
) -> Type {
1708-
let substs = Substitution::build_for_def(db, def).fill_with_unknown().build();
1709-
let ty = db.ty(def.into()).subst(&substs);
1707+
let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
17101708
Type::new(db, krate, def, ty)
17111709
}
17121710

@@ -1785,13 +1783,10 @@ impl Type {
17851783
}
17861784

17871785
pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1788-
let trait_ref = hir_ty::TraitRef {
1789-
trait_id: hir_ty::to_chalk_trait_id(trait_.id),
1790-
substitution: Substitution::build_for_def(db, trait_.id)
1791-
.push(self.ty.clone())
1792-
.fill(args.iter().map(|t| t.ty.clone()))
1793-
.build(),
1794-
};
1786+
let trait_ref = TyBuilder::trait_ref(db, trait_.id)
1787+
.push(self.ty.clone())
1788+
.fill(args.iter().map(|t| t.ty.clone()))
1789+
.build();
17951790

17961791
let goal = Canonical {
17971792
value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
@@ -1804,22 +1799,18 @@ impl Type {
18041799
pub fn normalize_trait_assoc_type(
18051800
&self,
18061801
db: &dyn HirDatabase,
1807-
trait_: Trait,
18081802
args: &[Type],
18091803
alias: TypeAlias,
18101804
) -> Option<Type> {
1811-
let subst = Substitution::build_for_def(db, trait_.id)
1805+
let projection = TyBuilder::assoc_type_projection(db, alias.id)
18121806
.push(self.ty.clone())
18131807
.fill(args.iter().map(|t| t.ty.clone()))
18141808
.build();
18151809
let goal = Canonical::new(
18161810
InEnvironment::new(
18171811
self.env.env.clone(),
18181812
AliasEq {
1819-
alias: AliasTy::Projection(ProjectionTy {
1820-
associated_ty_id: to_assoc_type_id(alias.id),
1821-
substitution: subst,
1822-
}),
1813+
alias: AliasTy::Projection(projection),
18231814
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
18241815
.intern(&Interner),
18251816
}

crates/hir_ty/src/autoderef.rs

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ use log::{info, warn};
1313

1414
use crate::{
1515
db::HirDatabase,
16-
to_assoc_type_id, to_chalk_trait_id,
1716
traits::{InEnvironment, Solution},
18-
utils::generics,
19-
AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20-
ProjectionTy, Substitution, TraitRef, Ty, TyKind,
17+
AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty,
18+
TyBuilder, TyKind,
2119
};
2220

2321
const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -57,21 +55,20 @@ fn deref_by_trait(
5755
};
5856
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
5957

60-
let generic_params = generics(db.upcast(), target.into());
61-
if generic_params.len() != 1 {
62-
// the Target type + Deref trait should only have one generic parameter,
63-
// namely Deref's Self type
64-
return None;
65-
}
58+
let projection = {
59+
let b = TyBuilder::assoc_type_projection(db, target);
60+
if b.remaining() != 1 {
61+
// the Target type + Deref trait should only have one generic parameter,
62+
// namely Deref's Self type
63+
return None;
64+
}
65+
b.push(ty.goal.value.clone()).build()
66+
};
6667

6768
// FIXME make the Canonical / bound var handling nicer
6869

69-
let parameters =
70-
Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71-
7270
// Check that the type implements Deref at all
73-
let trait_ref =
74-
TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
71+
let trait_ref = projection.trait_ref(db);
7572
let implements_goal = Canonical {
7673
binders: ty.goal.binders.clone(),
7774
value: InEnvironment {
@@ -84,21 +81,16 @@ fn deref_by_trait(
8481
}
8582

8683
// Now do the assoc type projection
87-
let projection = AliasEq {
88-
alias: AliasTy::Projection(ProjectionTy {
89-
associated_ty_id: to_assoc_type_id(target),
90-
substitution: parameters,
91-
}),
84+
let alias_eq = AliasEq {
85+
alias: AliasTy::Projection(projection),
9286
ty: TyKind::BoundVar(BoundVar::new(
9387
DebruijnIndex::INNERMOST,
9488
ty.goal.binders.len(&Interner),
9589
))
9690
.intern(&Interner),
9791
};
9892

99-
let obligation = projection.cast(&Interner);
100-
101-
let in_env = InEnvironment { goal: obligation, environment: ty.environment };
93+
let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
10294

10395
let canonical = Canonical {
10496
value: in_env,

0 commit comments

Comments
 (0)