Possibly fix binop type inference infinite recursion
This commit is contained in:
parent
7ca8949e8c
commit
60860498df
6
examples/a.reid
Normal file
6
examples/a.reid
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
pub fn main() -> u32 {
|
||||||
|
let b = 4;
|
||||||
|
let c = b + 4;
|
||||||
|
return c;
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::mir::VagueType as Vague;
|
use crate::mir::VagueType as Vague;
|
||||||
use crate::mir::*;
|
use crate::mir::*;
|
||||||
use typecheck::ErrorTypedefKind;
|
use typecheck::ErrorTypedefKind;
|
||||||
@ -291,7 +293,7 @@ impl TypeKind {
|
|||||||
|
|
||||||
pub(super) fn resolve_weak(&self, refs: &TypeRefs) -> TypeKind {
|
pub(super) fn resolve_weak(&self, refs: &TypeRefs) -> TypeKind {
|
||||||
match self {
|
match self {
|
||||||
TypeKind::Vague(Vague::TypeRef(idx)) => refs.retrieve_wide_type(*idx).unwrap(),
|
TypeKind::Vague(Vague::TypeRef(idx)) => refs.retrieve_wide_type(*idx, &mut HashSet::new()).unwrap(),
|
||||||
_ => self.clone(),
|
_ => self.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,7 +415,6 @@ impl Expression {
|
|||||||
// First find unfiltered parameters to binop
|
// First find unfiltered parameters to binop
|
||||||
let lhs_res = lhs.typecheck(state, &typerefs, HintKind::None);
|
let lhs_res = lhs.typecheck(state, &typerefs, HintKind::None);
|
||||||
let rhs_res = rhs.typecheck(state, &typerefs, HintKind::None);
|
let rhs_res = rhs.typecheck(state, &typerefs, HintKind::None);
|
||||||
dbg!(&lhs_res, &rhs_res, &ret_ty);
|
|
||||||
let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
|
let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
|
||||||
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
|
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
|
||||||
|
|
||||||
@ -433,8 +432,6 @@ impl Expression {
|
|||||||
operator: *op,
|
operator: *op,
|
||||||
});
|
});
|
||||||
|
|
||||||
dbg!(&binops);
|
|
||||||
// dbg!(&lhs_type, &rhs_type, &binops, &ret_ty, &expected_return_ty);
|
|
||||||
if let Some(binop) = binops
|
if let Some(binop) = binops
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())
|
.filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())
|
||||||
|
@ -15,7 +15,7 @@ impl<'scope> TypeRef<'scope> {
|
|||||||
/// Resolve current type in a weak manner, not resolving any Arrays or
|
/// Resolve current type in a weak manner, not resolving any Arrays or
|
||||||
/// further inner types
|
/// further inner types
|
||||||
pub fn resolve_weak(&self) -> Option<TypeKind> {
|
pub fn resolve_weak(&self) -> Option<TypeKind> {
|
||||||
Some(self.1.types.retrieve_wide_type(*self.0.borrow())?)
|
Some(self.1.types.retrieve_wide_type(*self.0.borrow(), &mut HashSet::new())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve type deeply, trying to resolve any inner types as well.
|
/// Resolve type deeply, trying to resolve any inner types as well.
|
||||||
@ -62,17 +62,16 @@ pub enum TypeRefKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeRefKind {
|
impl TypeRefKind {
|
||||||
pub fn widen(&self, types: &TypeRefs) -> TypeKind {
|
pub fn widen(&self, types: &TypeRefs, seen: &mut HashSet<usize>) -> TypeKind {
|
||||||
match self {
|
match self {
|
||||||
TypeRefKind::BinOp(op, lhs, rhs) => {
|
TypeRefKind::BinOp(op, lhs, rhs) => {
|
||||||
|
let lhs_resolved = types.cut_recursion(lhs, seen).resolve_ref(types);
|
||||||
|
let rhs_resolved = types.cut_recursion(rhs, seen).resolve_ref(types);
|
||||||
let mut binops = types
|
let mut binops = types
|
||||||
.binop_types
|
.binop_types
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|b| b.1.operator == *op)
|
.filter(|b| b.1.operator == *op)
|
||||||
.map(|b| {
|
.map(|b| b.1.narrow(&lhs_resolved, &rhs_resolved).map(|b| b.2))
|
||||||
b.1.narrow(&lhs.resolve_ref(types), &rhs.resolve_ref(types))
|
|
||||||
.map(|b| b.2)
|
|
||||||
})
|
|
||||||
.filter_map(|s| s);
|
.filter_map(|s| s);
|
||||||
if let Some(mut ty) = binops.next() {
|
if let Some(mut ty) = binops.next() {
|
||||||
while let Some(other) = binops.next() {
|
while let Some(other) = binops.next() {
|
||||||
@ -84,7 +83,7 @@ impl TypeRefKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeRefKind::Direct(ty) => match ty {
|
TypeRefKind::Direct(ty) => match ty {
|
||||||
TypeKind::Vague(VagueType::TypeRef(id)) => types.retrieve_wide_type(*id).unwrap(),
|
TypeKind::Vague(VagueType::TypeRef(id)) => types.retrieve_wide_type(*id, seen).unwrap(),
|
||||||
_ => ty.clone(),
|
_ => ty.clone(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -110,7 +109,7 @@ impl std::fmt::Display for TypeRefs {
|
|||||||
i,
|
i,
|
||||||
unsafe { *self.recurse_type_ref(idx).borrow() },
|
unsafe { *self.recurse_type_ref(idx).borrow() },
|
||||||
self.retrieve_typeref(idx),
|
self.retrieve_typeref(idx),
|
||||||
self.retrieve_wide_type(idx),
|
self.retrieve_wide_type(idx, &mut HashSet::new()),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -182,8 +181,35 @@ impl TypeRefs {
|
|||||||
self.hints.borrow().get(inner_idx).cloned()
|
self.hints.borrow().get(inner_idx).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retrieve_wide_type(&self, idx: usize) -> Option<TypeKind> {
|
pub fn retrieve_wide_type(&self, idx: usize, seen: &mut HashSet<usize>) -> Option<TypeKind> {
|
||||||
self.retrieve_typeref(idx).map(|t| t.widen(self))
|
self.retrieve_typeref(idx).map(|t| t.widen(self, seen))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cut_recursion_weak<'s>(&self, idx: usize, seen: &mut HashSet<usize>) -> Option<TypeRefKind> {
|
||||||
|
if seen.insert(idx) {
|
||||||
|
self.retrieve_typeref(idx)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn cut_recursion(&self, kind: &TypeKind, seen: &mut HashSet<usize>) -> TypeKind {
|
||||||
|
match kind {
|
||||||
|
TypeKind::Array(type_kind, len) => TypeKind::Array(Box::new(self.cut_recursion(&type_kind, seen)), *len),
|
||||||
|
TypeKind::Borrow(type_kind, mutable) => {
|
||||||
|
TypeKind::Borrow(Box::new(self.cut_recursion(&type_kind, seen)), *mutable)
|
||||||
|
}
|
||||||
|
TypeKind::UserPtr(type_kind) => TypeKind::UserPtr(Box::new(self.cut_recursion(&type_kind, seen))),
|
||||||
|
TypeKind::CodegenPtr(type_kind) => TypeKind::CodegenPtr(Box::new(self.cut_recursion(&type_kind, seen))),
|
||||||
|
TypeKind::Vague(VagueType::TypeRef(idx)) => {
|
||||||
|
if let Some(tyref) = self.cut_recursion_weak(*idx, seen) {
|
||||||
|
tyref.widen(self, seen)
|
||||||
|
} else {
|
||||||
|
TypeKind::Vague(VagueType::Unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => kind.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +355,7 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.get_unchecked(*hint2.0.borrow())
|
.get_unchecked(*hint2.0.borrow())
|
||||||
.clone()
|
.clone()
|
||||||
.widen(self.types);
|
.widen(self.types, &mut HashSet::new());
|
||||||
self.narrow_to_type(&hint1, &ty)?;
|
self.narrow_to_type(&hint1, &ty)?;
|
||||||
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
|
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
|
||||||
let hint2_typeref = self.types.retrieve_typeref(*hint2.0.borrow()).unwrap();
|
let hint2_typeref = self.types.retrieve_typeref(*hint2.0.borrow()).unwrap();
|
||||||
@ -357,10 +383,22 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(TypeRefKind::BinOp(_, lhs1, rhs1), TypeRefKind::BinOp(_, lhs2, rhs2)) => {
|
(TypeRefKind::BinOp(_, lhs1, rhs1), TypeRefKind::BinOp(_, lhs2, rhs2)) => {
|
||||||
let mut lhs_ref = self.from_type(&lhs1).unwrap();
|
let mut lhs_ref = self
|
||||||
let mut rhs_ref = self.from_type(&rhs1).unwrap();
|
.from_type(&self.types.cut_recursion(lhs1, &mut HashSet::new()))
|
||||||
lhs_ref.narrow(&self.from_type(&lhs2).unwrap());
|
.unwrap();
|
||||||
rhs_ref.narrow(&self.from_type(&rhs2).unwrap());
|
let mut rhs_ref = self
|
||||||
|
.from_type(&self.types.cut_recursion(rhs1, &mut HashSet::new()))
|
||||||
|
.unwrap();
|
||||||
|
lhs_ref.narrow(
|
||||||
|
&self
|
||||||
|
.from_type(&self.types.cut_recursion(lhs2, &mut HashSet::new()))
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
rhs_ref.narrow(
|
||||||
|
&self
|
||||||
|
.from_type(&self.types.cut_recursion(rhs2, &mut HashSet::new()))
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user