Skip to content

Commit 56c110c

Browse files
authored
feat!: Make NamedOp private. Add MakeExtensionOp::name and MakeOpDef::opdef_name (#2138)
BREAKING CHANGE: `NamedOp` is no longer public. Use `OpType`'s `Display` impl for a short string describing the OpType. BREAKING CHANGE: New required trait method `opdef_name` on `MakeOpDef` BREAKING CHANGE: New required trait method `name` on `MakeExtensionOp`
1 parent 9a1b615 commit 56c110c

35 files changed

+329
-288
lines changed

hugr-core/src/export.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ impl<'a> Context<'a> {
447447
}
448448

449449
OpType::OpaqueOp(op) => {
450-
let node = self.make_named_global_ref(op.extension(), op.op_name());
450+
let node = self.make_named_global_ref(op.extension(), op.unqualified_id());
451451
let params = self
452452
.bump
453453
.alloc_slice_fill_iter(op.args().iter().map(|arg| self.export_type_arg(arg)));

hugr-core/src/extension.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@ trait CustomConcrete {
466466
impl CustomConcrete for OpaqueOp {
467467
type Identifier = OpName;
468468

469-
fn def_name(&self) -> &OpName {
470-
self.op_name()
469+
fn def_name(&self) -> &Self::Identifier {
470+
self.unqualified_id()
471471
}
472472

473473
fn type_args(&self) -> &[TypeArg] {

hugr-core/src/extension/prelude.rs

+36-31
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,12 @@ impl ConstFold for TupleOpDef {
595595
}
596596
}
597597
}
598+
598599
impl MakeOpDef for TupleOpDef {
600+
fn opdef_id(&self) -> OpName {
601+
<&'static str>::from(self).into()
602+
}
603+
599604
fn init_signature(&self, _extension_ref: &Weak<Extension>) -> SignatureFunc {
600605
let rv = TypeRV::new_row_var_use(0, TypeBound::Any);
601606
let tuple_type = TypeRV::new_tuple(vec![rv.clone()]);
@@ -649,20 +654,18 @@ impl MakeTuple {
649654
}
650655
}
651656

652-
impl NamedOp for MakeTuple {
653-
fn name(&self) -> OpName {
654-
TupleOpDef::MakeTuple.name()
657+
impl MakeExtensionOp for MakeTuple {
658+
fn op_id(&self) -> OpName {
659+
TupleOpDef::MakeTuple.opdef_id()
655660
}
656-
}
657661

658-
impl MakeExtensionOp for MakeTuple {
659662
fn from_extension_op(ext_op: &crate::ops::ExtensionOp) -> Result<Self, OpLoadError>
660663
where
661664
Self: Sized,
662665
{
663666
let def = TupleOpDef::from_def(ext_op.def())?;
664667
if def != TupleOpDef::MakeTuple {
665-
return Err(OpLoadError::NotMember(ext_op.def().name().to_string()))?;
668+
return Err(OpLoadError::NotMember(ext_op.unqualified_id().to_string()))?;
666669
}
667670
let [TypeArg::Sequence { elems }] = ext_op.args() else {
668671
return Err(SignatureError::InvalidTypeArgs)?;
@@ -711,20 +714,18 @@ impl UnpackTuple {
711714
}
712715
}
713716

714-
impl NamedOp for UnpackTuple {
715-
fn name(&self) -> OpName {
716-
TupleOpDef::UnpackTuple.name()
717+
impl MakeExtensionOp for UnpackTuple {
718+
fn op_id(&self) -> OpName {
719+
TupleOpDef::UnpackTuple.opdef_id()
717720
}
718-
}
719721

720-
impl MakeExtensionOp for UnpackTuple {
721722
fn from_extension_op(ext_op: &crate::ops::ExtensionOp) -> Result<Self, OpLoadError>
722723
where
723724
Self: Sized,
724725
{
725726
let def = TupleOpDef::from_def(ext_op.def())?;
726727
if def != TupleOpDef::UnpackTuple {
727-
return Err(OpLoadError::NotMember(ext_op.def().name().to_string()))?;
728+
return Err(OpLoadError::NotMember(ext_op.unqualified_id().to_string()))?;
728729
}
729730
let [TypeArg::Sequence { elems }] = ext_op.args() else {
730731
return Err(SignatureError::InvalidTypeArgs)?;
@@ -760,28 +761,30 @@ impl MakeRegisteredOp for UnpackTuple {
760761
}
761762
}
762763

764+
/// Name of the no-op operation.
765+
pub const NOOP_OP_ID: OpName = OpName::new_inline("Noop");
766+
763767
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
764768
/// A no-op operation definition.
765769
pub struct NoopDef;
766770

767-
impl NamedOp for NoopDef {
768-
fn name(&self) -> OpName {
769-
"Noop".into()
770-
}
771-
}
772-
773771
impl std::str::FromStr for NoopDef {
774772
type Err = ();
775773

776774
fn from_str(s: &str) -> Result<Self, Self::Err> {
777-
if s == NoopDef.name() {
775+
if s == NoopDef.op_id() {
778776
Ok(Self)
779777
} else {
780778
Err(())
781779
}
782780
}
783781
}
782+
784783
impl MakeOpDef for NoopDef {
784+
fn opdef_id(&self) -> OpName {
785+
NOOP_OP_ID
786+
}
787+
785788
fn init_signature(&self, _extension_ref: &Weak<Extension>) -> SignatureFunc {
786789
let tv = Type::new_var_use(0, TypeBound::Any);
787790
PolyFuncType::new([TypeBound::Any.into()], Signature::new_endo(tv)).into()
@@ -836,13 +839,12 @@ impl Default for Noop {
836839
Self(Type::UNIT)
837840
}
838841
}
839-
impl NamedOp for Noop {
840-
fn name(&self) -> OpName {
841-
NoopDef.name()
842-
}
843-
}
844842

845843
impl MakeExtensionOp for Noop {
844+
fn op_id(&self) -> OpName {
845+
NoopDef.op_id()
846+
}
847+
846848
fn from_extension_op(ext_op: &crate::ops::ExtensionOp) -> Result<Self, OpLoadError>
847849
where
848850
Self: Sized,
@@ -875,17 +877,12 @@ pub struct BarrierDef;
875877

876878
/// Name of the barrier operation.
877879
pub const BARRIER_OP_ID: OpName = OpName::new_inline("Barrier");
878-
impl NamedOp for BarrierDef {
879-
fn name(&self) -> OpName {
880-
BARRIER_OP_ID
881-
}
882-
}
883880

884881
impl std::str::FromStr for BarrierDef {
885882
type Err = ();
886883

887884
fn from_str(s: &str) -> Result<Self, Self::Err> {
888-
if s == BarrierDef.name() {
885+
if s == BarrierDef.op_id() {
889886
Ok(Self)
890887
} else {
891888
Err(())
@@ -894,6 +891,10 @@ impl std::str::FromStr for BarrierDef {
894891
}
895892

896893
impl MakeOpDef for BarrierDef {
894+
fn opdef_id(&self) -> OpName {
895+
BARRIER_OP_ID
896+
}
897+
897898
fn init_signature(&self, _extension_ref: &Weak<Extension>) -> SignatureFunc {
898899
PolyFuncTypeRV::new(
899900
vec![TypeParam::new_list(TypeBound::Any)],
@@ -940,11 +941,15 @@ impl Barrier {
940941

941942
impl NamedOp for Barrier {
942943
fn name(&self) -> OpName {
943-
BarrierDef.name()
944+
BarrierDef.op_id()
944945
}
945946
}
946947

947948
impl MakeExtensionOp for Barrier {
949+
fn op_id(&self) -> OpName {
950+
BarrierDef.op_id()
951+
}
952+
948953
fn from_extension_op(ext_op: &crate::ops::ExtensionOp) -> Result<Self, OpLoadError>
949954
where
950955
Self: Sized,

hugr-core/src/extension/prelude/generic.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::extension::OpDef;
99
use crate::extension::SignatureFunc;
1010
use crate::extension::{ConstFold, ExtensionId};
1111
use crate::ops::ExtensionOp;
12-
use crate::ops::NamedOp;
1312
use crate::ops::OpName;
1413
use crate::type_row;
1514
use crate::types::FuncValueType;
@@ -28,23 +27,17 @@ use super::{ConstUsize, PRELUDE_ID};
2827
use crate::types::type_param::TypeParam;
2928

3029
/// Name of the operation for loading generic BoundedNat parameters.
31-
pub const LOAD_NAT_OP_ID: OpName = OpName::new_inline("load_nat");
30+
pub static LOAD_NAT_OP_ID: OpName = OpName::new_inline("load_nat");
3231

3332
/// Definition of the load nat operation.
3433
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
3534
pub struct LoadNatDef;
3635

37-
impl NamedOp for LoadNatDef {
38-
fn name(&self) -> OpName {
39-
LOAD_NAT_OP_ID
40-
}
41-
}
42-
4336
impl FromStr for LoadNatDef {
4437
type Err = ();
4538

4639
fn from_str(s: &str) -> Result<Self, Self::Err> {
47-
if s == LoadNatDef.name() {
40+
if s == Self.op_id() {
4841
Ok(Self)
4942
} else {
5043
Err(())
@@ -72,6 +65,10 @@ impl ConstFold for LoadNatDef {
7265
}
7366

7467
impl MakeOpDef for LoadNatDef {
68+
fn opdef_id(&self) -> OpName {
69+
LOAD_NAT_OP_ID.clone()
70+
}
71+
7572
fn from_def(op_def: &OpDef) -> Result<Self, OpLoadError>
7673
where
7774
Self: Sized,
@@ -120,13 +117,11 @@ impl LoadNat {
120117
}
121118
}
122119

123-
impl NamedOp for LoadNat {
124-
fn name(&self) -> OpName {
125-
LOAD_NAT_OP_ID
120+
impl MakeExtensionOp for LoadNat {
121+
fn op_id(&self) -> OpName {
122+
LoadNatDef.opdef_id()
126123
}
127-
}
128124

129-
impl MakeExtensionOp for LoadNat {
130125
fn from_extension_op(ext_op: &ExtensionOp) -> Result<Self, OpLoadError>
131126
where
132127
Self: Sized,

hugr-core/src/extension/resolution/ops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub(crate) fn resolve_op_extensions<'e>(
7373
// Fail if the Extension is not in the registry, or if the Extension was
7474
// found but did not have the expected operation.
7575
let extension = extension.expect("OpaqueOp should have an extension");
76-
let Some(def) = extension.get_op(opaque.op_name()) else {
76+
let Some(def) = extension.get_op(opaque.unqualified_id()) else {
7777
return Err(OpaqueOpError::OpNotFoundInExtension {
7878
node,
7979
op: opaque.name().clone(),

hugr-core/src/extension/simple_op.rs

+36-23
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ use std::sync::Weak;
55
use strum::IntoEnumIterator;
66

77
use crate::ops::{ExtensionOp, OpName, OpNameRef};
8-
use crate::{
9-
ops::{NamedOp, OpType},
10-
types::TypeArg,
11-
Extension,
12-
};
8+
use crate::{ops::OpType, types::TypeArg, Extension};
139

1410
use super::{op_def::SignatureFunc, ExtensionBuildError, ExtensionId, OpDef, SignatureError};
1511
use delegate::delegate;
@@ -29,22 +25,24 @@ pub enum OpLoadError {
2925
WrongExtension(ExtensionId, ExtensionId),
3026
}
3127

32-
impl<T> NamedOp for T
33-
where
34-
for<'a> &'a T: Into<&'static str>,
35-
{
36-
fn name(&self) -> OpName {
37-
let s = self.into();
38-
s.into()
39-
}
40-
}
41-
4228
/// Traits implemented by types which can add themselves to [`Extension`]s as
4329
/// [`OpDef`]s or load themselves from an [`OpDef`].
4430
///
4531
/// Particularly useful with C-style enums that implement [strum::IntoEnumIterator],
4632
/// as then all definitions can be added to an extension at once.
47-
pub trait MakeOpDef: NamedOp {
33+
///
34+
/// [MakeExtensionOp] has a blanket impl for types that impl [MakeOpDef].
35+
pub trait MakeOpDef {
36+
/// The [OpDef::name] which will be used when `Self` is added to an [Extension]
37+
/// or when `Self` is loaded from an [OpDef].
38+
///
39+
/// This identifer must be unique within the extension with which the
40+
/// [OpDef] is registered. An [ExtensionOp] instantiating this [OpDef] will
41+
/// report `self.opdef_id()` as its [ExtensionOp::unqualified_id].
42+
///
43+
/// [MakeExtensionOp::op_id] must match this function.
44+
fn opdef_id(&self) -> OpName;
45+
4846
/// Try to load one of the operations of this set from an [OpDef].
4947
fn from_def(op_def: &OpDef) -> Result<Self, OpLoadError>
5048
where
@@ -68,9 +66,9 @@ pub trait MakeOpDef: NamedOp {
6866
self.init_signature(&self.extension_ref())
6967
}
7068

71-
/// Description of the operation. By default, the same as `self.name()`.
69+
/// Description of the operation. By default, the same as `self.opdef_id()`.
7270
fn description(&self) -> String {
73-
self.name().to_string()
71+
self.opdef_id().to_string()
7472
}
7573

7674
/// Edit the opdef before finalising. By default does nothing.
@@ -87,7 +85,7 @@ pub trait MakeOpDef: NamedOp {
8785
extension_ref: &Weak<Extension>,
8886
) -> Result<(), ExtensionBuildError> {
8987
let def = extension.add_op(
90-
self.name(),
88+
self.opdef_id(),
9189
self.description(),
9290
self.init_signature(extension_ref),
9391
extension_ref,
@@ -150,7 +148,14 @@ pub trait HasDef: MakeExtensionOp {
150148

151149
/// Traits implemented by types which can be loaded from [`ExtensionOp`]s,
152150
/// i.e. concrete instances of [`OpDef`]s, with defined type arguments.
153-
pub trait MakeExtensionOp: NamedOp {
151+
pub trait MakeExtensionOp {
152+
/// The [OpDef::name] of [ExtensionOp]s from which `Self` can be loaded.
153+
///
154+
/// This identifer must be unique within the extension with which the
155+
/// [OpDef] is registered. An [ExtensionOp] instantiating this [OpDef] will
156+
/// report `self.opdef_id()` as its [ExtensionOp::unqualified_id].
157+
fn op_id(&self) -> OpName;
158+
154159
/// Try to load one of the operations of this set from an [OpDef].
155160
fn from_extension_op(ext_op: &ExtensionOp) -> Result<Self, OpLoadError>
156161
where
@@ -188,6 +193,10 @@ pub trait MakeExtensionOp: NamedOp {
188193

189194
/// Blanket implementation for non-polymorphic operations - [OpDef]s with no type parameters.
190195
impl<T: MakeOpDef> MakeExtensionOp for T {
196+
fn op_id(&self) -> OpName {
197+
self.opdef_id()
198+
}
199+
191200
#[inline]
192201
fn from_extension_op(ext_op: &ExtensionOp) -> Result<Self, OpLoadError>
193202
where
@@ -243,7 +252,7 @@ impl<T: MakeExtensionOp> RegisteredOp<T> {
243252
/// Generate an [OpType].
244253
pub fn to_extension_op(&self) -> Option<ExtensionOp> {
245254
ExtensionOp::new(
246-
self.extension.upgrade()?.get_op(&self.name())?.clone(),
255+
self.extension.upgrade()?.get_op(&self.op_id())?.clone(),
247256
self.type_args(),
248257
)
249258
.ok()
@@ -252,7 +261,7 @@ impl<T: MakeExtensionOp> RegisteredOp<T> {
252261
delegate! {
253262
to self.op {
254263
/// Name of the operation - derived from strum serialization.
255-
pub fn name(&self) -> OpName;
264+
pub fn op_id(&self) -> OpName;
256265
/// Any type args which define this operation. Default is no type arguments.
257266
pub fn type_args(&self) -> Vec<TypeArg>;
258267
}
@@ -310,6 +319,10 @@ mod test {
310319
}
311320

312321
impl MakeOpDef for DummyEnum {
322+
fn opdef_id(&self) -> OpName {
323+
<&'static str>::from(self).into()
324+
}
325+
313326
fn init_signature(&self, _extension_ref: &Weak<Extension>) -> SignatureFunc {
314327
Signature::new_endo(type_row![]).into()
315328
}
@@ -366,7 +379,7 @@ mod test {
366379
let o = DummyEnum::Dumb;
367380

368381
assert_eq!(
369-
DummyEnum::from_def(EXT.get_op(&o.name()).unwrap()).unwrap(),
382+
DummyEnum::from_def(EXT.get_op(&o.opdef_id()).unwrap()).unwrap(),
370383
o
371384
);
372385

0 commit comments

Comments
 (0)