Skip to content

Commit 0cf5980

Browse files
committed
Fix: Track interface package map kind to avoid incorrect package association instance flagging
1 parent 411b524 commit 0cf5980

11 files changed

Lines changed: 88 additions & 14 deletions

File tree

vhdl_lang/src/analysis/association.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ impl<'a> AnalyzeContext<'a, '_> {
662662
if let ResolvedName::Design(actual_pkg) = resolved {
663663
let actual_region = match actual_pkg.kind() {
664664
Design::PackageInstance(r)
665-
| Design::InterfacePackageInstance(r) => Some(r),
665+
| Design::InterfacePackageInstance(_, r) => Some(r),
666666
_ => None,
667667
};
668668
if let Some(actual_region) = actual_region {

vhdl_lang/src/analysis/declarative.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,10 +968,16 @@ impl<'a> AnalyzeContext<'a, '_> {
968968
diagnostics,
969969
)?;
970970

971+
let map_kind = match instance.generic_map.item {
972+
InterfacePackageGenericMapAspect::Map(_) => InterfacePackageMapKind::Map,
973+
InterfacePackageGenericMapAspect::Box => InterfacePackageMapKind::Box,
974+
InterfacePackageGenericMapAspect::Default => InterfacePackageMapKind::Default,
975+
};
976+
971977
vec![self.define(
972978
&mut instance.ident,
973979
parent,
974-
AnyEntKind::Design(Design::InterfacePackageInstance(package_region)),
980+
AnyEntKind::Design(Design::InterfacePackageInstance(map_kind, package_region)),
975981
span,
976982
)]
977983
}
@@ -1284,7 +1290,7 @@ fn get_entity_class(ent: EntRef<'_>) -> Option<EntityClass> {
12841290
Design::PackageBody(..) => None,
12851291
Design::UninstPackage(_, _) => None,
12861292
Design::PackageInstance(_) => None,
1287-
Design::InterfacePackageInstance(_) => None,
1293+
Design::InterfacePackageInstance(..) => None,
12881294
Design::Context(_) => None,
12891295
},
12901296
AnyEntKind::View(_) => None,

vhdl_lang/src/analysis/design_unit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ impl<'a> AnalyzeContext<'a, '_> {
679679
}
680680
Design::Package(_, ref primary_region)
681681
| Design::PackageInstance(ref primary_region)
682-
| Design::InterfacePackageInstance(ref primary_region) => {
682+
| Design::InterfacePackageInstance(_, ref primary_region) => {
683683
scope.make_all_potentially_visible(
684684
Some(&name.pos(self.ctx)),
685685
primary_region,

vhdl_lang/src/analysis/package_instance.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,9 @@ impl<'a> AnalyzeContext<'a, '_> {
207207
Design::PackageInstance(region) => AnyEntKind::Design(Design::PackageInstance(
208208
self.map_region(parent, mapping, region, scope)?,
209209
)),
210-
Design::InterfacePackageInstance(region) => {
210+
Design::InterfacePackageInstance(map_kind, region) => {
211211
AnyEntKind::Design(Design::InterfacePackageInstance(
212+
*map_kind,
212213
self.map_region(parent, mapping, region, scope)?,
213214
))
214215
}

vhdl_lang/src/analysis/tests/package_instance.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,3 +869,38 @@ end architecture;
869869
let diagnostics = builder.analyze();
870870
check_no_diagnostics(&diagnostics);
871871
}
872+
873+
// Regression test for https://github.com/VHDL-LS/rust_hdl/issues/460
874+
#[test]
875+
fn interface_package_with_explicit_generic_map_does_not_require_association() {
876+
let mut builder = LibraryBuilder::new();
877+
builder.code(
878+
"libname",
879+
"
880+
package example_pkg is
881+
generic (
882+
G_GENERIC : integer
883+
);
884+
end package;
885+
886+
entity example is
887+
generic (
888+
package example_pkg is new work.example_pkg
889+
generic map (
890+
G_GENERIC => 1
891+
)
892+
);
893+
end entity;
894+
895+
architecture rtl of example is
896+
begin
897+
898+
inst: entity work.example;
899+
900+
end architecture;
901+
",
902+
);
903+
904+
let diagnostics = builder.analyze();
905+
check_no_diagnostics(&diagnostics);
906+
}

vhdl_lang/src/completion/generic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ fn visible_entities_from<'a>(
131131
completion_items_from_visibility(root, visibility),
132132
)
133133
.collect_vec(),
134-
PackageInstance(region) | InterfacePackageInstance(region) | Context(region) => {
134+
PackageInstance(region) | InterfacePackageInstance(_, region) | Context(region) => {
135135
completion_items_from_region(root, region).collect_vec()
136136
}
137137
Configuration => vec![],

vhdl_lang/src/completion/selected.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn completions_for_design<'a>(
6161
) -> Vec<CompletionItem<'a>> {
6262
use crate::named_entity::Design::*;
6363
match design {
64-
Package(_, region) | PackageInstance(region) | InterfacePackageInstance(region) => {
64+
Package(_, region) | PackageInstance(region) | InterfacePackageInstance(_, region) => {
6565
completion_items_from_region(root, region)
6666
.chain(once(CompletionItem::Keyword(All)))
6767
.collect()

vhdl_lang/src/named_entity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use overloaded::{Overloaded, OverloadedEnt, Signature, SignatureKey, Subprog
2020
mod object;
2121
pub use object::{InterfaceMode, Object, ObjectEnt, ObjectInterface, ViewEnt};
2222
mod design;
23-
pub use design::{Design, DesignEnt};
23+
pub use design::{Design, DesignEnt, InterfacePackageMapKind};
2424
mod attribute;
2525
pub use attribute::AttributeEnt;
2626
mod arena;

vhdl_lang/src/named_entity/design.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,31 @@ use crate::ast::WithRef;
1313
use crate::named_entity::visibility::Visibility;
1414
use crate::Diagnostic;
1515

16+
/// LRM 6.5.5: Discriminates the three forms an interface-package's
17+
/// `generic_map_aspect` may take.
18+
/// [`crate::ast::InterfacePackageGenericMapAspect`].
19+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20+
pub enum InterfacePackageMapKind {
21+
/// `generic map (a => x, ...)` - fully bound at declaration; the enclosing
22+
/// generic clause is the only place the package's generics are associated.
23+
Map,
24+
/// `generic map (<>)` - unbound; the enclosing entity/package/subprogram's
25+
/// instantiation must associate this interface package.
26+
Box,
27+
/// `generic map (default)` - bound via the named package's default values
28+
/// for its generics.
29+
Default,
30+
}
31+
32+
impl InterfacePackageMapKind {
33+
/// Returns whether the enclosing instantiation is *not* required to
34+
/// associate this interface package - i.e., it is fully bound at the
35+
/// declaration site.
36+
pub fn has_default(self) -> bool {
37+
matches!(self, Self::Map | Self::Default)
38+
}
39+
}
40+
1641
#[derive(Clone)]
1742
pub enum Design<'a> {
1843
Entity(Visibility<'a>, Region<'a>),
@@ -34,7 +59,10 @@ pub enum Design<'a> {
3459
/// package foo is new bar generic map (<>)
3560
/// )
3661
/// ```
37-
InterfacePackageInstance(Region<'a>),
62+
/// The [`InterfacePackageMapKind`] records which of the three forms of
63+
/// `generic_map_aspect` was used; this drives whether the enclosing
64+
/// instantiation must associate the interface package.
65+
InterfacePackageInstance(InterfacePackageMapKind, Region<'a>),
3866
Context(Region<'a>),
3967
}
4068

@@ -48,7 +76,7 @@ impl Design<'_> {
4876
Package(..) => "package",
4977
PackageBody(..) => "package body",
5078
UninstPackage(..) => "uninstantiated package",
51-
PackageInstance(_) | InterfacePackageInstance(_) => "package instance",
79+
PackageInstance(_) | InterfacePackageInstance(..) => "package instance",
5280
Context(..) => "context",
5381
}
5482
}
@@ -88,7 +116,7 @@ impl<'a> DesignEnt<'a> {
88116
match self.kind() {
89117
Design::Package(_, ref region)
90118
| Design::PackageInstance(ref region)
91-
| Design::InterfacePackageInstance(ref region) => {
119+
| Design::InterfacePackageInstance(_, ref region) => {
92120
if let Some(decl) = region.lookup_immediate(suffix.designator()) {
93121
Ok(decl.clone())
94122
} else {

vhdl_lang/src/named_entity/formal_region.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl<'a> InterfaceEnt<'a> {
4040
AnyEntKind::InterfaceFile(_) => {
4141
Some(InterfaceEnt::File(FileEnt::from_any(ent).unwrap()))
4242
}
43-
AnyEntKind::Design(Design::InterfacePackageInstance(_)) => {
43+
AnyEntKind::Design(Design::InterfacePackageInstance(..)) => {
4444
Some(InterfaceEnt::Package(DesignEnt::from_any(ent).unwrap()))
4545
}
4646
AnyEntKind::Type(Type::Interface) => {
@@ -56,6 +56,10 @@ impl<'a> InterfaceEnt<'a> {
5656
pub fn has_default(&self) -> bool {
5757
match self {
5858
InterfaceEnt::Object(o) => o.kind().has_default,
59+
InterfaceEnt::Package(pkg) => match pkg.kind() {
60+
Design::InterfacePackageInstance(map_kind, _) => map_kind.has_default(),
61+
_ => false,
62+
},
5963
_ => false,
6064
}
6165
}
@@ -124,7 +128,7 @@ impl<'a> GpkgInterfaceEnt<'a> {
124128
AnyEntKind::Overloaded(Overloaded::InterfaceSubprogram(_)) => Some(
125129
GpkgInterfaceEnt::Subprogram(OverloadedEnt::from_any(ent).unwrap()),
126130
),
127-
AnyEntKind::Design(Design::InterfacePackageInstance(_)) => {
131+
AnyEntKind::Design(Design::InterfacePackageInstance(..)) => {
128132
Some(GpkgInterfaceEnt::Package(DesignEnt::from_any(ent).unwrap()))
129133
}
130134
_ => None,

0 commit comments

Comments
 (0)