fn check_literal<T>(
    context: &Context,
    raw_literal: &raw::Literal,
    expected_ty: &RcType,
    wrap_literal: impl Fn(Literal) -> T,
    wrap_array: impl Fn(Vec<T>) -> T,
) -> Result<T, TypeError> {
    match *raw_literal {
        raw::Literal::String(_, ref val) if Type::term_eq(context.string(), expected_ty) => {
            return Ok(wrap_literal(Literal::String(val.clone())));
        },
        raw::Literal::String(_, ref val) => match context.array(expected_ty) {
            Some((len, elem_ty))
                if *len == val.len().into() && Type::term_eq(elem_ty, context.u8()) =>
            {
                let elems = val
                    .bytes()
                    .map(|elem| wrap_literal(Literal::Int(elem.into(), IntFormat::Dec)))
                    .collect();

                return Ok(wrap_array(elems));
            }
            Some((len, _)) => {
                return Err(TypeError::ArrayLengthMismatch {
                    span: raw_literal.span(),
                    found_len: val.len(),
                    expected_len: len.clone(),
                });
            },
            None => {},
        },
        raw::Literal::Char(_, val) if Type::term_eq(context.char(), expected_ty) => {
            return Ok(wrap_literal(Literal::Char(val)));
        },

        // FIXME: overflow?
        raw::Literal::Int(_, ref val, _) if Type::term_eq(context.f32(), expected_ty) => {
            return Ok(wrap_literal(Literal::F32(
                val.to_f32().unwrap(),
                FloatFormat::Dec,
            )));
        },
        raw::Literal::Int(_, ref val, _) if Type::term_eq(context.f64(), expected_ty) => {
            return Ok(wrap_literal(Literal::F64(
                val.to_f64().unwrap(),
                FloatFormat::Dec,
            )));
        },
        raw::Literal::Float(_, val, format) if Type::term_eq(context.f32(), expected_ty) => {
            return Ok(wrap_literal(Literal::F32(val as f32, format)));
        },
        raw::Literal::Float(_, val, format) if Type::term_eq(context.f64(), expected_ty) => {
            return Ok(wrap_literal(Literal::F64(val, format)));
        },

        _ => {},
    }

    let (term, inferred_ty) = infer_literal(context, raw_literal, wrap_literal)?;
    if is_subtype(context, &inferred_ty, expected_ty) {
        Ok(term)
    } else {
        Err(TypeError::LiteralMismatch {
            literal_span: raw_literal.span(),
            found: raw_literal.clone(),
            expected: Box::new(expected_ty.resugar(context.resugar_env())),
        })
    }
}
/// Checks that a literal is compatible with the given type, returning the
/// elaborated literal if successful
Checks that a literal is compatible with the given type, returning the
elaborated literal if successful
Checks that a literal is compatible with the given type returning the elaborated literal if successful
fn check_literal<T>(
    context: &Context,
    raw_literal: &raw::Literal,
    expected_ty: &RcType,
    wrap_literal: impl Fn(Literal) -> T,
    wrap_array: impl Fn(Vec<T>) -> T,
) -> Result<T, TypeError> {
    match *raw_literal {
        raw::Literal::String(_, ref val) if Type::term_eq(context.string(), expected_ty) => {
            return Ok(wrap_literal(Literal::String(val.clone())));
        },
        raw::Literal::String(_, ref val) => match context.array(expected_ty) {
            Some((len, elem_ty))
                if *len == val.len().into() && Type::term_eq(elem_ty, context.u8()) =>
            {
                let elems = val
                    .bytes()
                    .map(|elem| wrap_literal(Literal::Int(elem.into(), IntFormat::Dec)))
                    .collect();
                return Ok(wrap_array(elems));
            }
            Some((len, _)) => {
                return Err(TypeError::ArrayLengthMismatch {
                    span: raw_literal.span(),
                    found_len: val.len(),
                    expected_len: len.clone(),
                });
            },
            None => {},
        },
        raw::Literal::Char(_, val) if Type::term_eq(context.char(), expected_ty) => {
            return Ok(wrap_literal(Literal::Char(val)));
        },
        // FIXME: overflow?
        raw::Literal::Int(_, ref val, _) if Type::term_eq(context.f32(), expected_ty) => {
            return Ok(wrap_literal(Literal::F32(
                val.to_f32().unwrap(),
                FloatFormat::Dec,
            )));
        },
        raw::Literal::Int(_, ref val, _) if Type::term_eq(context.f64(), expected_ty) => {
            return Ok(wrap_literal(Literal::F64(
                val.to_f64().unwrap(),
                FloatFormat::Dec,
            )));
        },
        raw::Literal::Float(_, val, format) if Type::term_eq(context.f32(), expected_ty) => {
            return Ok(wrap_literal(Literal::F32(val as f32, format)));
        },
        raw::Literal::Float(_, val, format) if Type::term_eq(context.f64(), expected_ty) => {
            return Ok(wrap_literal(Literal::F64(val, format)));
        },
        _ => {},
    }
    let (term, inferred_ty) = infer_literal(context, raw_literal, wrap_literal)?;
    if is_subtype(context, &inferred_ty, expected_ty) {
        Ok(term)
    } else {
        Err(TypeError::LiteralMismatch {
            literal_span: raw_literal.span(),
            found: raw_literal.clone(),
            expected: Box::new(expected_ty.resugar(context.resugar_env())),
        })
    }
}
fn check_literal < T > ( context : & Context , raw_literal : & raw :: Literal , expected_ty : & RcType , wrap_literal : impl Fn ( Literal ) -> T , wrap_array : impl Fn ( Vec < T > ) -> T , ) -> Result < T , TypeError > { match * raw_literal { raw :: Literal :: String ( _ , ref val ) if Type :: term_eq ( context . string ( ) , expected_ty ) => { return Ok ( wrap_literal ( Literal :: String ( val . clone ( ) ) ) ) ; } , raw :: Literal :: String ( _ , ref val ) => match context . array ( expected_ty ) { Some ( ( len , elem_ty ) ) if * len == val . len ( ) . into ( ) && Type :: term_eq ( elem_ty , context . u8 ( ) ) => { let elems = val . bytes ( ) . map ( | elem | wrap_literal ( Literal :: Int ( elem . into ( ) , IntFormat :: Dec ) ) ) . collect ( ) ; return Ok ( wrap_array ( elems ) ) ; } Some ( ( len , _ ) ) => { return Err ( TypeError :: ArrayLengthMismatch { span : raw_literal . span ( ) , found_len : val . len ( ) , expected_len : len . clone ( ) , } ) ; } , None => { } , } , raw :: Literal :: Char ( _ , val ) if Type :: term_eq ( context . char ( ) , expected_ty ) => { return Ok ( wrap_literal ( Literal :: Char ( val ) ) ) ; } , // FIXME: overflow? raw :: Literal :: Int ( _ , ref val , _ ) if Type :: term_eq ( context . f32 ( ) , expected_ty ) => { return Ok ( wrap_literal ( Literal :: F32 ( val . to_f32 ( ) . unwrap ( ) , FloatFormat :: Dec , ) ) ) ; } , raw :: Literal :: Int ( _ , ref val , _ ) if Type :: term_eq ( context . f64 ( ) , expected_ty ) => { return Ok ( wrap_literal ( Literal :: F64 ( val . to_f64 ( ) . unwrap ( ) , FloatFormat :: Dec , ) ) ) ; } , raw :: Literal :: Float ( _ , val , format ) if Type :: term_eq ( context . f32 ( ) , expected_ty ) => { return Ok ( wrap_literal ( Literal :: F32 ( val as f32 , format ) ) ) ; } , raw :: Literal :: Float ( _ , val , format ) if Type :: term_eq ( context . f64 ( ) , expected_ty ) => { return Ok ( wrap_literal ( Literal :: F64 ( val , format ) ) ) ; } , _ => { } , } let ( term , inferred_ty ) = infer_literal ( context , raw_literal , wrap_literal ) ? ; if is_subtype ( context , & inferred_ty , expected_ty ) { Ok ( term ) } else { Err ( TypeError :: LiteralMismatch { literal_span : raw_literal . span ( ) , found : raw_literal . clone ( ) , expected : Box :: new ( expected_ty . resugar ( context . resugar_env ( ) ) ) , } ) } }
Checks that a literal is compatible with the given type, returning the
elaborated literal if successful
Checks that a literal is compatible with the given type returning the elaborated literal if successful
context
&Context
raw_literal
&raw::Literal
expected_ty
&RcType
wrap_literal
impl Fn(Literal) -> T
wrap_array
impl Fn(Vec<T>) -> T
context
&Context
raw_literal
&raw::Literal
expected_ty
&RcType
wrap_literal
impl Fn(Literal) -> T
wrap_array
impl Fn(Vec<T>) -> T