fix: param type instantiation bug

This commit is contained in:
Shunsuke Shibayama 2024-01-29 13:20:40 +09:00
parent 0f3d228997
commit f0e47201bf
5 changed files with 75 additions and 46 deletions

View file

@ -389,7 +389,12 @@ impl Context {
mode,
not_found_is_qvar,
)
.map_err(|errs| (Type::Failure, errs))?
.map_err(|errs| {
(
opt_decl_t.map_or(Type::Failure, |pt| pt.typ().clone()),
errs,
)
})?
} else {
match &sig.pat {
ast::ParamPattern::Lit(lit) => {

View file

@ -1456,6 +1456,25 @@ impl Context {
}
}
}
pub(crate) fn get_tv_ctx(&self, ident: &ast::Identifier, args: &ast::Args) -> TyVarCache {
let mut tv_ctx = TyVarCache::new(self.level, self);
if let Some(ctx) = self.get_type_ctx(ident.inspect()) {
let arg_ts = ctx.params.iter().map(|(_, vi)| &vi.t);
for ((tp, arg), arg_t) in ctx.typ.typarams().iter().zip(args.pos_args()).zip(arg_ts) {
if let ast::Expr::Accessor(ast::Accessor::Ident(ident)) = &arg.expr {
if self.subtype_of(arg_t, &Type::Type) {
if let Ok(tv) = self.convert_tp_into_type(tp.clone()) {
tv_ctx.push_or_init_tyvar(&ident.name, &tv, self);
continue;
}
}
tv_ctx.push_or_init_typaram(&ident.name, tp, self);
}
}
}
tv_ctx
}
}
#[derive(Debug, Clone, Default)]

View file

