mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Fix inferring bug
This commit is contained in:
parent
d0fa924ea8
commit
7776297de2
2 changed files with 37 additions and 23 deletions
|
@ -919,6 +919,19 @@ impl Context {
|
||||||
if sub == Type::Never {
|
if sub == Type::Never {
|
||||||
return Ok(proj(lhs, rhs));
|
return Ok(proj(lhs, rhs));
|
||||||
}
|
}
|
||||||
|
// in Methods
|
||||||
|
if self.name == sub.qual_name() {
|
||||||
|
if let Ok(obj) = self.get_const_local(&Token::symbol(&rhs), &self.name) {
|
||||||
|
if let ValueObj::Type(quant_t) = obj {
|
||||||
|
let subst_ctx = SubstContext::new(&sub, self, t_loc);
|
||||||
|
let t = subst_ctx.substitute(quant_t.typ().clone())?;
|
||||||
|
let t = self.eval_t_params(t, level, t_loc)?;
|
||||||
|
return Ok(t);
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for ty_ctx in self.get_nominal_super_type_ctxs(&sub).ok_or_else(|| {
|
for ty_ctx in self.get_nominal_super_type_ctxs(&sub).ok_or_else(|| {
|
||||||
EvalError::no_var_error(
|
EvalError::no_var_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
|
|
@ -1110,16 +1110,16 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.ctx.check_decls_and_pop() {
|
match self.ctx.check_decls() {
|
||||||
Ok(methods) => {
|
Ok(()) => {
|
||||||
self.check_override(&class, &methods);
|
self.check_override(&class);
|
||||||
if let Some((trait_, _)) = &impl_trait {
|
if let Some((trait_, _)) = &impl_trait {
|
||||||
self.register_trait_impl(&class, trait_);
|
self.register_trait_impl(&class, trait_);
|
||||||
}
|
}
|
||||||
if let Err(err) = self.check_trait_impl(impl_trait, &class, &methods) {
|
if let Err(err) = self.check_trait_impl(impl_trait, &class) {
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
}
|
}
|
||||||
self.check_collision_and_push(class, methods);
|
self.check_collision_and_push(class);
|
||||||
}
|
}
|
||||||
Err(mut errs) => {
|
Err(mut errs) => {
|
||||||
self.errs.append(&mut errs);
|
self.errs.append(&mut errs);
|
||||||
|
@ -1185,14 +1185,15 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_override(&mut self, class: &Type, ctx: &Context) {
|
fn check_override(&mut self, class: &Type) {
|
||||||
if let Some(sups) = self.ctx.get_nominal_super_type_ctxs(class) {
|
if let Some(sups) = self.ctx.get_nominal_super_type_ctxs(class) {
|
||||||
for sup in sups.into_iter().skip(1) {
|
for sup in sups.into_iter().skip(1) {
|
||||||
for (method_name, vi) in ctx
|
for (method_name, vi) in self.ctx.locals.iter().chain(
|
||||||
.locals
|
self.ctx
|
||||||
.iter()
|
.methods_list
|
||||||
.chain(ctx.methods_list.iter().flat_map(|(_, c)| c.locals.iter()))
|
.iter()
|
||||||
{
|
.flat_map(|(_, c)| c.locals.iter()),
|
||||||
|
) {
|
||||||
if let Some(_sup_vi) = sup.get_current_scope_var(method_name.inspect()) {
|
if let Some(_sup_vi) = sup.get_current_scope_var(method_name.inspect()) {
|
||||||
// must `@Override`
|
// must `@Override`
|
||||||
if let Some(decos) = &vi.comptime_decos {
|
if let Some(decos) = &vi.comptime_decos {
|
||||||
|
@ -1206,7 +1207,7 @@ impl ASTLowerer {
|
||||||
method_name.inspect(),
|
method_name.inspect(),
|
||||||
method_name.loc(),
|
method_name.loc(),
|
||||||
&mono(&sup.name), // TODO: get super type
|
&mono(&sup.name), // TODO: get super type
|
||||||
ctx.caused_by(),
|
self.ctx.caused_by(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1220,21 +1221,20 @@ impl ASTLowerer {
|
||||||
&mut self,
|
&mut self,
|
||||||
impl_trait: Option<(Type, Location)>,
|
impl_trait: Option<(Type, Location)>,
|
||||||
class: &Type,
|
class: &Type,
|
||||||
methods: &Context,
|
|
||||||
) -> SingleLowerResult<()> {
|
) -> SingleLowerResult<()> {
|
||||||
if let Some((impl_trait, loc)) = impl_trait {
|
if let Some((impl_trait, loc)) = impl_trait {
|
||||||
// assume the class has implemented the trait, regardless of whether the implementation is correct
|
// assume the class has implemented the trait, regardless of whether the implementation is correct
|
||||||
let trait_ctx = self.ctx.get_nominal_type_ctx(&impl_trait).unwrap().clone();
|
let trait_ctx = self.ctx.get_nominal_type_ctx(&impl_trait).unwrap().clone();
|
||||||
let (_, class_ctx) = self.ctx.get_mut_nominal_type_ctx(class).unwrap();
|
let (_, class_ctx) = self.ctx.get_mut_nominal_type_ctx(class).unwrap();
|
||||||
class_ctx.register_supertrait(impl_trait.clone(), &trait_ctx);
|
class_ctx.register_supertrait(impl_trait.clone(), &trait_ctx);
|
||||||
let mut unverified_names = methods.locals.keys().collect::<Set<_>>();
|
let mut unverified_names = self.ctx.locals.keys().collect::<Set<_>>();
|
||||||
if let Some(trait_obj) = self.ctx.rec_get_const_obj(&impl_trait.local_name()) {
|
if let Some(trait_obj) = self.ctx.rec_get_const_obj(&impl_trait.local_name()) {
|
||||||
if let ValueObj::Type(typ) = trait_obj {
|
if let ValueObj::Type(typ) = trait_obj {
|
||||||
match typ {
|
match typ {
|
||||||
TypeObj::Generated(gen) => match gen.require_or_sup.as_ref().typ() {
|
TypeObj::Generated(gen) => match gen.require_or_sup.as_ref().typ() {
|
||||||
Type::Record(attrs) => {
|
Type::Record(attrs) => {
|
||||||
for (field, field_typ) in attrs.iter() {
|
for (field, field_typ) in attrs.iter() {
|
||||||
if let Some((name, vi)) = methods.get_local_kv(&field.symbol) {
|
if let Some((name, vi)) = self.ctx.get_local_kv(&field.symbol) {
|
||||||
unverified_names.remove(name);
|
unverified_names.remove(name);
|
||||||
if !self.ctx.supertype_of(field_typ, &vi.t) {
|
if !self.ctx.supertype_of(field_typ, &vi.t) {
|
||||||
self.errs.push(LowerError::trait_member_type_error(
|
self.errs.push(LowerError::trait_member_type_error(
|
||||||
|
@ -1265,12 +1265,12 @@ impl ASTLowerer {
|
||||||
other => todo!("{other}"),
|
other => todo!("{other}"),
|
||||||
},
|
},
|
||||||
TypeObj::Builtin(_typ) => {
|
TypeObj::Builtin(_typ) => {
|
||||||
log!("{class}, {_typ}, {impl_trait}",);
|
|
||||||
let ctx = self.ctx.get_nominal_type_ctx(_typ).unwrap();
|
let ctx = self.ctx.get_nominal_type_ctx(_typ).unwrap();
|
||||||
for (decl_name, decl_vi) in ctx.decls.iter() {
|
for (decl_name, decl_vi) in ctx.decls.iter() {
|
||||||
if let Some((name, vi)) = methods.get_local_kv(decl_name.inspect())
|
if let Some((name, vi)) = self.ctx.get_local_kv(decl_name.inspect())
|
||||||
{
|
{
|
||||||
unverified_names.remove(name);
|
unverified_names.remove(name);
|
||||||
|
log!(err "checking");
|
||||||
if !self.ctx.supertype_of(&decl_vi.t, &vi.t) {
|
if !self.ctx.supertype_of(&decl_vi.t, &vi.t) {
|
||||||
self.errs.push(LowerError::trait_member_type_error(
|
self.errs.push(LowerError::trait_member_type_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -1337,24 +1337,25 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_trait_impl(&mut self, class: &Type, trait_: &Type) {
|
fn register_trait_impl(&mut self, class: &Type, trait_: &Type) {
|
||||||
|
let trait_impls = &mut self.ctx.outer.as_mut().unwrap().trait_impls;
|
||||||
// TODO: polymorphic trait
|
// TODO: polymorphic trait
|
||||||
if let Some(impls) = self.ctx.trait_impls.get_mut(&trait_.qual_name()) {
|
if let Some(impls) = trait_impls.get_mut(&trait_.qual_name()) {
|
||||||
impls.insert(TraitInstance::new(class.clone(), trait_.clone()));
|
impls.insert(TraitInstance::new(class.clone(), trait_.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.ctx.trait_impls.insert(
|
trait_impls.insert(
|
||||||
trait_.qual_name(),
|
trait_.qual_name(),
|
||||||
set! {TraitInstance::new(class.clone(), trait_.clone())},
|
set! {TraitInstance::new(class.clone(), trait_.clone())},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_collision_and_push(&mut self, class: Type, methods: Context) {
|
fn check_collision_and_push(&mut self, class: Type) {
|
||||||
|
let methods = self.ctx.pop();
|
||||||
let (_, class_root) = self
|
let (_, class_root) = self
|
||||||
.ctx
|
.ctx
|
||||||
.get_mut_nominal_type_ctx(&class)
|
.get_mut_nominal_type_ctx(&class)
|
||||||
.unwrap_or_else(|| todo!("{class} not found"));
|
.unwrap_or_else(|| todo!("{class} not found"));
|
||||||
for (newly_defined_name, _vi) in methods.locals.iter() {
|
for (newly_defined_name, _vi) in methods.locals.clone().into_iter() {
|
||||||
log!("{}", class_root.methods_list.len());
|
|
||||||
for (_, already_defined_methods) in class_root.methods_list.iter_mut() {
|
for (_, already_defined_methods) in class_root.methods_list.iter_mut() {
|
||||||
// TODO: 特殊化なら同じ名前でもOK
|
// TODO: 特殊化なら同じ名前でもOK
|
||||||
// TODO: 定義のメソッドもエラー表示
|
// TODO: 定義のメソッドもエラー表示
|
||||||
|
@ -1366,7 +1367,7 @@ impl ASTLowerer {
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
newly_defined_name.loc(),
|
newly_defined_name.loc(),
|
||||||
methods.name.clone().into(),
|
methods.caused_by(),
|
||||||
newly_defined_name.inspect(),
|
newly_defined_name.inspect(),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue