forked from M-Labs/nac3
core: Add report_type_error to enable more code reuse
This commit is contained in:
parent
c820daf5f8
commit
bc40a32524
|
@ -4,13 +4,12 @@ use std::iter::once;
|
||||||
use std::ops::Not;
|
use std::ops::Not;
|
||||||
use std::{cell::RefCell, sync::Arc};
|
use std::{cell::RefCell, sync::Arc};
|
||||||
|
|
||||||
use super::typedef::OperatorInfo;
|
|
||||||
use super::{
|
use super::{
|
||||||
magic_methods::*,
|
magic_methods::*,
|
||||||
type_error::TypeError,
|
type_error::{TypeError, TypeErrorKind},
|
||||||
typedef::{
|
typedef::{
|
||||||
into_var_map, iter_type_vars, Call, CallId, FunSignature, FuncArg, RecordField, Type,
|
into_var_map, iter_type_vars, Call, CallId, FunSignature, FuncArg, OperatorInfo,
|
||||||
TypeEnum, TypeVar, Unifier, VarMap,
|
RecordField, RecordKey, Type, TypeEnum, TypeVar, Unifier, VarMap,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -114,6 +113,14 @@ fn report_error<T>(msg: &str, location: Location) -> Result<T, HashSet<String>>
|
||||||
Err(HashSet::from([format!("{msg} at {location}")]))
|
Err(HashSet::from([format!("{msg} at {location}")]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn report_type_error<T>(
|
||||||
|
kind: TypeErrorKind,
|
||||||
|
loc: Option<Location>,
|
||||||
|
unifier: &Unifier,
|
||||||
|
) -> Result<T, HashSet<String>> {
|
||||||
|
Err(HashSet::from([TypeError::new(kind, loc).to_display(unifier).to_string()]))
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Fold<()> for Inferencer<'a> {
|
impl<'a> Fold<()> for Inferencer<'a> {
|
||||||
type TargetU = Option<Type>;
|
type TargetU = Option<Type>;
|
||||||
type Error = HashSet<String>;
|
type Error = HashSet<String>;
|
||||||
|
@ -1659,9 +1666,11 @@ impl<'a> Inferencer<'a> {
|
||||||
// just a fast path
|
// just a fast path
|
||||||
match (fields.get(&attr), ctx == ExprContext::Store) {
|
match (fields.get(&attr), ctx == ExprContext::Store) {
|
||||||
(Some((ty, true)), _) | (Some((ty, false)), false) => Ok(*ty),
|
(Some((ty, true)), _) | (Some((ty, false)), false) => Ok(*ty),
|
||||||
(Some((_, false)), true) => {
|
(Some((ty, false)), true) => report_type_error(
|
||||||
report_error(&format!("Field `{attr}` is immutable"), value.location)
|
TypeErrorKind::MutationError(RecordKey::Str(attr), *ty),
|
||||||
}
|
Some(value.location),
|
||||||
|
self.unifier,
|
||||||
|
),
|
||||||
(None, mutable) => {
|
(None, mutable) => {
|
||||||
// Check whether it is a class attribute
|
// Check whether it is a class attribute
|
||||||
let defs = self.top_level.definitions.read();
|
let defs = self.top_level.definitions.read();
|
||||||
|
@ -1683,13 +1692,11 @@ impl<'a> Inferencer<'a> {
|
||||||
&format!("Class Attribute `{attr}` is immutable"),
|
&format!("Class Attribute `{attr}` is immutable"),
|
||||||
value.location,
|
value.location,
|
||||||
),
|
),
|
||||||
None => {
|
None => report_type_error(
|
||||||
let t = self.unifier.stringify(ty);
|
TypeErrorKind::NoSuchField(RecordKey::Str(attr), ty),
|
||||||
report_error(
|
Some(value.location),
|
||||||
&format!("`{t}::{attr}` field/method does not exist"),
|
self.unifier,
|
||||||
value.location,
|
),
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue