Please note that this question is not about how to change the code below to make it work; rather, I am looking for some insight on why a compiler would find this assignment ambiguous:
entity assignment_to_aggregates is
end;
architecture example of assignment_to_aggregates is
type vowel_type is (a, e, i, o, u);
type consonant_type is (b, c, d, f, g);
type vowel_consonant_pair is record
vowel: vowel_type;
consonant: consonant_type;
end record;
signal my_vowel: vowel_type;
signal my_consonant: consonant_type;
begin
(my_vowel, my_consonant) <= (a, b); -- Doesn't work: "Ambiguous types in signal assignment statement."
end;
I have tested it with Modelsim Altera 10.1b and GHDL 0.29.1 and I'm seeing the following error messages:
VCOM: (vcom-1349) Ambiguous types in signal assignment statement
Possible target types are:
vowel_consonant_pair
ieee.std_logic_1164.STD_ULOGIC_VECTOR
std.STANDARD.TIME_VECTOR
std.STANDARD.REAL_VECTOR
std.STANDARD.INTEGER_VECTOR
std.STANDARD.BIT_VECTOR
std.STANDARD.BOOLEAN_VECTOR
std.STANDARD.STRING
GHDL: type of waveform is unknown, use type qualifier
Of course, if I declare a new type explicitly (vowel_consonant_pair in the sample code) and use type qualification, it works fine:
(my_vowel, my_consonant) <= vowel_consonant_pair'(a, b); -- Works fine
But why should this be necessary, if there is absolutely no other type that could match the aggregate on the right-hand side of the assignment? Is this a tool problem, or is this a VHDL semantics problem? If the latter, could someone please provide a LRM reference?
Quoted from my answer to the previous question:
Add a bit more:
-1993, 0.2 Structure and terminology of this document (see -2008, 1.3/1.3.1:
It's a semantic restriction, 'must' carries a mandatory weight, a condition that must be met will otherwise generate and error in VHDL. The type of the aggregate isn't known without qualification. Note 'that' must has been supplanted by 'shall' in the 2008 version of the standard.
The type in question here is of the target (the left hand side). We're bound by to the requirement in the section on sequential signal assignment for the concurrent signal assignment statement by the first sentence of the section on concurrent signal assignment, IEEE Std 1076-2008:
(Also found in -1993, 9.5).
Type is generally carried as an attribute on a name, but the aggregate isn't a named object. It's possible to get the type from the right hand side except it's an aggregate too:
Nick Gasson's VHDL analyzer/simulator nvc points a little more elegantly to where to fix the problem:
(Following a fix for an elaboration 'crash' caused by a missing semantic check found using a previous stackoverflow VHDL question).
How can you type the right hand side?
From IEEE Std 1076-1993:
There isn't a glossary definition of 'context' in any of the VHDL standard versions. A working definition might include the notion that the declaration for something is visible, which isn't the case for the type of an aggregate without qualification.
I wrote the answer to the previous question and I introduced the record type declaration specifically to address the lack of ability to decorate the aggregate with a type mark in a qualified expression. Note that there is no subtype (signal and) declared as a vowel_consonant_pair record. The type declaration was needed, not an actual record.
Also note I submitted a bug on ghdl-0.31 which has been fixed source tree but there hasn't been an actual release since - ghdl barfs when it can't discern the type of an aggregate. A newer version of ghdl won't crash if you don't qualify the expression.
Questions on stackoverflow generally make a wonderful contribution to improving open source VHDL tools.
I keep the standards handy and usually am able to cite chapter and verse. It can be a lot of work, there's very little you can't find out about VHDL by a thorough reading of the standard although there isn't a permuted index and you have to be inculcated in the terminology to understand the significance of what you read.
Like the answer to your current question a reference in the standard can lead to another part of the standard.
The comp.lang.vhdl FAQ quoted by Jim Lewis in a recent answer is a wonderful reference but sometimes lacks authoritative emphasis, using references to the -1993 standard sparingly.
See the FAQ, 4.2.18 How to Resolve Type Ambiguities in Expressions.
Your confusion seems to stem from the Modelsim error messages suggesting 'possible' types needed to resolve ambiguity. Note the first sentence in the 4.2.18:
And an aggregate is an expression (See 7.3.2/9.3.3 Aggregates, -1993/-2008).
Most of the possible type declarations provided by the vcom errror message are not accurate for the aggregate which is comprised of two disparate type elements - a is an enumeration name for a value of vowel_type and b is an enumeration for a value of consonant_type.
The types provided with the vcom error appear to be all the composite types made visible by local declaration (vowel_consonant_pair) or context clause (std_ulogic_vector, real_vector, integer_vector, bit_vector, boolean_vector, string, collectively found in ieee.std_logic_1164 or std.standard).
Of that bunch only one would be valid (vowel_consonant_pair). Notice the VHDL analyzer didn't guess, instead requiring the correct type to be made available from context as an object decoration (type qualification) as a result of a semantic rule (Signal assignment statement 8.4/10.5.2.1, "...the type of the aggregate must be determinable from the context, excluding the aggregate itself but including the fact that the type of the aggregate must be a composite type"). The rule giving the list of possible candidates, available composite types while disallowing guessing ("excluding the aggregate itself").