mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +00:00
Fix a refinement + union types bug
This commit is contained in:
parent
188f8ad965
commit
6cb3231845
12 changed files with 144 additions and 101 deletions
|
@ -551,7 +551,7 @@ impl Context {
|
|||
self.get_attr_info_from_attributive(&fv.crack(), ident, namespace)
|
||||
}
|
||||
Type::FreeVar(fv) => {
|
||||
let sup = fv.get_sup().unwrap();
|
||||
let sup = fv.get_super().unwrap();
|
||||
self.get_attr_info_from_attributive(&sup, ident, namespace)
|
||||
}
|
||||
Type::Ref(t) => self.get_attr_info_from_attributive(t, ident, namespace),
|
||||
|
@ -1573,7 +1573,7 @@ impl Context {
|
|||
match t {
|
||||
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),
|
||||
Type::FreeVar(fv) => {
|
||||
if let Some(sup) = fv.get_sup() {
|
||||
if let Some(sup) = fv.get_super() {
|
||||
self.get_nominal_super_type_ctxs(&sup)
|
||||
} else {
|
||||
self.get_nominal_super_type_ctxs(&Type)
|
||||
|
@ -1614,7 +1614,7 @@ impl Context {
|
|||
&'a self,
|
||||
t: &Type,
|
||||
) -> Option<impl Iterator<Item = &'a Context>> {
|
||||
let ctx = self.get_nominal_type_ctx(t)?;
|
||||
let (_, ctx) = self.get_nominal_type_ctx(t)?;
|
||||
let sups = ctx
|
||||
.super_classes
|
||||
.iter()
|
||||
|
@ -1622,18 +1622,19 @@ impl Context {
|
|||
.map(|sup| {
|
||||
self.get_nominal_type_ctx(sup)
|
||||
.unwrap_or_else(|| todo!("compiler bug: {sup} not found"))
|
||||
.1
|
||||
});
|
||||
Some(vec![ctx].into_iter().chain(sups))
|
||||
}
|
||||
|
||||
pub(crate) fn _get_super_traits(&self, typ: &Type) -> Option<impl Iterator<Item = Type>> {
|
||||
self.get_nominal_type_ctx(typ)
|
||||
.map(|ctx| ctx.super_traits.clone().into_iter())
|
||||
.map(|(_, ctx)| ctx.super_traits.clone().into_iter())
|
||||
}
|
||||
|
||||
/// if `typ` is a refinement type, include the base type (refine.t)
|
||||
pub(crate) fn _get_super_classes(&self, typ: &Type) -> Option<impl Iterator<Item = Type>> {
|
||||
self.get_nominal_type_ctx(typ).map(|ctx| {
|
||||
self.get_nominal_type_ctx(typ).map(|(_, ctx)| {
|
||||
let super_classes = ctx.super_classes.clone();
|
||||
let derefined = typ.derefine();
|
||||
if typ != &derefined {
|
||||
|
@ -1645,7 +1646,10 @@ impl Context {
|
|||
}
|
||||
|
||||
// TODO: Never
|
||||
pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a Context> {
|
||||
pub(crate) fn get_nominal_type_ctx<'a>(
|
||||
&'a self,
|
||||
typ: &Type,
|
||||
) -> Option<(&'a Type, &'a Context)> {
|
||||
match typ {
|
||||
Type::FreeVar(fv) if fv.is_linked() => {
|
||||
if let Some(res) = self.get_nominal_type_ctx(&fv.crack()) {
|
||||
|
@ -1653,7 +1657,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
Type::FreeVar(fv) => {
|
||||
let sup = fv.get_sup().unwrap();
|
||||
let sup = fv.get_super().unwrap();
|
||||
if let Some(res) = self.get_nominal_type_ctx(&sup) {
|
||||
return Some(res);
|
||||
}
|
||||
|
@ -1664,37 +1668,37 @@ impl Context {
|
|||
}
|
||||
}
|
||||
Type::Quantified(_) => {
|
||||
if let Some((_t, ctx)) = self
|
||||
if let Some((t, ctx)) = self
|
||||
.get_builtins()
|
||||
.unwrap_or(self)
|
||||
.rec_get_mono_type("QuantifiedFunc")
|
||||
{
|
||||
return Some(ctx);
|
||||
return Some((t, ctx));
|
||||
}
|
||||
}
|
||||
Type::Subr(subr) => match subr.kind {
|
||||
SubrKind::Func => {
|
||||
if let Some((_, ctx)) = self
|
||||
if let Some((t, ctx)) = self
|
||||
.get_builtins()
|
||||
.unwrap_or(self)
|
||||
.rec_get_mono_type("Func")
|
||||
{
|
||||
return Some(ctx);
|
||||
return Some((t, ctx));
|
||||
}
|
||||
}
|
||||
SubrKind::Proc => {
|
||||
if let Some((_, ctx)) = self
|
||||
if let Some((t, ctx)) = self
|
||||
.get_builtins()
|
||||
.unwrap_or(self)
|
||||
.rec_get_mono_type("Proc")
|
||||
{
|
||||
return Some(ctx);
|
||||
return Some((t, ctx));
|
||||
}
|
||||
}
|
||||
},
|
||||
Type::Mono(name) => {
|
||||
if let Some((_, ctx)) = self.rec_get_mono_type(&typ.local_name()) {
|
||||
return Some(ctx);
|
||||
if let Some((t, ctx)) = self.rec_get_mono_type(&typ.local_name()) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
// e.g. http.client.Response -> http.client
|
||||
let mut namespaces = name.split_with(&[".", "::"]);
|
||||
|
@ -1717,14 +1721,14 @@ impl Context {
|
|||
.and_then(|cache| cache.ref_ctx(path.as_path()))
|
||||
})
|
||||
{
|
||||
if let Some((_, ctx)) = ctx.rec_get_mono_type(type_name) {
|
||||
return Some(ctx);
|
||||
if let Some((t, ctx)) = ctx.rec_get_mono_type(type_name) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
Type::Poly { name, .. } => {
|
||||
if let Some((_, ctx)) = self.rec_get_poly_type(&typ.local_name()) {
|
||||
return Some(ctx);
|
||||
if let Some((t, ctx)) = self.rec_get_poly_type(&typ.local_name()) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
// NOTE: This needs to be changed if we want to be able to define classes/traits outside of the top level
|
||||
let mut namespaces = name.split_with(&[".", "::"]);
|
||||
|
@ -1747,8 +1751,8 @@ impl Context {
|
|||
.and_then(|cache| cache.ref_ctx(path.as_path()))
|
||||
})
|
||||
{
|
||||
if let Some((_, ctx)) = ctx.rec_get_poly_type(type_name) {
|
||||
return Some(ctx);
|
||||
if let Some((t, ctx)) = ctx.rec_get_poly_type(type_name) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1756,15 +1760,13 @@ impl Context {
|
|||
return self
|
||||
.get_builtins()
|
||||
.unwrap_or(self)
|
||||
.rec_get_mono_type("RecordType")
|
||||
.map(|(_, ctx)| ctx);
|
||||
.rec_get_mono_type("RecordType");
|
||||
}
|
||||
Type::Record(_) => {
|
||||
return self
|
||||
.get_builtins()
|
||||
.unwrap_or(self)
|
||||
.rec_get_mono_type("Record")
|
||||
.map(|(_, ctx)| ctx);
|
||||
.rec_get_mono_type("Record");
|
||||
}
|
||||
Type::Or(_l, _r) => {
|
||||
if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) {
|
||||
|
@ -1773,8 +1775,8 @@ impl Context {
|
|||
}
|
||||
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
|
||||
other if other.is_monomorphic() => {
|
||||
if let Some((_t, ctx)) = self.rec_get_mono_type(&other.local_name()) {
|
||||
return Some(ctx);
|
||||
if let Some((t, ctx)) = self.rec_get_mono_type(&other.local_name()) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
}
|
||||
Type::Ref(t) | Type::RefMut { before: t, .. } => {
|
||||
|
@ -1801,7 +1803,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
Type::FreeVar(fv) => {
|
||||
let sup = fv.get_sup().unwrap();
|
||||
let sup = fv.get_super().unwrap();
|
||||
if let Some(res) = self.get_mut_nominal_type_ctx(&sup) {
|
||||
return Some(res);
|
||||
}
|
||||
|
@ -2184,7 +2186,7 @@ impl Context {
|
|||
#[allow(clippy::single_match)]
|
||||
match lhs {
|
||||
Type::FreeVar(fv) => {
|
||||
if let Some(sup) = fv.get_sup() {
|
||||
if let Some(sup) = fv.get_super() {
|
||||
let insts = self.get_trait_impls(&sup);
|
||||
let candidates = insts.into_iter().filter_map(move |inst| {
|
||||
if self.supertype_of(&inst.sup_trait, &sup) {
|
||||
|
@ -2220,7 +2222,7 @@ impl Context {
|
|||
Type::Refinement(refine) => self.is_class(&refine.t),
|
||||
Type::Ref(t) | Type::RefMut { before: t, .. } => self.is_class(t),
|
||||
_ => {
|
||||
if let Some(ctx) = self.get_nominal_type_ctx(typ) {
|
||||
if let Some((_, ctx)) = self.get_nominal_type_ctx(typ) {
|
||||
ctx.kind.is_class()
|
||||
} else {
|
||||
// TODO: unknown types
|
||||
|
@ -2243,7 +2245,7 @@ impl Context {
|
|||
Type::Refinement(refine) => self.is_trait(&refine.t),
|
||||
Type::Ref(t) | Type::RefMut { before: t, .. } => self.is_trait(t),
|
||||
_ => {
|
||||
if let Some(ctx) = self.get_nominal_type_ctx(typ) {
|
||||
if let Some((_, ctx)) = self.get_nominal_type_ctx(typ) {
|
||||
ctx.kind.is_trait()
|
||||
} else {
|
||||
false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue