diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 80cf2c2384e5bf2f619e58947a66d22db4d73ef3..518b5f07d699dd1f3800407424add0738a7c0751 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -128,7 +128,7 @@ impl ProtocolDescription { // By now we're sure that all of the arguments are correct. So create // the connector. - return Ok(Prompt::new(&self.types, &self.heap, definition_id, 0, arguments)); + return Ok(Prompt::new(&self.types, &self.heap, definition_id, mono_index, arguments)); } fn lookup_module_root(&self, module_name: &[u8]) -> Option { diff --git a/src/protocol/parser/pass_typing.rs b/src/protocol/parser/pass_typing.rs index 83ba7e66895ce36e6bd3ea9a6b90940de032a84a..a1ed224125d4cd4370298db0fdab3d51c4fcdd6a 100644 --- a/src/protocol/parser/pass_typing.rs +++ b/src/protocol/parser/pass_typing.rs @@ -837,7 +837,7 @@ struct InferenceExpression { expr_type: InferenceType, // result type from expression expr_id: ExpressionId, // expression that is evaluated field_or_monomorph_idx: i32, // index of field, of index of monomorph array in type table - extra_data_idx: i32, // index of extra data needed for inference + extra_data_idx: i32, // index of extra data needed for inference } impl Default for InferenceExpression { @@ -1501,7 +1501,6 @@ 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]; - if extra_data.poly_vars.is_empty() { continue; } // Note that only call and literal expressions need full inference. // Select expressions also use `extra_data`, but only for temporary diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index f38043fe0a54cea496248536c5dddd5c14b647b5..280ebb993a6cd34997b1508fed97a023fb73e910 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -430,7 +430,8 @@ impl Hash for MonomorphKey { impl PartialEq for MonomorphKey { fn eq(&self, other: &Self) -> bool { if self.in_use.is_empty() { - return self.parts == other.parts; + let temp_result = self.parts == other.parts; + return temp_result; } else { // Outer type does not match if self.parts[0] != other.parts[0] { @@ -491,7 +492,7 @@ impl MonomorphTable { key: UnsafeCell::new(MonomorphKey{ parts: Vec::with_capacity(32), in_use: Vec::with_capacity(32), - }) + }), } } @@ -514,9 +515,8 @@ impl MonomorphTable { } fn get_monomorph_index(&self, parts: &[ConcreteTypePart], in_use: &[PolymorphicVariable]) -> Option { - // Note: the entire goal of this internal `MonomorphKey` is to prevent - // allocation. So: let key = unsafe { + // Clear-and-extend to, at some point, prevent future allocations let key = &mut *self.key.get(); key.parts.clear(); key.parts.extend_from_slice(parts); @@ -1043,9 +1043,15 @@ impl TypeTable { Self::check_poly_args_collision(modules, ctx, root_id, &definition.poly_vars)?; // Construct internal representation of component + // FIXME: Marking used polymorphic variables on procedures requires + // making sure that each is used in the body. For now, mark them all + // as required. let mut poly_vars = Self::create_polymorphic_variables(&definition.poly_vars); - for argument in &arguments { - Self::mark_used_polymorphic_variables(&mut poly_vars, &argument.parser_type); + // for argument in &arguments { + // Self::mark_used_polymorphic_variables(&mut poly_vars, &argument.parser_type); + // } + for poly_var in &mut poly_vars { + poly_var.is_in_use = true; } let is_polymorph = poly_vars.iter().any(|arg| arg.is_in_use); @@ -1764,7 +1770,7 @@ impl TypeTable { // If here then we can compute the memory layout of the tuple. let mut cur_offset = 0; - let mut max_alignment = 0; + let mut max_alignment = 1; let mono_info = self.mono_lookup.get_mut(breadcrumb.monomorph_idx); let mono_tuple = mono_info.variant.as_tuple_mut(); diff --git a/src/protocol/tests/parser_validation.rs b/src/protocol/tests/parser_validation.rs index 2d142af3f451423a6e95b4a7ee72d0f1b64cf2c0..00df347f92e8489a54d993c33c798ad7ba02c3ec 100644 --- a/src/protocol/tests/parser_validation.rs +++ b/src/protocol/tests/parser_validation.rs @@ -422,14 +422,45 @@ fn test_correct_tuple_polymorph_args() { " ).for_union("Option", |u| { u .assert_has_monomorph("Option<()>") - .assert_has_monomorph("Option<(u32, u64)>") - .assert_has_monomorph("Option<(Option<(u8,s8)>,Option<(s8,u8)>)>"); + .assert_has_monomorph("Option<(u32,u64)>") + .assert_has_monomorph("Option<(Option<(u8,s8)>,Option<(s8,u8)>)>") + .assert_size_alignment("Option<()>", 1, 1, 0, 0) + .assert_size_alignment("Option<(u32,u64)>", 24, 8, 0, 0) // (u32, u64) becomes size 16, alignment 8. Hence union tag is aligned to 8 + .assert_size_alignment("Option<(Option<(u8,s8)>,Option<(s8,u8)>)>", 7, 1, 0, 0); // inner unions are size 3, alignment 1. Two of those with a tag is size 7 }); } #[test] fn test_incorrect_tuple_polymorph_args() { - todo!("write"); + // Do some mismatching brackets. I don't know what else to test + Tester::new_single_source_expect_err( + "mismatch angle bracket", + " + union Option{ Some(T), None } + func f() -> u32 { + auto a = Option<(u32>)::None; + return 0; + }" + ).error(|e| { e + .assert_num(2) + .assert_msg_has(0, "closing '>'").assert_occurs_at(0, ">)::None") + .assert_msg_has(1, "match this '('").assert_occurs_at(1, "(u32>"); + }); + + Tester::new_single_source_expect_err( + "wrongly placed angle", + " + union O{ S(T), N } + func f() -> u32 { + auto a = O<()>::None; + return 0; + } + " + ).error(|e| { e + .assert_num(1) + .assert_msg_has(0, "expected typename") + .assert_occurs_at(0, " *v, + _ => DefinitionId::new_invalid(), + }; + if got_definition_id == definition_id { + append_to_full_buffer(&mono.concrete_type, mono_idx); + } } full_buffer.push(']');