@ -325,6 +325,7 @@ impl Context {
&mut self,
sig: &mut hir::NonDefaultParamSignature,
opt_decl_t: Option<&ParamTy>,
tmp_tv_cache: &mut TyVarCache,
kind: ParamKind,
) -> TyCheckResult<()> {
let vis = if PYTHON_MODE {
@ -341,7 +342,7 @@ impl Context {
let (spec_t, errs) = match self.instantiate_param_sig_t(
&sig.raw,
opt_decl_t,
&mut TyVarCache::new(self.level, self),
tmp_tv_cache,
Normal,
kind,
false,
@ -384,11 +385,10 @@ impl Context {
)))
} else {
// ok, not defined
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
let (spec_t, mut errs) = match self.instantiate_param_sig_t(
&sig.raw,
opt_decl_t,
&mut dummy_tv_cache,
tmp_tv_cache,
Normal,
kind.clone(),
false,
@ -441,11 +441,10 @@ impl Context {
)))
} else {
// ok, not defined
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
let (spec_t, mut errs) = match self.instantiate_param_sig_t(
&sig.raw,
opt_decl_t,
&mut dummy_tv_cache,
tmp_tv_cache,
Normal,
kind,
false,
@ -494,11 +493,10 @@ impl Context {
)))
} else {
// ok, not defined
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
let (spec_t, mut errs) = match self.instantiate_param_sig_t(
&sig.raw,
opt_decl_t,
&mut dummy_tv_cache,
tmp_tv_cache,
Normal,
kind,
false,
@ -543,6 +541,7 @@ impl Context {
pub(crate) fn assign_params(
&mut self,
params: &mut hir::Params,
tmp_tv_cache: &mut TyVarCache,
expect: Option<SubrType>,
) -> TyCheckResult<()> {
let mut errs = TyCheckErrors::empty();
@ -570,18 +569,23 @@ impl Context {
.iter_mut()
.zip(subr_t.non_default_params.iter())
{
if let Err(es) = self.assign_param(non_default, Some(pt), ParamKind::NonDefault) {
if let Err(es) =
self.assign_param(non_default, Some(pt), tmp_tv_cache, ParamKind::NonDefault)
{
errs.extend(es);
}
}
if let Some(var_params) = &mut params.var_params {
if let Some(pt) = &subr_t.var_params {
let pt = pt.clone().map_type(unknown_len_array_t);
if let Err(es) = self.assign_param(var_params, Some(&pt), ParamKind::VarParams)
if let Err(es) =
self.assign_param(var_params, Some(&pt), tmp_tv_cache, ParamKind::VarParams)
{
errs.extend(es);
}
} else if let Err(es) = self.assign_param(var_params, None, ParamKind::VarParams) {
} else if let Err(es) =
self.assign_param(var_params, None, tmp_tv_cache, ParamKind::VarParams)
{
errs.extend(es);
}
}
@ -589,6 +593,7 @@ impl Context {
if let Err(es) = self.assign_param(
&mut default.sig,
Some(pt),
tmp_tv_cache,
ParamKind::Default(default.default_val.t()),
) {
errs.extend(es);
@ -597,25 +602,32 @@ impl Context {
if let Some(kw_var_params) = &mut params.kw_var_params {
if let Some(pt) = &subr_t.var_params {
let pt = pt.clone().map_type(str_dict_t);
if let Err(es) =
self.assign_param(kw_var_params, Some(&pt), ParamKind::KwVarParams)
{
if let Err(es) = self.assign_param(
kw_var_params,
Some(&pt),
tmp_tv_cache,
ParamKind::KwVarParams,
) {
errs.extend(es);
}
} else if let Err(es) =
self.assign_param(kw_var_params, None, ParamKind::KwVarParams)
self.assign_param(kw_var_params, None, tmp_tv_cache, ParamKind::KwVarParams)
{
errs.extend(es);
}
}
} else {
for non_default in params.non_defaults.iter_mut() {
if let Err(es) = self.assign_param(non_default, None, ParamKind::NonDefault) {
if let Err(es) =
self.assign_param(non_default, None, tmp_tv_cache, ParamKind::NonDefault)
{
errs.extend(es);
}
}
if let Some(var_params) = &mut params.var_params {
if let Err(es) = self.assign_param(var_params, None, ParamKind::VarParams) {
if let Err(es) =
self.assign_param(var_params, None, tmp_tv_cache, ParamKind::VarParams)
{
errs.extend(es);
}
}
@ -623,13 +635,16 @@ impl Context {
if let Err(es) = self.assign_param(
&mut default.sig,
None,
tmp_tv_cache,
ParamKind::Default(default.default_val.t()),
) {
errs.extend(es);
}
}
if let Some(kw_var_params) = &mut params.kw_var_params {
if let Err(es) = self.assign_param(kw_var_params, None, ParamKind::KwVarParams) {
if let Err(es) =
self.assign_param(kw_var_params, None, tmp_tv_cache, ParamKind::KwVarParams)
{
errs.extend(es);
}
}

View file

@ -617,25 +617,6 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
}
}
fn get_tv_ctx(&self, ident: &ast::Identifier, args: &ast::Args) -> TyVarCache {
let mut tv_ctx = TyVarCache::new(self.module.context.level, &self.module.context);
if let Some(ctx) = self.module.context.get_type_ctx(ident.inspect()) {
let arg_ts = ctx.params.iter().map(|(_, vi)| &vi.t);
for ((tp, arg), arg_t) in ctx.typ.typarams().iter().zip(args.pos_args()).zip(arg_ts) {
if let ast::Expr::Accessor(ast::Accessor::Ident(ident)) = &arg.expr {
if self.module.context.subtype_of(arg_t, &Type::Type) {
if let Ok(tv) = self.module.context.convert_tp_into_type(tp.clone()) {
tv_ctx.push_or_init_tyvar(&ident.name, &tv, &self.module.context);
continue;
}
}
tv_ctx.push_or_init_typaram(&ident.name, tp, &self.module.context);
}
}
}
tv_ctx
}
fn declare_ident(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
log!(info "entered {}({})", fn_name!(), tasc);
let kind = tasc.kind();
@ -688,7 +669,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
"complex polymorphic type declaration"
);
};
self.get_tv_ctx(&ident, &call.args)
self.module.context.get_tv_ctx(&ident, &call.args)
} else {
TyVarCache::new(self.module.context.level, &self.module.context)
};
@ -805,7 +786,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
);
};
let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
let mut tv_cache = self.get_tv_ctx(&ident, &call.args);
let mut tv_cache = self.module.context.get_tv_ctx(&ident, &call.args);
let t = self
.module
.context

View file

@ -1528,9 +1528,14 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
fn lower_params(
&mut self,
params: ast::Params,
bounds: ast::TypeBoundSpecs,
expect: Option<&SubrType>,
) -> LowerResult<hir::Params> {
log!(info "entered {}({})", fn_name!(), params);
let mut tmp_tv_ctx = self
.module
.context
.instantiate_ty_bounds(&bounds, RegistrationMode::Normal)?;
let mut errs = LowerErrors::empty();
let mut hir_non_defaults = vec![];
for non_default in params.non_defaults.into_iter() {
@ -1577,10 +1582,10 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
vec![],
params.parens,
);
if let Err(errs) = self
.module
.context
.assign_params(&mut hir_params, expect.cloned())
if let Err(errs) =
self.module
.context
.assign_params(&mut hir_params, &mut tmp_tv_ctx, expect.cloned())
{
self.errs.extend(errs);
}
@ -1642,7 +1647,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
.grow(&name, kind, Private, Some(tv_cache));
}
let params = self
.lower_params(lambda.sig.params, expect)
.lower_params(lambda.sig.params, lambda.sig.bounds, expect)
.map_err(|errs| {
if !in_statement {
self.pop_append_errs();
@ -2025,7 +2030,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
self.lower_subr_block(subr_t, sig, decorators, body)
}
Type::Failure => {
let params = self.lower_params(sig.params, None)?;
let params = self.lower_params(sig.params, sig.bounds.clone(), None)?;
if let Err(errs) = self.module.context.register_const(&body.block) {
self.errs.extend(errs);
}
@ -2067,7 +2072,11 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
decorators: Set<hir::Expr>,
body: ast::DefBody,
) -> LowerResult<hir::Def> {
let params = self.lower_params(sig.params.clone(), Some(&registered_subr_t))?;
let params = self.lower_params(
sig.params.clone(),
sig.bounds.clone(),
Some(&registered_subr_t),
)?;
if let Err(errs) = self.module.context.register_const(&body.block) {
self.errs.extend(errs);
}