mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
WIP
This commit is contained in:
parent
2cf4b5aba8
commit
d62ec0f78f
2 changed files with 38 additions and 7 deletions
|
@ -59,6 +59,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
(TyParam::MonoQVar(name), _other) | (_other, TyParam::MonoQVar(name)) => {
|
||||
log!(err "comparing '{name} and {_other}");
|
||||
panic!("Not instantiated type parameter: {name}")
|
||||
}
|
||||
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval }) => {
|
||||
|
@ -673,22 +674,44 @@ impl Context {
|
|||
}
|
||||
|
||||
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
||||
let (_, ty_ctx) = self.get_nominal_type_ctx(rhs).unwrap();
|
||||
let subst_ctx = SubstContext::new(rhs, ty_ctx);
|
||||
// if `rhs` is {S: Str | ... }, `defined_rhs` will be Str
|
||||
let defined_rhs = if let Some((defined_rhs, _)) = self.get_nominal_type_ctx(rhs) {
|
||||
defined_rhs
|
||||
let defined_rhs = if let Some((defined_rhs, _ty_ctx)) = self.get_nominal_type_ctx(rhs) {
|
||||
if defined_rhs.has_qvar() {
|
||||
subst_ctx
|
||||
.substitute(defined_rhs.clone(), self, Location::Unknown)
|
||||
.unwrap()
|
||||
} else {
|
||||
defined_rhs.clone()
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
if let Some(super_traits) = self.get_nominal_super_trait_ctxs(rhs) {
|
||||
for (sup_trait, _) in super_traits {
|
||||
if self.sup_conforms(lhs, defined_rhs, sup_trait) {
|
||||
for (sup_trait, _ty_ctx) in super_traits {
|
||||
let sup_trait = if sup_trait.has_qvar() {
|
||||
subst_ctx
|
||||
.substitute(sup_trait.clone(), self, Location::Unknown)
|
||||
.unwrap()
|
||||
} else {
|
||||
sup_trait.clone()
|
||||
};
|
||||
if self.sup_conforms(lhs, &defined_rhs, &sup_trait) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(sup_classes) = self.get_nominal_super_class_ctxs(rhs) {
|
||||
for (sup_class, _) in sup_classes {
|
||||
if self.cyclic_supertype_of(lhs, sup_class) {
|
||||
for (sup_class, _ty_ctx) in sup_classes {
|
||||
let sup_class = if sup_class.has_qvar() {
|
||||
subst_ctx
|
||||
.substitute(sup_class.clone(), self, Location::Unknown)
|
||||
.unwrap()
|
||||
} else {
|
||||
sup_class.clone()
|
||||
};
|
||||
if self.cyclic_supertype_of(lhs, &sup_class) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,8 +106,13 @@ pub(crate) fn eval_lit(lit: &Literal) -> ValueObj {
|
|||
ValueObj::from_str(t, lit.token.content.clone())
|
||||
}
|
||||
|
||||
/// Instantiate the polymorphic type from the quantified state.
|
||||
///
|
||||
/// e.g.
|
||||
/// ```
|
||||
/// SubstContext::new(Array(?T, 0), Context(Array('T, 'N))) => SubstContext{ params: { 'T: ?T; 'N: 0 } } => ctx
|
||||
/// ctx.substitute(Array!('T; !'N)): Array(?T, !0)
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct SubstContext {
|
||||
bounds: Set<TyBound>,
|
||||
|
@ -125,6 +130,9 @@ impl fmt::Display for SubstContext {
|
|||
}
|
||||
|
||||
impl SubstContext {
|
||||
/// `substituted` is used to obtain real argument information. So it must be instantiated as `Array(?T, 0)` and so on.
|
||||
///
|
||||
/// `ty_ctx` is used to obtain information on the names and variance of the parameters.
|
||||
pub fn new(substituted: &Type, ty_ctx: &Context) -> Self {
|
||||
let bounds = ty_ctx.type_params_bounds();
|
||||
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
|
||||
|
@ -135,7 +143,7 @@ impl SubstContext {
|
|||
if param_names.len() != substituted.typarams().len() {
|
||||
let param_names = param_names.collect::<Vec<_>>();
|
||||
panic!(
|
||||
"{param_names:?} != {}",
|
||||
"{param_names:?} != [{}]",
|
||||
erg_common::fmt_vec(&substituted.typarams())
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue