Changeset - 6c13962edb01
[Not reviewed]
0 1 0
MH - 3 years ago 2022-02-18 18:05:05
contact@maxhenger.nl
WIP: More refactoring of type inference
1 file changed with 147 insertions and 74 deletions:
0 comments (0 inline, 0 general)
src/protocol/parser/pass_typing.rs
Show inline comments
 
@@ -809,7 +809,7 @@ enum SingleInferenceResult {
 
// -----------------------------------------------------------------------------
 

	
 
type InferNodeIndex = usize;
 
type ExtraIndex = usize;
 
type PolyDataIndex = usize;
 

	
 
enum DefinitionType{
 
    Component(ComponentDefinitionId),
 
@@ -843,7 +843,7 @@ struct InferenceNode {
 
    inference_rule: InferenceRule,
 
    parent_index: Option<InferNodeIndex>,
 
    field_or_monomorph_index: i32,    // index of field
 
    extra_index: ExtraIndex,            // index of extra data needed for inference
 
    poly_data_index: PolyDataIndex,            // index of extra data needed for inference
 
    type_id: TypeId,                // when applicable indexes into type table
 
}
 

	
 
@@ -1018,7 +1018,7 @@ pub(crate) struct PassTyping {
 
    reserved_type_id: TypeId,
 
    definition_type: DefinitionType,
 
    poly_vars: Vec<ConcreteType>,
 
    // Temporary variables during construction of inference rules
 
    // Temporary variables during construction of inference rulesr
 
    parent_index: Option<InferNodeIndex>,
 
    // Buffers for iteration over various types
 
    var_buffer: ScopedBuffer<VariableId>,
 
@@ -1030,35 +1030,61 @@ pub(crate) struct PassTyping {
 
    // specify these types until we're stuck or we've fully determined the type.
 
    var_types: HashMap<VariableId, VarData>,            // types of variables
 
    infer_nodes: Vec<InferenceNode>,                     // will be transferred to type table at end
 
    extra_data: Vec<ExtraData>,       // data for polymorph inference
 
    poly_data: Vec<PolyData>,       // data for polymorph inference
 
    // Keeping track of which expressions need to be reinferred because the
 
    // expressions they're linked to made progression on an associated type
 
    expr_queued: DequeSet<i32>,
 
}
 

	
 
// TODO: @Rename, this is used for a lot of type inferencing. It seems like
 
//  there is a different underlying architecture waiting to surface.
 
struct ExtraData {
 
/// Generic struct that is used to store inferred types associated with
 
/// polymorphic types.
 
struct PolyData {
 
    definition_id: DefinitionId, // the definition, only used for user feedback
 
    /// Progression of polymorphic variables (if any)
 
    /// Inferred types of the polymorphic variables as they are written down
 
    /// at the type's definition.
 
    poly_vars: Vec<InferenceType>,
 
    /// Progression of types of call arguments or struct members
 
    embedded: Vec<InferenceType>,
 
    /// Inferred types of associated types (e.g. struct fields, tuple members,
 
    /// function arguments). These types may depend on the polymorphic variables
 
    /// defined above.
 
    associated: Vec<InferenceType>,
 
    /// Inferred "returned" type (e.g. if a struct field is selected, then this
 
    /// contains the type of the selected field, for a function call it contains
 
    /// the return type). May depend on the polymorphic variables defined above.
 
    returned: InferenceType,
 
}
 

	
 
impl Default for ExtraData {
 
impl Default for PolyData {
 
    fn default() -> Self {
 
        Self{
 
            expr_id: ExpressionId::new_invalid(),
 
        Self {
 
            definition_id: DefinitionId::new_invalid(),
 
            poly_vars: Vec::new(),
 
            embedded: Vec::new(),
 
            associated: Vec::new(),
 
            returned: InferenceType::default(),
 
        }
 
    }
 
}
 

	
 
enum PolyDataTypeIndex {
 
    Associated(usize), // indexes into `PolyData.associated`
 
    Returned,
 
}
 

	
 
impl PolyData {
 
    fn get_type(&self, index: PolyDataTypeIndex) -> &InferenceType {
 
        match index {
 
            PolyDataTypeIndex::Associated(index) => return &self.associated[index],
 
            PolyDataTypeIndex::Returned => return &self.returned,
 
        }
 
    }
 

	
 
    fn get_type_mut(&mut self, index: PolyDataTypeIndex) -> &mut InferenceType {
 
        match index {
 
            PolyDataTypeIndex::Associated(index) => return &mut self.associated[index],
 
            PolyDataTypeIndex::Returned => return &mut self.returned,
 
        }
 
    }
 
}
 

	
 
struct VarData {
 
    /// Type of the variable
 
    var_type: InferenceType,
 
@@ -1091,7 +1117,7 @@ impl PassTyping {
 
            bool_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_SMALL),
 
            var_types: HashMap::new(),
 
            infer_nodes: Vec::new(),
 
            extra_data: Vec::new(),
 
            poly_data: Vec::new(),
 
            expr_queued: DequeSet::new(),
 
        }
 
    }
 
@@ -1164,7 +1190,7 @@ impl PassTyping {
 
        self.poly_vars.clear();
 
        self.var_types.clear();
 
        self.infer_nodes.clear();
 
        self.extra_data.clear();
 
        self.poly_data.clear();
 
        self.expr_queued.clear();
 
    }
 
}
 
@@ -1718,7 +1744,7 @@ impl PassTyping {
 
                // Assign rule and extra data index to inference node
 
                let extra_index = self.insert_initial_struct_polymorph_data(ctx, id);
 
                let node = &mut self.infer_nodes[self_index];
 
                node.extra_index = extra_index;
 
                node.poly_data_index = extra_index;
 
                node.inference_rule = InferenceRule::LiteralStruct(InferenceRuleLiteralStruct{
 
                    element_indices,
 
                });
 
@@ -1730,7 +1756,7 @@ impl PassTyping {
 
                // polymorphic variable
 
                let extra_index = self.insert_initial_enum_polymorph_data(ctx, id);
 
                let node = &mut self.infer_nodes[self_index];
 
                node.extra_index = extra_index;
 
                node.poly_data_index = extra_index;
 
                node.inference_rule = InferenceRule::LiteralEnum(InferenceRuleLiteralEnum{
 

	
 
                });
 
@@ -1749,7 +1775,7 @@ impl PassTyping {
 
                let element_indices = expr_indices.into_vec();
 

	
 
                let node = &mut self.infer_nodes[self_index];
 
                node.extra_index = extra_index;
 
                node.poly_data_index = extra_index;
 
                node.inference_rule = InferenceRule::LiteralUnion(InferenceRuleLiteralUnion{
 
                    element_indices,
 
                });
 
@@ -1766,7 +1792,7 @@ impl PassTyping {
 
                let element_indices = expr_indices.into_vec();
 

	
 
                let node = &mut self.infer_nodes[self_index];
 
                node.extra_index = extra_index;
 
                node.poly_data_index = extra_index;
 
                node.inference_rule = InferenceRule::LiteralArray(InferenceRuleLiteralArray{
 
                    element_indices,
 
                })
 
@@ -1821,7 +1847,7 @@ impl PassTyping {
 
        let argument_indices = expr_indices.into_vec();
 

	
 
        let node = &mut self.infer_nodes[self_index];
 
        node.extra_index = extra_index;
 
        node.poly_data_index = extra_index;
 
        node.inference_rule = InferenceRule::CallExpr(InferenceRuleCallExpr{
 
            argument_indices,
 
        });
 
@@ -1967,7 +1993,7 @@ impl PassTyping {
 

	
 
            // Extra data is attached, perform typechecking and transfer
 
            // resolved information to the expression
 
            let extra_data = &self.extra_data[infer_expr.extra_data_idx as usize];
 
            let extra_data = &self.poly_data[infer_expr.extra_data_idx as usize];
 

	
 
            // Note that only call and literal expressions need full inference.
 
            // Select expressions also use `extra_data`, but only for temporary
 
@@ -2309,7 +2335,7 @@ impl PassTyping {
 
                    // fields
 
                    let extra_index = self.insert_initial_select_polymorph_data(ctx, node_index, definition_id);
 
                    let node = &mut self.infer_nodes[node_index];
 
                    node.extra_index = extra_index;
 
                    node.poly_data_index = extra_index;
 
                },
 
                Ok(None) => {
 
                    // We don't know what to do yet, because we don't know the
 
@@ -2330,11 +2356,11 @@ impl PassTyping {
 
        // If here then the field index is known, hence we can start inferring
 
        // the type of the selected field
 
        let node = &self.infer_nodes[node_index];
 
        let poly_data = &mut self.extra_data[node.extra_index as usize];
 
        let poly_data = &mut self.poly_data[node.poly_data_index as usize];
 
        let mut poly_progress = HashSet::new(); // TODO: @Performance
 

	
 
        // Apply to struct's type
 
        let signature_type: *mut _ = &mut poly_data.embedded[0];
 
        let signature_type: *mut _ = &mut poly_data.associated[0];
 
        let subject_type: *mut _ = &mut self.infer_nodes[subject_expr_idx as usize].expr_type;
 

	
 
        let (_, progress_subject) = Self::apply_equal2_signature_constraint(
 
@@ -2353,7 +2379,7 @@ impl PassTyping {
 
        let (_, progress_expr) = Self::apply_equal2_signature_constraint(
 
            ctx, upcast_id, None, poly_data, &mut poly_progress,
 
            signature_type, 0, expr_type, 0
 
        )?;
 
         )?;
 

	
 
        if progress_expr {
 
            if let Some(parent_id) = ctx.heap[upcast_id].parent_expr_id() {
 
@@ -2363,7 +2389,7 @@ impl PassTyping {
 
        }
 

	
 
        // Reapply progress in polymorphic variables to struct's type
 
        let signature_type: *mut _ = &mut poly_data.embedded[0];
 
        let signature_type: *mut _ = &mut poly_data.associated[0];
 
        let subject_type: *mut _ = &mut self.infer_nodes[subject_expr_idx as usize].expr_type;
 

	
 
        let progress_subject = Self::apply_equal2_polyvar_constraint(
 
@@ -2917,11 +2943,11 @@ impl PassTyping {
 
                // If here then field index is known, and the referenced struct type
 
                // information is inserted into `extra_data`. Check to see if we can
 
                // do some mutual inference.
 
                let poly_data = &mut self.extra_data[extra_idx as usize];
 
                let poly_data = &mut self.poly_data[extra_idx as usize];
 
                let mut poly_progress = HashSet::new(); // TODO: @Performance
 

	
 
                // Apply to struct's type
 
                let signature_type: *mut _ = &mut poly_data.embedded[0];
 
                let signature_type: *mut _ = &mut poly_data.associated[0];
 
                let subject_type: *mut _ = &mut self.infer_nodes[subject_expr_idx as usize].expr_type;
 

	
 
                let (_, progress_subject) = Self::apply_equal2_signature_constraint(
 
@@ -2950,7 +2976,7 @@ impl PassTyping {
 
                }
 

	
 
                // Reapply progress in polymorphic variables to struct's type
 
                let signature_type: *mut _ = &mut poly_data.embedded[0];
 
                let signature_type: *mut _ = &mut poly_data.associated[0];
 
                let subject_type: *mut _ = &mut self.infer_nodes[subject_expr_idx as usize].expr_type;
 

	
 
                let progress_subject = Self::apply_equal2_polyvar_constraint(
 
@@ -3060,12 +3086,12 @@ impl PassTyping {
 
                self.apply_forced_constraint(ctx, upcast_id, &STRING_TEMPLATE)?
 
            },
 
            Literal::Struct(data) => {
 
                let extra = &mut self.extra_data[extra_idx as usize];
 
                let extra = &mut self.poly_data[extra_idx as usize];
 
                for _poly in &extra.poly_vars {
 
                    debug_log!(" * Poly: {}", _poly.display_name(&ctx.heap));
 
                }
 
                let mut poly_progress = HashSet::new();
 
                debug_assert_eq!(extra.embedded.len(), data.fields.len());
 
                debug_assert_eq!(extra.associated.len(), data.fields.len());
 

	
 
                debug_log!(" * During (inferring types from fields and struct type):");
 

	
 
@@ -3073,7 +3099,7 @@ impl PassTyping {
 
                for (field_idx, field) in data.fields.iter().enumerate() {
 
                    let field_expr_id = field.value;
 
                    let field_expr_idx = ctx.heap[field_expr_id].get_unique_id_in_definition();
 
                    let signature_type: *mut _ = &mut extra.embedded[field_idx];
 
                    let signature_type: *mut _ = &mut extra.associated[field_idx];
 
                    let field_type: *mut _ = &mut self.infer_nodes[field_expr_idx as usize].expr_type;
 
                    let (_, progress_arg) = Self::apply_equal2_signature_constraint(
 
                        ctx, upcast_id, Some(field_expr_id), extra, &mut poly_progress,
 
@@ -3122,12 +3148,12 @@ impl PassTyping {
 
                debug_log!(" * During (reinferring from progressed polyvars):");
 

	
 
                // For all field expressions
 
                for field_idx in 0..extra.embedded.len() {
 
                for field_idx in 0..extra.associated.len() {
 
                    // Note: fields in extra.embedded are in the same order as
 
                    // they are specified in the literal. Whereas
 
                    // `data.fields[...].field_idx` points to the field in the
 
                    // struct definition.
 
                    let signature_type: *mut _ = &mut extra.embedded[field_idx];
 
                    let signature_type: *mut _ = &mut extra.associated[field_idx];
 
                    let field_expr_id = data.fields[field_idx].value;
 
                    let field_expr_idx = ctx.heap[field_expr_id].get_unique_id_in_definition();
 
                    let field_type: *mut _ = &mut self.infer_nodes[field_expr_idx as usize].expr_type;
 
@@ -3157,7 +3183,7 @@ impl PassTyping {
 
                progress_expr
 
            },
 
            Literal::Enum(_) => {
 
                let extra = &mut self.extra_data[extra_idx as usize];
 
                let extra = &mut self.poly_data[extra_idx as usize];
 
                for _poly in &extra.poly_vars {
 
                    debug_log!(" * Poly: {}", _poly.display_name(&ctx.heap));
 
                }
 
@@ -3194,12 +3220,12 @@ impl PassTyping {
 
                progress_expr
 
            },
 
            Literal::Union(data) => {
 
                let extra = &mut self.extra_data[extra_idx as usize];
 
                let extra = &mut self.poly_data[extra_idx as usize];
 
                for _poly in &extra.poly_vars {
 
                    debug_log!(" * Poly: {}", _poly.display_name(&ctx.heap));
 
                }
 
                let mut poly_progress = HashSet::new();
 
                debug_assert_eq!(extra.embedded.len(), data.values.len());
 
                debug_assert_eq!(extra.associated.len(), data.values.len());
 

	
 
                debug_log!(" * During (inferring types from variant values and union type):");
 

	
 
@@ -3207,7 +3233,7 @@ impl PassTyping {
 
                for (value_idx, value_expr_id) in data.values.iter().enumerate() {
 
                    let value_expr_id = *value_expr_id;
 
                    let value_expr_idx = ctx.heap[value_expr_id].get_unique_id_in_definition();
 
                    let signature_type: *mut _ = &mut extra.embedded[value_idx];
 
                    let signature_type: *mut _ = &mut extra.associated[value_idx];
 
                    let value_type: *mut _ = &mut self.infer_nodes[value_expr_idx as usize].expr_type;
 
                    let (_, progress_arg) = Self::apply_equal2_signature_constraint(
 
                        ctx, upcast_id, Some(value_expr_id), extra, &mut poly_progress,
 
@@ -3253,8 +3279,8 @@ impl PassTyping {
 
                debug_log!(" * During (reinferring from progress polyvars):");
 
            
 
                // For all embedded values of the union variant
 
                for value_idx in 0..extra.embedded.len() {
 
                    let signature_type: *mut _ = &mut extra.embedded[value_idx];
 
                for value_idx in 0..extra.associated.len() {
 
                    let signature_type: *mut _ = &mut extra.associated[value_idx];
 
                    let value_expr_id = data.values[value_idx];
 
                    let value_expr_idx = ctx.heap[value_expr_id].get_unique_id_in_definition();
 
                    let value_type: *mut _ = &mut self.infer_nodes[value_expr_idx as usize].expr_type;
 
@@ -3463,16 +3489,16 @@ impl PassTyping {
 
        debug_log!("   - Expr type: {}", self.debug_get_display_name(ctx, upcast_id));
 
        debug_log!(" * During (inferring types from arguments and return type):");
 

	
 
        let extra = &mut self.extra_data[extra_idx as usize];
 
        let extra = &mut self.poly_data[extra_idx as usize];
 

	
 
        // Check if we can make progress using the arguments and/or return types
 
        // while keeping track of the polyvars we've extended
 
        let mut poly_progress = HashSet::new();
 
        debug_assert_eq!(extra.embedded.len(), expr.arguments.len());
 
        debug_assert_eq!(extra.associated.len(), expr.arguments.len());
 

	
 
        for (call_arg_idx, arg_id) in expr.arguments.clone().into_iter().enumerate() {
 
            let arg_expr_idx = ctx.heap[arg_id].get_unique_id_in_definition();
 
            let signature_type: *mut _ = &mut extra.embedded[call_arg_idx];
 
            let signature_type: *mut _ = &mut extra.associated[call_arg_idx];
 
            let argument_type: *mut _ = &mut self.infer_nodes[arg_expr_idx as usize].expr_type;
 
            let (_, progress_arg) = Self::apply_equal2_signature_constraint(
 
                ctx, upcast_id, Some(arg_id), extra, &mut poly_progress,
 
@@ -3522,8 +3548,8 @@ impl PassTyping {
 
        // TODO: @performance If the algorithm is changed to be more "on demand
 
        //  argument re-evaluation", instead of "all-argument re-evaluation",
 
        //  then this is no longer true
 
        for arg_idx in 0..extra.embedded.len() {
 
            let signature_type: *mut _ = &mut extra.embedded[arg_idx];
 
        for arg_idx in 0..extra.associated.len() {
 
            let signature_type: *mut _ = &mut extra.associated[arg_idx];
 
            let arg_expr_id = expr.arguments[arg_idx];
 
            let arg_expr_idx = ctx.heap[arg_expr_id].get_unique_id_in_definition();
 
            let arg_type: *mut _ = &mut self.infer_nodes[arg_expr_idx as usize].expr_type;
 
@@ -3763,6 +3789,53 @@ impl PassTyping {
 
        Ok((infer_res.modified_lhs(), infer_res.modified_rhs()))
 
    }
 

	
 
    /// Applies an equal2 constraint between a member of the `PolyData` struct,
 
    /// and another inferred type. If any progress is made in the `PolyData`
 
    /// struct then the affected polymorphic variables are updated as well.
 
    ///
 
    /// Because a lot of types/expressions are involved in polymorphic type
 
    /// inference, some explanation: "outer_node" refers to the main expression
 
    /// that is the root cause of type inference (e.g. a struct literal
 
    /// expression, or a tuple member select expression). Associated with that
 
    /// outer node is `PolyData`, so that is what the "poly_data" variables
 
    /// are referring to. We are applying equality between a "poly_data" type
 
    /// and an associated expression (not necessarily the "outer_node", e.g.
 
    /// the expression that constructs the value of a struct field). Hence the
 
    /// "associated" variables.
 
    ///
 
    /// Again a special case: the `associated_expr_id` is only used
 
    fn apply_polydata_equal2_constraint(
 
        &mut self, ctx: &Ctx,
 
        outer_node_index: InferNodeIndex, error_location_expr_id: ExpressionId, error_location_name: &str
 
        poly_data_type: PolyDataTypeIndex, poly_data_start_index: usize,
 
        associated_node_index: InferNodeIndex, associated_node_start_index: usize
 
    ) -> Result<(bool, bool), ParseError> {
 
        let poly_index = self.infer_nodes[outer_node_index].poly_data_index;
 
        let poly_data_type: *mut _ = self.poly_data[poly_index].get_type_mut(poly_data_type);
 
        let associated_type: *mut _ = &mut self.infer_nodes[associated_node_index].expr_type;
 

	
 
        let inference_result = unsafe{
 
            // Safety: pointers originate from different vectors, so cannot
 
            // alias.
 
            InferenceType::infer_subtrees_for_both_types(
 
                poly_data_type, poly_data_start_index,
 
                associated_type, associated_node_start_index
 
            )
 
        };
 

	
 
        let modified_poly_data = inference_result.modified_lhs();
 
        let modified_associated = inference_result.modified_rhs();
 
        if inference_result == DualInferenceResult::Incompatible {
 
            let outer_node_expr_id = self.infer_nodes[outer_node_index].expr_id;
 
            let outer_node_span = ctx.heap[outer_node_expr_id].full_span();
 
            let detailed_span = ctx.heap[error_location_expr_id].
 
        }
 
    }
 

	
 
    fn apply_polydata_polyvar_constraint() -> bool {
 

	
 
    }
 

	
 
    /// Applies an equal2 constraint between a signature type (e.g. a function
 
    /// argument or struct field) and an expression whose type should match that
 
    /// expression. If we make progress on the signature, then we try to see if
 
@@ -3774,7 +3847,7 @@ impl PassTyping {
 
    /// `expression_start_idx` belong to `expr_id`.
 
    fn apply_equal2_signature_constraint(
 
        ctx: &Ctx, outer_expr_id: ExpressionId, expr_id: Option<ExpressionId>,
 
        polymorph_data: &mut ExtraData, polymorph_progress: &mut HashSet<u32>,
 
        polymorph_data: &mut PolyData, polymorph_progress: &mut HashSet<u32>,
 
        signature_type: *mut InferenceType, signature_start_idx: usize,
 
        expression_type: *mut InferenceType, expression_start_idx: usize
 
    ) -> Result<(bool, bool), ParseError> {
 
@@ -3785,7 +3858,7 @@ impl PassTyping {
 
            InferenceType::infer_subtrees_for_both_types(
 
                signature_type, signature_start_idx,
 
                expression_type, expression_start_idx
 
            ) 
 
            )
 
        };
 

	
 
        if infer_res == DualInferenceResult::Incompatible {
 
@@ -3846,7 +3919,7 @@ impl PassTyping {
 
    ///
 
    /// This function returns true if the expression's type has been progressed
 
    fn apply_equal2_polyvar_constraint(
 
        polymorph_data: &ExtraData, _polymorph_progress: &HashSet<u32>,
 
        polymorph_data: &PolyData, _polymorph_progress: &HashSet<u32>,
 
        signature_type: *mut InferenceType, expr_type: *mut InferenceType
 
    ) -> bool {
 
        // Safety: all pointers should be distinct
 
@@ -4082,7 +4155,7 @@ impl PassTyping {
 

	
 
    fn insert_initial_call_polymorph_data(
 
        &mut self, ctx: &mut Ctx, call_id: CallExpressionId
 
    ) -> ExtraIndex {
 
    ) -> PolyDataIndex {
 
        // Note: the polymorph variables may be partially specified and may
 
        // contain references to the wrapping definition's (i.e. the proctype
 
        // we are currently visiting) polymorphic arguments.
 
@@ -4133,12 +4206,12 @@ impl PassTyping {
 
            }
 
        };
 

	
 
        let extra_data_idx = self.extra_data.len() as ExtraIndex;
 
        self.extra_data.push(ExtraData{
 
        let extra_data_idx = self.poly_data.len() as PolyDataIndex;
 
        self.poly_data.push(PolyData {
 
            expr_id: call_id.upcast(),
 
            definition_id: call.definition,
 
            poly_vars: poly_args,
 
            embedded: parameter_types,
 
            associated: parameter_types,
 
            returned: return_type
 
        });
 
        return extra_data_idx
 
@@ -4146,7 +4219,7 @@ impl PassTyping {
 

	
 
    fn insert_initial_struct_polymorph_data(
 
        &mut self, ctx: &mut Ctx, lit_id: LiteralExpressionId,
 
    ) -> ExtraIndex {
 
    ) -> PolyDataIndex {
 
        use InferenceTypePart as ITP;
 
        let literal = ctx.heap[lit_id].value.as_struct();
 

	
 
@@ -4195,12 +4268,12 @@ impl PassTyping {
 
        debug_assert_eq!(parts.len(), parts_reserved);
 
        let return_type = InferenceType::new(!poly_args.is_empty(), return_type_done, parts);
 

	
 
        let extra_data_index = self.extra_data.len() as ExtraIndex;
 
        self.extra_data.push(ExtraData{
 
        let extra_data_index = self.poly_data.len() as PolyDataIndex;
 
        self.poly_data.push(PolyData {
 
            expr_id: lit_id.upcast(),
 
            definition_id: literal.definition,
 
            poly_vars: poly_args,
 
            embedded: embedded_types,
 
            associated: embedded_types,
 
            returned: return_type,
 
        });
 

	
 
@@ -4212,7 +4285,7 @@ impl PassTyping {
 
    /// the use of the enum.
 
    fn insert_initial_enum_polymorph_data(
 
        &mut self, ctx: &Ctx, lit_id: LiteralExpressionId
 
    ) -> ExtraIndex {
 
    ) -> PolyDataIndex {
 
        use InferenceTypePart as ITP;
 
        let literal = ctx.heap[lit_id].value.as_enum();
 

	
 
@@ -4242,12 +4315,12 @@ impl PassTyping {
 
        debug_assert_eq!(parts.len(), parts_reserved);
 
        let enum_type = InferenceType::new(!poly_args.is_empty(), enum_type_done, parts);
 

	
 
        let extra_data_index = self.extra_data.len() as ExtraIndex;
 
        self.extra_data.push(ExtraData{
 
        let extra_data_index = self.poly_data.len() as PolyDataIndex;
 
        self.poly_data.push(PolyData {
 
            expr_id: lit_id.upcast(),
 
            definition_id: literal.definition,
 
            poly_vars: poly_args,
 
            embedded: Vec::new(),
 
            associated: Vec::new(),
 
            returned: enum_type,
 
        });
 

	
 
@@ -4258,7 +4331,7 @@ impl PassTyping {
 
    /// arguments may be partially determined from embedded values in the union.
 
    fn insert_initial_union_polymorph_data(
 
        &mut self, ctx: &Ctx, lit_id: LiteralExpressionId
 
    ) -> ExtraIndex {
 
    ) -> PolyDataIndex {
 
        use InferenceTypePart as ITP;
 
        let literal = ctx.heap[lit_id].value.as_union();
 

	
 
@@ -4303,12 +4376,12 @@ impl PassTyping {
 
        debug_assert_eq!(parts_reserved, parts.len());
 
        let union_type = InferenceType::new(!poly_args.is_empty(), union_type_done, parts);
 

	
 
        let extra_data_index = self.extra_data.len();
 
        self.extra_data.push(ExtraData{
 
        let extra_data_index = self.poly_data.len();
 
        self.poly_data.push(PolyData {
 
            expr_id: lit_id.upcast(),
 
            definition_id: literal.definition,
 
            poly_vars: poly_args,
 
            embedded,
 
            associated: embedded,
 
            returned: union_type
 
        });
 

	
 
@@ -4319,7 +4392,7 @@ impl PassTyping {
 
    /// expression's referenced (definition_id, field_idx) has been resolved.
 
    fn insert_initial_select_polymorph_data(
 
        &mut self, ctx: &Ctx, node_index: InferNodeIndex, struct_def_id: DefinitionId
 
    ) -> ExtraIndex {
 
    ) -> PolyDataIndex {
 
        use InferenceTypePart as ITP;
 

	
 
        let definition = ctx.heap[struct_def_id].as_struct();
 
@@ -4346,11 +4419,11 @@ impl PassTyping {
 
        // Generate initial field type
 
        let field_type = self.determine_inference_type_from_parser_type_elements(&definition.fields[field_index].parser_type.elements, false);
 

	
 
        let extra_data_index = self.extra_data.len() as ExtraIndex;
 
        self.extra_data.push(ExtraData{
 
        let extra_data_index = self.poly_data.len() as PolyDataIndex;
 
        self.poly_data.push(PolyData {
 
            definition_id: struct_def_id,
 
            poly_vars,
 
            embedded: vec![InferenceType::new(num_poly_vars != 0, num_poly_vars == 0, struct_parts)],
 
            associated: vec![InferenceType::new(num_poly_vars != 0, num_poly_vars == 0, struct_parts)],
 
            returned: field_type
 
        });
 

	
 
@@ -4569,7 +4642,7 @@ impl PassTyping {
 
    /// We assume that the expression is a function call or a struct literal,
 
    /// and that an actual error has occurred.
 
    fn construct_poly_arg_error(
 
        ctx: &Ctx, poly_data: &ExtraData, expr_id: ExpressionId
 
        ctx: &Ctx, poly_data: &PolyData, expr_id: ExpressionId
 
    ) -> ParseError {
 
        // Helper function to check for polymorph mismatch between two inference
 
        // types.
 
@@ -4621,7 +4694,7 @@ impl PassTyping {
 
        }
 

	
 
        // Helper function to construct initial error
 
        fn construct_main_error(ctx: &Ctx, poly_data: &ExtraData, poly_var_idx: u32, expr: &Expression) -> ParseError {
 
        fn construct_main_error(ctx: &Ctx, poly_data: &PolyData, poly_var_idx: u32, expr: &Expression) -> ParseError {
 
            match expr {
 
                Expression::Call(expr) => {
 
                    let (poly_var, func_name) = get_poly_var_and_definition_name(ctx, poly_var_idx, poly_data.definition_id);
 
@@ -4704,8 +4777,8 @@ impl PassTyping {
 
        }
 

	
 
        // - check arguments with each other argument and with return type
 
        for (arg_a_idx, arg_a) in poly_data.embedded.iter().enumerate() {
 
            for (arg_b_idx, arg_b) in poly_data.embedded.iter().enumerate() {
 
        for (arg_a_idx, arg_a) in poly_data.associated.iter().enumerate() {
 
            for (arg_b_idx, arg_b) in poly_data.associated.iter().enumerate() {
 
                if arg_b_idx > arg_a_idx {
 
                    break;
 
                }
 
@@ -4762,7 +4835,7 @@ impl PassTyping {
 

	
 
        // Now check against the explicitly specified polymorphic variables (if
 
        // any).
 
        for (arg_idx, arg) in poly_data.embedded.iter().enumerate() {
 
        for (arg_idx, arg) in poly_data.associated.iter().enumerate() {
 
            if let Some((poly_idx, poly_section, arg_section)) = has_explicit_poly_mismatch(&poly_data.poly_vars, arg) {
 
                let arg = &ctx.heap[expr_args[arg_idx]];
 
                return construct_main_error(ctx, poly_data, poly_idx, expr)
0 comments (0 inline, 0 general)