Skip to content

Commit c34a43e

Browse files
committed
Add and lower to ir::InlineBounds
1 parent d9ffab3 commit c34a43e

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
);
@@ -634,6 +635,107 @@ impl LowerTraitRef for TraitRef {
634635
}
635636
}
636637

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

0 commit comments

Comments
 (0)