Fix inferring bug

This commit is contained in:
Shunsuke Shibayama 2022-10-14 09:46:42 +09:00
parent d0fa924ea8
commit 7776297de2
2 changed files with 37 additions and 23 deletions

View file

@ -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(),

View file

@ -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 {