Skip to content

Commit d109ff0

Browse files
committed
Add and lower to ir::InlineBounds
1 parent c29c033 commit d109ff0

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

src/ir.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,32 @@ pub struct TraitFlags {
258258
pub deref: bool,
259259
}
260260

261+
/// An inline bound, e.g. `: Foo<K>` in `impl<K, T: Foo<K>> SomeType<T>`.
262+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
263+
pub enum InlineBound {
264+
TraitBound(TraitBound),
265+
ProjectionEqBound(ProjectionEqBound),
266+
}
267+
268+
/// Represents a trait bound on e.g. a type or type parameter.
269+
/// Does not know anything about what it's binding.
270+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
271+
pub struct TraitBound {
272+
crate trait_id: ItemId,
273+
crate args_no_self: Vec<Parameter>,
274+
}
275+
276+
/// Represents a projection equality bound on e.g. a type or type parameter.
277+
/// Does not know anything about what it's binding.
278+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
279+
pub struct ProjectionEqBound {
280+
crate trait_bound: TraitBound,
281+
crate associated_ty_id: ItemId,
282+
/// Does not include trait parameters.
283+
crate parameters: Vec<Parameter>,
284+
crate value: Ty,
285+
}
286+
261287
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
262288
pub struct AssociatedTyDatum {
263289
/// The trait this associated type is defined in.
@@ -273,7 +299,11 @@ pub struct AssociatedTyDatum {
273299
/// but possibly including more.
274300
crate parameter_kinds: Vec<ParameterKind<Identifier>>,
275301

276-
// FIXME: inline bounds on the associated ty need to be implemented
302+
/// Bounds on the associated type itself.
303+
///
304+
/// These must be proven by the implementer, for all possible parameters that
305+
/// would result in a well-formed projection.
306+
crate bounds: Vec<InlineBound>,
277307

278308
/// Where clauses that must hold for the projection be well-formed.
279309
crate where_clauses: Vec<QuantifiedDomainGoal>,

src/ir/lowering.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ impl LowerProgram for Program {
191191
id: info.id,
192192
name: defn.name.str,
193193
parameter_kinds: parameter_kinds,
194+
bounds: defn.bounds.lower(&env)?,
194195
where_clauses: defn.where_clauses.lower(&env)?,
195196
},
196197
);
@@ -638,6 +639,107 @@ impl LowerTraitRef for TraitRef {
638639
}
639640
}
640641

642+
trait LowerTraitBound {
643+
fn lower_trait_bound(&self, env: &Env) -> Result<ir::TraitBound>;
644+
}
645+
646+
impl LowerTraitBound for TraitBound {
647+
fn lower_trait_bound(&self, env: &Env) -> Result<ir::TraitBound> {
648+
let id = match env.lookup(self.trait_name)? {
649+
NameLookup::Type(id) => id,
650+
NameLookup::Parameter(_) => bail!(ErrorKind::NotTrait(self.trait_name)),
651+
};
652+
653+
let k = env.type_kind(id);
654+
if k.sort != ir::TypeSort::Trait {
655+
bail!(ErrorKind::NotTrait(self.trait_name));
656+
}
657+
658+
let parameters = self.args_no_self
659+
.iter()
660+
.map(|a| Ok(a.lower(env)?))
661+
.collect::<Result<Vec<_>>>()?;
662+
663+
if parameters.len() != k.binders.len() {
664+
bail!(
665+
"wrong number of parameters, expected `{:?}`, got `{:?}`",
666+
k.binders.len(),
667+
parameters.len()
668+
)
669+
}
670+
671+
for (binder, param) in k.binders.binders.iter().zip(parameters.iter()) {
672+
check_type_kinds("incorrect kind for trait parameter", binder, param)?;
673+
}
674+
675+
Ok(ir::TraitBound {
676+
trait_id: id,
677+
args_no_self: parameters,
678+
})
679+
}
680+
}
681+
682+
trait LowerInlineBound {
683+
fn lower(&self, env: &Env) -> Result<ir::InlineBound>;
684+
}
685+
686+
impl LowerInlineBound for TraitBound {
687+
fn lower(&self, env: &Env) -> Result<ir::InlineBound> {
688+
Ok(ir::InlineBound::TraitBound(self.lower_trait_bound(&env)?))
689+
}
690+
}
691+
692+
impl LowerInlineBound for ProjectionEqBound {
693+
fn lower(&self, env: &Env) -> Result<ir::InlineBound> {
694+
let trait_bound = self.trait_bound.lower_trait_bound(env)?;
695+
let info = match env.associated_ty_infos.get(&(trait_bound.trait_id, self.name.str)) {
696+
Some(info) => info,
697+
None => bail!("no associated type `{}` defined in trait", self.name.str),
698+
};
699+
let args: Vec<_> = try!(self.args.iter().map(|a| a.lower(env)).collect());
700+
701+
if args.len() != info.addl_parameter_kinds.len() {
702+
bail!(
703+
"wrong number of parameters for associated type (expected {}, got {})",
704+
info.addl_parameter_kinds.len(),
705+
args.len()
706+
)
707+
}
708+
709+
for (param, arg) in info.addl_parameter_kinds.iter().zip(args.iter()) {
710+
check_type_kinds("incorrect kind for associated type parameter", param, arg)?;
711+
}
712+
713+
Ok(ir::InlineBound::ProjectionEqBound(ir::ProjectionEqBound {
714+
trait_bound,
715+
associated_ty_id: info.id,
716+
parameters: args,
717+
value: self.value.lower(env)?,
718+
}))
719+
}
720+
}
721+
722+
impl LowerInlineBound for InlineBound {
723+
fn lower(&self, env: &Env) -> Result<ir::InlineBound> {
724+
match self {
725+
InlineBound::TraitBound(b) => b.lower(&env),
726+
InlineBound::ProjectionEqBound(b) => b.lower(&env),
727+
}
728+
}
729+
}
730+
731+
trait LowerInlineBounds {
732+
fn lower(&self, env: &Env) -> Result<Vec<ir::InlineBound>>;
733+
}
734+
735+
impl LowerInlineBounds for Vec<InlineBound> {
736+
fn lower(&self, env: &Env) -> Result<Vec<ir::InlineBound>> {
737+
self.iter()
738+
.map(|b| b.lower(env))
739+
.collect()
740+
}
741+
}
742+
641743
trait LowerPolarizedTraitRef {
642744
fn lower(&self, env: &Env) -> Result<ir::PolarizedTraitRef>;
643745
}

0 commit comments

Comments
 (0)