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