Skip to content

Commit

Permalink
fix record labels in the face of bound variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Westerlind committed Feb 21, 2022
1 parent 848ab34 commit 794a801
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
4 changes: 3 additions & 1 deletion libflux/flux-core/src/semantic/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ fn add_record_to_map(
env.insert(
match &head.k {
RecordLabel::Concrete(s) => s.clone().into(),
RecordLabel::Variable(_) => bail!("Record contains variable labels"),
RecordLabel::BoundVariable(_) | RecordLabel::Variable(_) => {
bail!("Record contains variable labels")
}
},
PolyType {
vars: new_vars,
Expand Down
2 changes: 1 addition & 1 deletion libflux/flux-core/src/semantic/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ impl<'a> Converter<'a> {
.entry(prop.name.name.clone())
.or_insert_with(|| self.sub.fresh())
.clone();
tvar.into()
types::RecordLabel::BoundVariable(tvar)
} else {
types::Label::from(self.symbols.lookup(&prop.name.name)).into()
},
Expand Down
2 changes: 1 addition & 1 deletion libflux/flux-core/src/semantic/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1846,7 +1846,7 @@ impl IdentifierExpr {
fn infer(&mut self, infer: &mut InferState<'_, '_>) -> Result {
let poly = infer.lookup(&self.loc, &self.name);

let (t, cons) = infer::instantiate(poly, infer.sub, self.loc.clone());
let (t, cons) = infer::instantiate(poly.clone(), infer.sub, self.loc.clone());
infer.solve(&cons);
self.typ = t;
Ok(())
Expand Down
32 changes: 24 additions & 8 deletions libflux/flux-core/src/semantic/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ impl Record {
let has_variable_label = |r: &Record| {
r.fields().any(|prop| match prop.k {
RecordLabel::Variable(v) => unifier.sub.try_apply(v).is_none(),
RecordLabel::Concrete(_) => false,
RecordLabel::BoundVariable(_) | RecordLabel::Concrete(_) => false,
})
};
if has_variable_label(self) || has_variable_label(actual) {
Expand Down Expand Up @@ -1450,22 +1450,39 @@ fn unify_in_context<T>(
}

/// Labels in records that are allowed be variables
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Serialize, derive_more::From)]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Serialize)]
pub enum RecordLabel {
/// A variable label
Variable(Tvar),
/// A variable label
BoundVariable(Tvar),
/// A concrete label
Concrete(Label),
}

impl From<Label> for RecordLabel {
fn from(label: Label) -> Self {
Self::Concrete(label)
}
}

impl Substitutable for RecordLabel {
fn walk(&self, sub: &dyn Substituter) -> Option<Self> {
match self {
Self::Variable(tvr) => sub.try_apply(*tvr).and_then(|new| match new {
MonoType::Label(l) => Some(Self::Concrete(l)),
MonoType::BoundVar(l) => Some(Self::BoundVariable(l)),
MonoType::Var(l) => Some(Self::Variable(l)),
_ => None,
}),

Self::BoundVariable(tvr) => sub.try_apply_bound(*tvr).and_then(|new| match new {
MonoType::Label(l) => Some(Self::Concrete(l)),
MonoType::BoundVar(l) => Some(Self::BoundVariable(l)),
MonoType::Var(l) => Some(Self::Variable(l)),
_ => None,
}),

Self::Concrete(_) => None,
}
}
Expand All @@ -1474,7 +1491,8 @@ impl Substitutable for RecordLabel {
impl fmt::Display for RecordLabel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Variable(v) => v.fmt(f),
Self::BoundVariable(v) => v.fmt(f),
Self::Variable(v) => write!(f, "#{}", v),
Self::Concrete(v) => v.fmt(f),
}
}
Expand All @@ -1483,7 +1501,7 @@ impl fmt::Display for RecordLabel {
impl PartialEq<str> for RecordLabel {
fn eq(&self, other: &str) -> bool {
match self {
Self::Variable(_) => false,
Self::BoundVariable(_) | Self::Variable(_) => false,
Self::Concrete(l) => l == other,
}
}
Expand Down Expand Up @@ -1630,10 +1648,8 @@ where
V: Substitutable + Clone,
{
fn walk(&self, sub: &dyn Substituter) -> Option<Self> {
self.v.visit(sub).map(|v| Property {
k: self.k.clone(),
v,
})
let Self { k, v } = self;
apply2(k, v, sub).map(|(k, v)| Property { k, v })
}
}

Expand Down

0 comments on commit 794a801

Please sign in to comment.