Skip to content

Commit 40b53a3

Browse files
committed
fix: trait impl bugs (2)
1 parent 017b13f commit 40b53a3

File tree

4 files changed

+61
-25
lines changed

4 files changed

+61
-25
lines changed

crates/erg_common/dict.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ impl<K, V> Dict<K, V> {
218218
self.dict.retain(f);
219219
}
220220

221+
pub fn retained(mut self, f: impl FnMut(&K, &mut V) -> bool) -> Self {
222+
self.retain(f);
223+
self
224+
}
225+
221226
pub fn get_by(&self, k: &K, cmp: impl Fn(&K, &K) -> bool) -> Option<&V> {
222227
for (k_, v) in self.dict.iter() {
223228
if cmp(k, k_) {

crates/erg_compiler/context/register.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ use super::instantiate::TyVarCache;
4646
use super::instantiate_spec::ParamKind;
4747
use super::{ControlKind, MethodContext, ParamSpec, TraitImpl, TypeContext};
4848

49+
type ClassTrait<'c> = (Type, Option<(Type, &'c TypeSpecWithOp)>);
50+
type ClassTraitErrors<'c> = (
51+
Option<Type>,
52+
Option<(Type, &'c TypeSpecWithOp)>,
53+
TyCheckErrors,
54+
);
55+
4956
pub fn valid_mod_name(name: &str) -> bool {
5057
!name.is_empty() && !name.starts_with('/') && name.trim() == name
5158
}
@@ -987,7 +994,7 @@ impl Context {
987994
pub(crate) fn get_class_and_impl_trait<'c>(
988995
&mut self,
989996
class_spec: &'c ast::TypeSpec,
990-
) -> TyCheckResult<(Type, Option<(Type, &'c TypeSpecWithOp)>)> {
997+
) -> Result<ClassTrait<'c>, ClassTraitErrors<'c>> {
991998
let mut errs = TyCheckErrors::empty();
992999
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
9931000
match class_spec {
@@ -1013,14 +1020,21 @@ impl Context {
10131020
(t, &tasc.t_spec)
10141021
}
10151022
other => {
1016-
return Err(TyCheckErrors::from(TyCheckError::syntax_error(
1017-
self.cfg.input.clone(),
1018-
line!() as usize,
1019-
other.loc(),
1020-
self.caused_by(),
1021-
format!("expected type ascription, but found {}", other.name()),
1023+
return Err((
1024+
None,
10221025
None,
1023-
)))
1026+
TyCheckErrors::from(TyCheckError::syntax_error(
1027+
self.cfg.input.clone(),
1028+
line!() as usize,
1029+
other.loc(),
1030+
self.caused_by(),
1031+
format!(
1032+
"expected type ascription, but found {}",
1033+
other.name()
1034+
),
1035+
None,
1036+
)),
1037+
))
10241038
}
10251039
};
10261040
let class = match self.instantiate_typespec_full(
@@ -1039,7 +1053,7 @@ impl Context {
10391053
if errs.is_empty() {
10401054
Ok((class, Some((impl_trait, t_spec))))
10411055
} else {
1042-
Err(errs)
1056+
Err((Some(class), Some((impl_trait, t_spec)), errs))
10431057
}
10441058
}
10451059
ast::TypeAppArgsKind::SubtypeOf(trait_spec) => {
@@ -1052,8 +1066,10 @@ impl Context {
10521066
) {
10531067
Ok(t) => t,
10541068
Err((t, es)) => {
1055-
errs.extend(es);
1056-
t
1069+
if !PYTHON_MODE {
1070+
errs.extend(es);
1071+
}
1072+
t.replace(&Type::Failure, &Type::Never)
10571073
}
10581074
};
10591075
let class = match self.instantiate_typespec_full(
@@ -1072,7 +1088,7 @@ impl Context {
10721088
if errs.is_empty() {
10731089
Ok((class, Some((impl_trait, trait_spec.as_ref()))))
10741090
} else {
1075-
Err(errs)
1091+
Err((Some(class), Some((impl_trait, trait_spec.as_ref())), errs))
10761092
}
10771093
}
10781094
}
@@ -1094,7 +1110,7 @@ impl Context {
10941110
if errs.is_empty() {
10951111
Ok((t, None))
10961112
} else {
1097-
Err(errs)
1113+
Err((Some(t), None, errs))
10981114
}
10991115
}
11001116
}
@@ -1243,10 +1259,14 @@ impl Context {
12431259
.instantiate_vis_modifier(class_def.def.sig.vis())
12441260
.unwrap_or(VisibilityModifier::Public);
12451261
for methods in class_def.methods_list.iter() {
1246-
let Ok((class, impl_trait)) = self.get_class_and_impl_trait(&methods.class)
1247-
else {
1248-
continue;
1249-
};
1262+
let (class, impl_trait) =
1263+
match self.get_class_and_impl_trait(&methods.class) {
1264+
Ok(x) => x,
1265+
Err((class, trait_, errs)) => {
1266+
total_errs.extend(errs);
1267+
(class.unwrap_or(Type::Obj), trait_)
1268+
}
1269+
};
12501270
// assume the class has implemented the trait, regardless of whether the implementation is correct
12511271
if let Some((trait_, trait_loc)) = &impl_trait {
12521272
if let Err(errs) = self.register_trait_impl(&class, trait_, *trait_loc)

crates/erg_compiler/lower.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,9 +2705,9 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
27052705
let (class, impl_trait) =
27062706
match self.module.context.get_class_and_impl_trait(&methods.class) {
27072707
Ok(x) => x,
2708-
Err(errs) => {
2708+
Err((class, trait_, errs)) => {
27092709
errors.extend(errs);
2710-
continue;
2710+
(class.unwrap_or(Type::Obj), trait_)
27112711
}
27122712
};
27132713
if let Some(class_root) = self.module.context.get_nominal_type_ctx(&class) {
@@ -3224,16 +3224,27 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
32243224
) -> (Set<&VarName>, CompileErrors) {
32253225
let mut errors = CompileErrors::empty();
32263226
let mut unverified_names = self.module.context.locals.keys().collect::<Set<_>>();
3227+
let mut super_impls = set! {};
32273228
let tys_decls = if let Some(sups) = self.module.context.get_super_types(trait_type) {
32283229
sups.map(|sup| {
32293230
if implemented.linear_contains(&sup) {
32303231
return (sup, Dict::new());
32313232
}
3232-
let decls = self
3233-
.module
3234-
.context
3235-
.get_nominal_type_ctx(&sup)
3236-
.map_or(Dict::new(), |ctx| ctx.decls.clone());
3233+
let decls =
3234+
self.module
3235+
.context
3236+
.get_nominal_type_ctx(&sup)
3237+
.map_or(Dict::new(), |ctx| {
3238+
super_impls.extend(ctx.locals.keys());
3239+
for methods in &ctx.methods_list {
3240+
super_impls.extend(methods.locals.keys());
3241+
}
3242+
ctx.decls.clone().retained(|k, _| {
3243+
let implemented_in_super = super_impls.contains(k);
3244+
let class_decl = ctx.kind.is_class();
3245+
!implemented_in_super && !class_decl
3246+
})
3247+
});
32373248
(sup, decls)
32383249
})
32393250
.collect::<Vec<_>>()

crates/erg_compiler/module/promise.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl SharedPromises {
171171
}
172172

173173
pub fn wait_until_finished(&self, path: &NormalizedPathBuf) {
174-
if self.promises.borrow().get(path).is_none() {
174+
if !self.graph.entries().contains(path) {
175175
panic!("not registered: {path}");
176176
}
177177
while !self.is_finished(path) {

0 commit comments

Comments
 (0)