fix: subtype relation bug

This commit is contained in:
Shunsuke Shibayama 2024-02-03 19:36:27 +09:00
parent 8d5641503f
commit 9c9f8b7a0a
7 changed files with 233 additions and 121 deletions

View file

@ -329,7 +329,11 @@ impl Context {
if !self.is_trait(lhs) {
return (Maybe, false);
}
self._nominal_subtype_of(lhs, rhs, |ty_ctx| &ty_ctx.super_traits)
let (cred, judge) = self._nominal_subtype_of(lhs, rhs, |ty_ctx| &ty_ctx.super_traits[..]);
if judge {
return (cred, judge);
}
self._nominal_subtype_of(lhs, rhs, |ty_ctx| &ty_ctx.super_classes[..])
}
/// lhs :> rhs?

View file

@ -507,13 +507,15 @@ impl Context {
self.instantiate_mono_t(simple, opt_decl_t, tmp_tv_cache, not_found_is_qvar)
}
ast::PreDeclTypeSpec::Poly(poly) => match &poly.acc {
ast::ConstAccessor::Local(local) => self.instantiate_local_poly_t(
local,
&poly.args,
opt_decl_t,
tmp_tv_cache,
not_found_is_qvar,
),
ast::ConstAccessor::Local(local) => self
.instantiate_local_poly_t(
local,
&poly.args,
opt_decl_t,
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|(_, err)| err),
ast::ConstAccessor::Attr(attr) => {
let ctxs = self.get_singular_ctxs(&attr.obj.clone().downgrade(), self)?;
for ctx in ctxs {
@ -667,7 +669,7 @@ impl Context {
opt_decl_t: Option<&ParamTy>,
tmp_tv_cache: &mut TyVarCache,
not_found_is_qvar: bool,
) -> TyCheckResult<Type> {
) -> Failable<Type> {
match name.inspect().trim_start_matches([':', '.']) {
"Array" => {
let ctx = &self
@ -677,19 +679,22 @@ impl Context {
// TODO: kw
let mut pos_args = args.pos_args();
if let Some(first) = pos_args.next() {
let t = self.instantiate_const_expr_as_type(
&first.expr,
Some((ctx, 0)),
tmp_tv_cache,
not_found_is_qvar,
)?;
let t = self
.instantiate_const_expr_as_type(
&first.expr,
Some((ctx, 0)),
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|err| (Type::Failure, err))?;
let len = if let Some(len) = pos_args.next() {
self.instantiate_const_expr(
&len.expr,
Some((ctx, 1)),
tmp_tv_cache,
not_found_is_qvar,
)?
)
.map_err(|err| (Type::Failure, err))?
} else {
TyParam::erased(Nat)
};
@ -701,104 +706,131 @@ impl Context {
"Ref" => {
let mut pos_args = args.pos_args();
let Some(first) = pos_args.next() else {
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"Ref",
self.caused_by(),
vec![Str::from("T")],
)));
return Err((
Failure,
TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"Ref",
self.caused_by(),
vec![Str::from("T")],
)),
));
};
let t = self.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)?;
let t = self
.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|err| (Type::Failure, err))?;
Ok(ref_(t))
}
"RefMut" => {
// TODO after
let mut pos_args = args.pos_args();
let Some(first) = pos_args.next() else {
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"RefMut",
self.caused_by(),
vec![Str::from("T")],
)));
return Err((
Failure,
TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"RefMut",
self.caused_by(),
vec![Str::from("T")],
)),
));
};
let t = self.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)?;
let t = self
.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|err| (Type::Failure, err))?;
Ok(ref_mut(t, None))
}
"Structural" => {
let mut pos_args = args.pos_args();
let Some(first) = pos_args.next() else {
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"Structural",
self.caused_by(),
vec![Str::from("Type")],
)));
return Err((
Failure,
TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"Structural",
self.caused_by(),
vec![Str::from("Type")],
)),
));
};
let t = self.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)?;
let t = self
.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|err| (Type::Failure, err))?;
Ok(t.structuralize())
}
"NamedTuple" => {
let mut pose_args = args.pos_args();
let Some(first) = pose_args.next() else {
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"NamedTuple",
self.caused_by(),
vec![Str::from("Fields")],
)));
return Err((
Failure,
TyCheckErrors::from(TyCheckError::args_missing_error(
self.cfg.input.clone(),
line!() as usize,
args.loc(),
"NamedTuple",
self.caused_by(),
vec![Str::from("Fields")],
)),
));
};
let ConstExpr::Record(fields) = &first.expr else {
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
self.cfg.input.clone(),
line!() as usize,
first.expr.loc(),
self.caused_by(),
"NamedTuple",
None,
&mono("Record"),
&self.instantiate_const_expr_as_type(
&first.expr,
return Err((
Failure,
TyCheckErrors::from(TyCheckError::type_mismatch_error(
self.cfg.input.clone(),
line!() as usize,
first.expr.loc(),
self.caused_by(),
"NamedTuple",
None,
tmp_tv_cache,
not_found_is_qvar,
)?,
None,
None,
)));
&mono("Record"),
&self
.instantiate_const_expr_as_type(
&first.expr,
None,
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|err| (Type::Failure, err))?,
None,
None,
)),
));
};
let mut ts = vec![];
for def in fields.attrs.iter() {
let t = self.instantiate_const_expr_as_type(
&def.body.block[0],
None,
tmp_tv_cache,
not_found_is_qvar,
)?;
let vis = self.instantiate_vis_modifier(&def.ident.vis)?;
let t = self
.instantiate_const_expr_as_type(
&def.body.block[0],
None,
tmp_tv_cache,
not_found_is_qvar,
)
.map_err(|err| (Type::Failure, err))?;
let vis = self
.instantiate_vis_modifier(&def.ident.vis)
.map_err(|err| (Type::Failure, err))?;
ts.push((Field::new(vis, def.ident.inspect().clone()), t));
}
Ok(Type::NamedTuple(ts))
@ -824,15 +856,19 @@ impl Context {
if let Some(decl_t) = opt_decl_t {
return Ok(decl_t.typ().clone());
}
return Err(TyCheckErrors::from(TyCheckError::no_type_error(
self.cfg.input.clone(),
line!() as usize,
name.loc(),
self.caused_by(),
other,
self.get_similar_name(other),
)));
return Err((
Failure,
TyCheckErrors::from(TyCheckError::no_type_error(
self.cfg.input.clone(),
line!() as usize,
name.loc(),
self.caused_by(),
other,
self.get_similar_name(other),
)),
));
};
let mut errs = TyCheckErrors::empty();
// FIXME: kw args
let mut new_params = vec![];
for ((i, arg), (name, param_vi)) in
@ -844,23 +880,25 @@ impl Context {
tmp_tv_cache,
not_found_is_qvar,
);
let param = param.or_else(|e| {
if not_found_is_qvar {
let name = arg.expr.to_string();
// FIXME: handle `::` as a right way
let name = Str::rc(name.trim_start_matches("::"));
let tp = TyParam::named_free_var(
name.clone(),
self.level,
Constraint::Uninited,
);
let varname = VarName::from_str(name);
tmp_tv_cache.push_or_init_typaram(&varname, &tp, self)?;
Ok(tp)
} else {
Err(e)
}
})?;
let param = param
.or_else(|e| {
if not_found_is_qvar {
let name = arg.expr.to_string();
// FIXME: handle `::` as a right way
let name = Str::rc(name.trim_start_matches("::"));
let tp = TyParam::named_free_var(
name.clone(),
self.level,
Constraint::Uninited,
);
let varname = VarName::from_str(name);
tmp_tv_cache.push_or_init_typaram(&varname, &tp, self)?;
Ok(tp)
} else {
Err(e)
}
})
.map_err(|err| (Type::Failure, err))?;
let arg_t = self
.get_tp_t(&param)
.map_err(|err| {
@ -871,7 +909,8 @@ impl Context {
if self.subtype_of(&arg_t, &param_vi.t) {
new_params.push(param);
} else {
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
new_params.push(TyParam::erased(param_vi.t.clone()));
errs.push(TyCheckError::type_mismatch_error(
self.cfg.input.clone(),
line!() as usize,
arg.expr.loc(),
@ -882,11 +921,16 @@ impl Context {
&arg_t,
None,
None,
)));
));
}
}
// FIXME: non-builtin
Ok(poly(ctx.typ.qual_name(), new_params))
let t = poly(ctx.typ.qual_name(), new_params);
if errs.is_empty() {
Ok(t)
} else {
Err((t, errs))
}
}
}
}