mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
feat: support using attributes in predicate
This commit is contained in:
parent
47818e431e
commit
0bedeb51ab
6 changed files with 194 additions and 21 deletions
|
@ -144,12 +144,7 @@ impl<T: ?Sized> Shared<T> {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn borrow(&self) -> RwLockReadGuard<'_, T> {
|
pub fn borrow(&self) -> RwLockReadGuard<'_, T> {
|
||||||
self.wait_until_unlocked();
|
self.wait_until_unlocked();
|
||||||
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
let res = self.data.try_read_for(GET_TIMEOUT).unwrap_or_else(|| {
|
||||||
{
|
|
||||||
*self.last_borrowed_at.try_write_for(GET_TIMEOUT).unwrap() =
|
|
||||||
BorrowInfo::new(Some(std::panic::Location::caller()));
|
|
||||||
}
|
|
||||||
self.data.try_read_for(GET_TIMEOUT).unwrap_or_else(|| {
|
|
||||||
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
{
|
{
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -162,24 +157,20 @@ impl<T: ?Sized> Shared<T> {
|
||||||
{
|
{
|
||||||
panic!("Shared::borrow: already borrowed")
|
panic!("Shared::borrow: already borrowed")
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
{
|
||||||
|
*self.last_borrowed_at.try_write_for(GET_TIMEOUT).unwrap() =
|
||||||
|
BorrowInfo::new(Some(std::panic::Location::caller()));
|
||||||
|
}
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn borrow_mut(&self) -> RwLockWriteGuard<'_, T> {
|
pub fn borrow_mut(&self) -> RwLockWriteGuard<'_, T> {
|
||||||
self.wait_until_unlocked();
|
self.wait_until_unlocked();
|
||||||
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
let res = self.data.try_write_for(SET_TIMEOUT).unwrap_or_else(|| {
|
||||||
{
|
|
||||||
let caller = std::panic::Location::caller();
|
|
||||||
*self.last_borrowed_at.try_write_for(SET_TIMEOUT).unwrap() =
|
|
||||||
BorrowInfo::new(Some(caller));
|
|
||||||
*self
|
|
||||||
.last_mut_borrowed_at
|
|
||||||
.try_write_for(SET_TIMEOUT)
|
|
||||||
.unwrap() = BorrowInfo::new(Some(caller));
|
|
||||||
}
|
|
||||||
self.data.try_write_for(SET_TIMEOUT).unwrap_or_else(|| {
|
|
||||||
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
{
|
{
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -192,7 +183,18 @@ impl<T: ?Sized> Shared<T> {
|
||||||
{
|
{
|
||||||
panic!("Shared::borrow_mut: already borrowed")
|
panic!("Shared::borrow_mut: already borrowed")
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
{
|
||||||
|
let caller = std::panic::Location::caller();
|
||||||
|
*self.last_borrowed_at.try_write_for(SET_TIMEOUT).unwrap() =
|
||||||
|
BorrowInfo::new(Some(caller));
|
||||||
|
*self
|
||||||
|
.last_mut_borrowed_at
|
||||||
|
.try_write_for(SET_TIMEOUT)
|
||||||
|
.unwrap() = BorrowInfo::new(Some(caller));
|
||||||
|
}
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lock the data and deny access from other threads.
|
/// Lock the data and deny access from other threads.
|
||||||
|
@ -277,6 +279,10 @@ impl<T: Clone> Shared<T> {
|
||||||
pub struct Forkable<T: Send + Clone> {
|
pub struct Forkable<T: Send + Clone> {
|
||||||
data: Arc<ThreadLocal<RefCell<T>>>,
|
data: Arc<ThreadLocal<RefCell<T>>>,
|
||||||
init: Arc<T>,
|
init: Arc<T>,
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
last_borrowed_at: Arc<ThreadLocal<RefCell<BorrowInfo>>>,
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
last_mut_borrowed_at: Arc<ThreadLocal<RefCell<BorrowInfo>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: fmt::Debug + Send + Clone> fmt::Debug for Forkable<T> {
|
impl<T: fmt::Debug + Send + Clone> fmt::Debug for Forkable<T> {
|
||||||
|
@ -307,6 +313,10 @@ impl<T: Send + Clone> Forkable<T> {
|
||||||
Self {
|
Self {
|
||||||
data: Arc::new(ThreadLocal::new()),
|
data: Arc::new(ThreadLocal::new()),
|
||||||
init: Arc::new(init),
|
init: Arc::new(init),
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
last_borrowed_at: Arc::new(ThreadLocal::new()),
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
last_mut_borrowed_at: Arc::new(ThreadLocal::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,4 +329,77 @@ impl<T: Send + Clone> Forkable<T> {
|
||||||
pub fn clone_inner(&self) -> T {
|
pub fn clone_inner(&self) -> T {
|
||||||
self.deref().borrow().clone()
|
self.deref().borrow().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
pub fn borrow(&self) -> std::cell::Ref<'_, T> {
|
||||||
|
match self.deref().try_borrow() {
|
||||||
|
Ok(res) => {
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
{
|
||||||
|
*self
|
||||||
|
.last_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow_mut() = BorrowInfo::new(Some(std::panic::Location::caller()));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
{
|
||||||
|
panic!(
|
||||||
|
"Forkable::borrow: already borrowed at {}, mutably borrowed at {} ({err})",
|
||||||
|
self.last_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow(),
|
||||||
|
self.last_mut_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#[cfg(not(any(feature = "backtrace", feature = "debug")))]
|
||||||
|
{
|
||||||
|
panic!("Forkable::borrow: {err}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
pub fn borrow_mut(&self) -> std::cell::RefMut<'_, T> {
|
||||||
|
match self.deref().try_borrow_mut() {
|
||||||
|
Ok(res) => {
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
{
|
||||||
|
let caller = std::panic::Location::caller();
|
||||||
|
*self
|
||||||
|
.last_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow_mut() = BorrowInfo::new(Some(caller));
|
||||||
|
*self
|
||||||
|
.last_mut_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow_mut() = BorrowInfo::new(Some(caller));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
#[cfg(any(feature = "backtrace", feature = "debug"))]
|
||||||
|
{
|
||||||
|
panic!(
|
||||||
|
"Forkable::borrow_mut: already borrowed at {}, mutably borrowed at {} ({err})",
|
||||||
|
self.last_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow(),
|
||||||
|
self.last_mut_borrowed_at
|
||||||
|
.get_or(|| RefCell::new(BorrowInfo::new(None)))
|
||||||
|
.borrow()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#[cfg(not(any(feature = "backtrace", feature = "debug")))]
|
||||||
|
{
|
||||||
|
panic!("Forkable::borrow_mut: {err}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1664,7 +1664,9 @@ impl Context {
|
||||||
Predicate::Call { receiver, name, .. } => {
|
Predicate::Call { receiver, name, .. } => {
|
||||||
let receiver_t = self.get_tp_t(receiver).unwrap_or(Obj);
|
let receiver_t = self.get_tp_t(receiver).unwrap_or(Obj);
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
let ctx = self.get_nominal_type_ctx(&receiver_t).unwrap();
|
let Some(ctx) = self.get_nominal_type_ctx(&receiver_t) else {
|
||||||
|
return Obj;
|
||||||
|
};
|
||||||
if let Some((_, method)) = ctx.get_var_info(name) {
|
if let Some((_, method)) = ctx.get_var_info(name) {
|
||||||
method.t.return_t().cloned().unwrap_or(Obj)
|
method.t.return_t().cloned().unwrap_or(Obj)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1674,6 +1676,17 @@ impl Context {
|
||||||
receiver_t.return_t().cloned().unwrap_or(Obj)
|
receiver_t.return_t().cloned().unwrap_or(Obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Predicate::Attr { receiver, name } => {
|
||||||
|
let receiver_t = self.get_tp_t(receiver).unwrap_or(Obj);
|
||||||
|
let Some(ctx) = self.get_nominal_type_ctx(&receiver_t) else {
|
||||||
|
return Obj;
|
||||||
|
};
|
||||||
|
if let Some((_, field)) = ctx.get_var_info(name) {
|
||||||
|
field.t.clone()
|
||||||
|
} else {
|
||||||
|
Obj
|
||||||
|
}
|
||||||
|
}
|
||||||
// REVIEW
|
// REVIEW
|
||||||
Predicate::GeneralEqual { rhs, .. }
|
Predicate::GeneralEqual { rhs, .. }
|
||||||
| Predicate::GeneralGreaterEqual { rhs, .. }
|
| Predicate::GeneralGreaterEqual { rhs, .. }
|
||||||
|
|
|
@ -1589,6 +1589,7 @@ impl Context {
|
||||||
Ok(TyParam::Value(ValueObj::Type(t)))
|
Ok(TyParam::Value(ValueObj::Type(t)))
|
||||||
}
|
}
|
||||||
TyParam::ProjCall { obj, attr, args } => self.eval_proj_call(*obj, attr, args, &()),
|
TyParam::ProjCall { obj, attr, args } => self.eval_proj_call(*obj, attr, args, &()),
|
||||||
|
TyParam::Proj { obj, attr } => self.eval_tp_proj(*obj, attr, &()),
|
||||||
TyParam::Value(_) => Ok(p.clone()),
|
TyParam::Value(_) => Ok(p.clone()),
|
||||||
other => feature_error!(self, Location::Unknown, &format!("evaluating {other}")),
|
other => feature_error!(self, Location::Unknown, &format!("evaluating {other}")),
|
||||||
}
|
}
|
||||||
|
@ -1951,6 +1952,51 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn eval_tp_proj(
|
||||||
|
&self,
|
||||||
|
lhs: TyParam,
|
||||||
|
rhs: Str,
|
||||||
|
t_loc: &impl Locational,
|
||||||
|
) -> EvalResult<TyParam> {
|
||||||
|
// in Methods
|
||||||
|
if let Some(ctx) = lhs
|
||||||
|
.qual_name()
|
||||||
|
.and_then(|name| self.get_same_name_context(&name))
|
||||||
|
{
|
||||||
|
if let Some(value) = ctx.rec_get_const_obj(&rhs) {
|
||||||
|
return Ok(TyParam::value(value.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let ty_ctxs = match self
|
||||||
|
.get_tp_t(&lhs)
|
||||||
|
.ok()
|
||||||
|
.and_then(|t| self.get_nominal_super_type_ctxs(&t))
|
||||||
|
{
|
||||||
|
Some(ty_ctxs) => ty_ctxs,
|
||||||
|
None => {
|
||||||
|
let errs = EvalErrors::from(EvalError::type_not_found(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
t_loc.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
&Type::Obj,
|
||||||
|
));
|
||||||
|
return Err(errs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for ty_ctx in ty_ctxs {
|
||||||
|
if let Some(value) = ty_ctx.rec_get_const_obj(&rhs) {
|
||||||
|
return Ok(TyParam::value(value.clone()));
|
||||||
|
}
|
||||||
|
for methods in ty_ctx.methods_list.iter() {
|
||||||
|
if let Some(value) = methods.rec_get_const_obj(&rhs) {
|
||||||
|
return Ok(TyParam::value(value.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(lhs.proj(rhs))
|
||||||
|
}
|
||||||
|
|
||||||
/// ```erg
|
/// ```erg
|
||||||
/// TyParam::Type(Int) => Int
|
/// TyParam::Type(Int) => Int
|
||||||
/// [{1}, {2}, {3}] => [{1, 2, 3}; 3]
|
/// [{1}, {2}, {3}] => [{1, 2, 3}; 3]
|
||||||
|
@ -2750,6 +2796,10 @@ impl Context {
|
||||||
feature_error!(self, Location::Unknown, "eval_pred: Predicate::Call")
|
feature_error!(self, Location::Unknown, "eval_pred: Predicate::Call")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Predicate::Attr { receiver, name } => {
|
||||||
|
let receiver = self.eval_tp(receiver)?;
|
||||||
|
Ok(Predicate::attr(receiver, name))
|
||||||
|
}
|
||||||
Predicate::GeneralEqual { lhs, rhs } => {
|
Predicate::GeneralEqual { lhs, rhs } => {
|
||||||
match (self.eval_pred(*lhs)?, self.eval_pred(*rhs)?) {
|
match (self.eval_pred(*lhs)?, self.eval_pred(*rhs)?) {
|
||||||
(Predicate::Value(lhs), Predicate::Value(rhs)) => {
|
(Predicate::Value(lhs), Predicate::Value(rhs)) => {
|
||||||
|
|
|
@ -335,6 +335,10 @@ impl Generalizer {
|
||||||
}
|
}
|
||||||
Predicate::call(receiver, name, new_args)
|
Predicate::call(receiver, name, new_args)
|
||||||
}
|
}
|
||||||
|
Predicate::Attr { receiver, name } => {
|
||||||
|
let receiver = self.generalize_tp(receiver, uninit);
|
||||||
|
Predicate::attr(receiver, name)
|
||||||
|
}
|
||||||
Predicate::Value(_) => pred,
|
Predicate::Value(_) => pred,
|
||||||
Predicate::GeneralEqual { lhs, rhs } => {
|
Predicate::GeneralEqual { lhs, rhs } => {
|
||||||
let lhs = self.generalize_pred(*lhs, uninit);
|
let lhs = self.generalize_pred(*lhs, uninit);
|
||||||
|
|
|
@ -1577,6 +1577,10 @@ impl Context {
|
||||||
self.inc_ref_local(local, self, tmp_tv_cache);
|
self.inc_ref_local(local, self, tmp_tv_cache);
|
||||||
Ok(Predicate::Const(local.inspect().clone()))
|
Ok(Predicate::Const(local.inspect().clone()))
|
||||||
}
|
}
|
||||||
|
ast::ConstExpr::Accessor(ast::ConstAccessor::Attr(attr)) => {
|
||||||
|
let obj = self.instantiate_const_expr(&attr.obj, None, tmp_tv_cache, false)?;
|
||||||
|
Ok(Predicate::attr(obj, attr.name.inspect().clone()))
|
||||||
|
}
|
||||||
ast::ConstExpr::App(app) => {
|
ast::ConstExpr::App(app) => {
|
||||||
let receiver = self.instantiate_const_expr(&app.obj, None, tmp_tv_cache, false)?;
|
let receiver = self.instantiate_const_expr(&app.obj, None, tmp_tv_cache, false)?;
|
||||||
let name = app.attr_name.as_ref().map(|n| n.inspect().to_owned());
|
let name = app.attr_name.as_ref().map(|n| n.inspect().to_owned());
|
||||||
|
|
|
@ -20,6 +20,10 @@ pub enum Predicate {
|
||||||
name: Option<Str>,
|
name: Option<Str>,
|
||||||
args: Vec<TyParam>,
|
args: Vec<TyParam>,
|
||||||
},
|
},
|
||||||
|
Attr {
|
||||||
|
receiver: TyParam,
|
||||||
|
name: Str,
|
||||||
|
},
|
||||||
/// TODO: unify with GeneralEqual
|
/// TODO: unify with GeneralEqual
|
||||||
/// i == 0 => Eq{ lhs: "i", rhs: 0 }
|
/// i == 0 => Eq{ lhs: "i", rhs: 0 }
|
||||||
Equal {
|
Equal {
|
||||||
|
@ -81,6 +85,7 @@ impl fmt::Display for Predicate {
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, name } => write!(f, "{receiver}.{name}"),
|
||||||
Self::Equal { lhs, rhs } => write!(f, "{lhs} == {rhs}"),
|
Self::Equal { lhs, rhs } => write!(f, "{lhs} == {rhs}"),
|
||||||
Self::GreaterEqual { lhs, rhs } => write!(f, "{lhs} >= {rhs}"),
|
Self::GreaterEqual { lhs, rhs } => write!(f, "{lhs} >= {rhs}"),
|
||||||
Self::LessEqual { lhs, rhs } => write!(f, "{lhs} <= {rhs}"),
|
Self::LessEqual { lhs, rhs } => write!(f, "{lhs} <= {rhs}"),
|
||||||
|
@ -120,6 +125,7 @@ impl LimitedDisplay for Predicate {
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, name } => write!(f, "{receiver}.{name}"),
|
||||||
Self::Equal { lhs, rhs } => {
|
Self::Equal { lhs, rhs } => {
|
||||||
write!(f, "{lhs} == ")?;
|
write!(f, "{lhs} == ")?;
|
||||||
rhs.limited_fmt(f, limit - 1)
|
rhs.limited_fmt(f, limit - 1)
|
||||||
|
@ -261,6 +267,7 @@ impl HasLevel for Predicate {
|
||||||
.level()
|
.level()
|
||||||
.zip(args.iter().map(|a| a.level().unwrap_or(usize::MAX)).min())
|
.zip(args.iter().map(|a| a.level().unwrap_or(usize::MAX)).min())
|
||||||
.map(|(a, b)| a.min(b)),
|
.map(|(a, b)| a.min(b)),
|
||||||
|
Self::Attr { receiver, .. } => receiver.level(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +280,9 @@ impl HasLevel for Predicate {
|
||||||
arg.set_level(level);
|
arg.set_level(level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, .. } => {
|
||||||
|
receiver.set_level(level);
|
||||||
|
}
|
||||||
Self::Equal { rhs, .. }
|
Self::Equal { rhs, .. }
|
||||||
| Self::GreaterEqual { rhs, .. }
|
| Self::GreaterEqual { rhs, .. }
|
||||||
| Self::LessEqual { rhs, .. }
|
| Self::LessEqual { rhs, .. }
|
||||||
|
@ -361,6 +371,10 @@ impl Predicate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attr(receiver: TyParam, name: Str) -> Self {
|
||||||
|
Self::Attr { receiver, name }
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn eq(lhs: Str, rhs: TyParam) -> Self {
|
pub const fn eq(lhs: Str, rhs: TyParam) -> Self {
|
||||||
Self::Equal { lhs, rhs }
|
Self::Equal { lhs, rhs }
|
||||||
}
|
}
|
||||||
|
@ -616,6 +630,7 @@ impl Predicate {
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, .. } => receiver.qvars(),
|
||||||
Self::Equal { rhs, .. }
|
Self::Equal { rhs, .. }
|
||||||
| Self::GreaterEqual { rhs, .. }
|
| Self::GreaterEqual { rhs, .. }
|
||||||
| Self::LessEqual { rhs, .. }
|
| Self::LessEqual { rhs, .. }
|
||||||
|
@ -638,6 +653,7 @@ impl Predicate {
|
||||||
Self::Call { receiver, args, .. } => {
|
Self::Call { receiver, args, .. } => {
|
||||||
receiver.has_qvar() || args.iter().any(|a| a.has_qvar())
|
receiver.has_qvar() || args.iter().any(|a| a.has_qvar())
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, .. } => receiver.has_qvar(),
|
||||||
Self::Equal { rhs, .. }
|
Self::Equal { rhs, .. }
|
||||||
| Self::GreaterEqual { rhs, .. }
|
| Self::GreaterEqual { rhs, .. }
|
||||||
| Self::LessEqual { rhs, .. }
|
| Self::LessEqual { rhs, .. }
|
||||||
|
@ -658,6 +674,7 @@ impl Predicate {
|
||||||
Self::Call { receiver, args, .. } => {
|
Self::Call { receiver, args, .. } => {
|
||||||
receiver.has_unbound_var() || args.iter().any(|a| a.has_unbound_var())
|
receiver.has_unbound_var() || args.iter().any(|a| a.has_unbound_var())
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, .. } => receiver.has_unbound_var(),
|
||||||
Self::Equal { rhs, .. }
|
Self::Equal { rhs, .. }
|
||||||
| Self::GreaterEqual { rhs, .. }
|
| Self::GreaterEqual { rhs, .. }
|
||||||
| Self::LessEqual { rhs, .. }
|
| Self::LessEqual { rhs, .. }
|
||||||
|
@ -681,6 +698,7 @@ impl Predicate {
|
||||||
receiver.has_undoable_linked_var()
|
receiver.has_undoable_linked_var()
|
||||||
|| args.iter().any(|a| a.has_undoable_linked_var())
|
|| args.iter().any(|a| a.has_undoable_linked_var())
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, .. } => receiver.has_undoable_linked_var(),
|
||||||
Self::Equal { rhs, .. }
|
Self::Equal { rhs, .. }
|
||||||
| Self::GreaterEqual { rhs, .. }
|
| Self::GreaterEqual { rhs, .. }
|
||||||
| Self::LessEqual { rhs, .. }
|
| Self::LessEqual { rhs, .. }
|
||||||
|
@ -732,7 +750,7 @@ impl Predicate {
|
||||||
|
|
||||||
pub fn typarams(&self) -> Vec<&TyParam> {
|
pub fn typarams(&self) -> Vec<&TyParam> {
|
||||||
match self {
|
match self {
|
||||||
Self::Value(_) | Self::Const(_) => vec![],
|
Self::Value(_) | Self::Const(_) | Self::Attr { .. } => vec![],
|
||||||
// REVIEW: Should the receiver be included?
|
// REVIEW: Should the receiver be included?
|
||||||
Self::Call { args, .. } => {
|
Self::Call { args, .. } => {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
|
@ -797,6 +815,7 @@ impl Predicate {
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
|
Self::Attr { receiver, .. } => receiver.variables(),
|
||||||
Self::Equal { rhs, .. }
|
Self::Equal { rhs, .. }
|
||||||
| Self::GreaterEqual { rhs, .. }
|
| Self::GreaterEqual { rhs, .. }
|
||||||
| Self::LessEqual { rhs, .. }
|
| Self::LessEqual { rhs, .. }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue