Skip to content

Commit f056b51

Browse files
author
Markus Westerlind
committed
fix record labels in the face of bound variables
1 parent 848ab34 commit f056b51

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

libflux/flux-core/src/semantic/bootstrap.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ fn add_record_to_map(
317317
env.insert(
318318
match &head.k {
319319
RecordLabel::Concrete(s) => s.clone().into(),
320-
RecordLabel::Variable(_) => bail!("Record contains variable labels"),
320+
RecordLabel::BoundVariable(_) | RecordLabel::Variable(_) => {
321+
bail!("Record contains variable labels")
322+
}
321323
},
322324
PolyType {
323325
vars: new_vars,

libflux/flux-core/src/semantic/convert.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ impl<'a> Converter<'a> {
574574
.entry(prop.name.name.clone())
575575
.or_insert_with(|| self.sub.fresh())
576576
.clone();
577-
tvar.into()
577+
types::RecordLabel::BoundVariable(tvar)
578578
} else {
579579
types::Label::from(self.symbols.lookup(&prop.name.name)).into()
580580
},

libflux/flux-core/src/semantic/nodes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,7 @@ impl IdentifierExpr {
18461846
fn infer(&mut self, infer: &mut InferState<'_, '_>) -> Result {
18471847
let poly = infer.lookup(&self.loc, &self.name);
18481848

1849-
let (t, cons) = infer::instantiate(poly, infer.sub, self.loc.clone());
1849+
let (t, cons) = infer::instantiate(poly.clone(), infer.sub, self.loc.clone());
18501850
infer.solve(&cons);
18511851
self.typ = t;
18521852
Ok(())

libflux/flux-core/src/semantic/types.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,7 +1245,7 @@ impl Record {
12451245
let has_variable_label = |r: &Record| {
12461246
r.fields().any(|prop| match prop.k {
12471247
RecordLabel::Variable(v) => unifier.sub.try_apply(v).is_none(),
1248-
RecordLabel::Concrete(_) => false,
1248+
RecordLabel::BoundVariable(_) | RecordLabel::Concrete(_) => false,
12491249
})
12501250
};
12511251
if has_variable_label(self) || has_variable_label(actual) {
@@ -1339,7 +1339,9 @@ impl Record {
13391339
},
13401340
tail: MonoType::Var(var),
13411341
});
1342+
log::error!("{} = {}", l, act);
13421343
l.unify(&act, unifier);
1344+
log::error!("{} = {}", exp, r);
13431345
exp.unify(r, unifier);
13441346
}
13451347
// If we are expecting {a: u | r} but find {}, label `a` is missing.
@@ -1450,22 +1452,39 @@ fn unify_in_context<T>(
14501452
}
14511453

14521454
/// Labels in records that are allowed be variables
1453-
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Serialize, derive_more::From)]
1455+
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Serialize)]
14541456
pub enum RecordLabel {
14551457
/// A variable label
14561458
Variable(Tvar),
1459+
/// A variable label
1460+
BoundVariable(Tvar),
14571461
/// A concrete label
14581462
Concrete(Label),
14591463
}
14601464

1465+
impl From<Label> for RecordLabel {
1466+
fn from(label: Label) -> Self {
1467+
Self::Concrete(label)
1468+
}
1469+
}
1470+
14611471
impl Substitutable for RecordLabel {
14621472
fn walk(&self, sub: &dyn Substituter) -> Option<Self> {
14631473
match self {
14641474
Self::Variable(tvr) => sub.try_apply(*tvr).and_then(|new| match new {
14651475
MonoType::Label(l) => Some(Self::Concrete(l)),
1476+
MonoType::BoundVar(l) => Some(Self::BoundVariable(l)),
14661477
MonoType::Var(l) => Some(Self::Variable(l)),
14671478
_ => None,
14681479
}),
1480+
1481+
Self::BoundVariable(tvr) => sub.try_apply_bound(*tvr).and_then(|new| match new {
1482+
MonoType::Label(l) => Some(Self::Concrete(l)),
1483+
MonoType::BoundVar(l) => Some(Self::BoundVariable(l)),
1484+
MonoType::Var(l) => Some(Self::Variable(l)),
1485+
_ => None,
1486+
}),
1487+
14691488
Self::Concrete(_) => None,
14701489
}
14711490
}
@@ -1474,7 +1493,8 @@ impl Substitutable for RecordLabel {
14741493
impl fmt::Display for RecordLabel {
14751494
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
14761495
match self {
1477-
Self::Variable(v) => v.fmt(f),
1496+
Self::BoundVariable(v) => v.fmt(f),
1497+
Self::Variable(v) => write!(f, "#{}", v),
14781498
Self::Concrete(v) => v.fmt(f),
14791499
}
14801500
}
@@ -1483,7 +1503,7 @@ impl fmt::Display for RecordLabel {
14831503
impl PartialEq<str> for RecordLabel {
14841504
fn eq(&self, other: &str) -> bool {
14851505
match self {
1486-
Self::Variable(_) => false,
1506+
Self::BoundVariable(_) | Self::Variable(_) => false,
14871507
Self::Concrete(l) => l == other,
14881508
}
14891509
}
@@ -1630,10 +1650,8 @@ where
16301650
V: Substitutable + Clone,
16311651
{
16321652
fn walk(&self, sub: &dyn Substituter) -> Option<Self> {
1633-
self.v.visit(sub).map(|v| Property {
1634-
k: self.k.clone(),
1635-
v,
1636-
})
1653+
let Self { k, v } = self;
1654+
apply2(k, v, sub).map(|(k, v)| Property { k, v })
16371655
}
16381656
}
16391657

0 commit comments

Comments
 (0)