diff --git a/src/Bridges/bridge.jl b/src/Bridges/bridge.jl index 47c951b13e..5fa273c79a 100644 --- a/src/Bridges/bridge.jl +++ b/src/Bridges/bridge.jl @@ -119,6 +119,18 @@ function MOI.supports( return false end +function _attribute_error_message(attr, bridge, action) + return "Bridge of type `$(nameof(typeof(bridge)))` does not support " * + "$action the attribute `$attr`. If you encountered this error " * + "unexpectedly, it probably means your model has been " * + "reformulated using the bridge, and you are attempting to query " * + "an attribute that we haven't implemented yet for this bridge. " * + "Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new " * + "and provide a reproducible example explaining what you were " * + "trying to do." +end + + """ function MOI.get( model::MOI.ModelLike, @@ -134,18 +146,8 @@ function MOI.get( attr::MOI.AbstractConstraintAttribute, bridge::AbstractBridge, ) - return throw( - ArgumentError( - "Bridge of type `$(typeof(bridge))` does not support accessing " * - "the attribute `$attr`. If you encountered this error " * - "unexpectedly, it probably means your model has been " * - "reformulated using the bridge, and you are attempting to query " * - "an attribute that we haven't implemented yet for this bridge. " * - "Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new " * - "and provide a reproducible example explaining what you were " * - "trying to do.", - ), - ) + message = _attribute_error_message(attr, bridge, "accessing") + return throw(ArgumentError(message)) end function MOI.get( @@ -173,12 +175,13 @@ function MOI.set( model::MOI.ModelLike, attr::MOI.AbstractConstraintAttribute, bridge::AbstractBridge, - value, + _, ) + message = _attribute_error_message(attr, bridge, "setting a value for") if MOI.is_copyable(attr) && !MOI.supports(model, attr, typeof(bridge)) - throw(MOI.UnsupportedAttribute(attr)) + throw(MOI.UnsupportedAttribute(attr, message)) else - throw(MOI.SetAttributeNotAllowed(attr)) + throw(MOI.SetAttributeNotAllowed(attr, message)) end end diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index 27ce198de4..3eac55c6f1 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -218,7 +218,13 @@ MOI.Utilities.@model( (MOI.VectorAffineFunction, MOI.VectorQuadraticFunction) ) -function unsupported_constraint_attribute() +struct AttributeNotAllowed <: MOI.AbstractConstraintAttribute end + +function MOI.supports(::MOI.ModelLike, ::AttributeNotAllowed, ::Type{<:MOI.Bridges.Constraint.SplitIntervalBridge}) + return true +end + +function test_unsupported_constraint_attribute() mock = MOI.Utilities.MockOptimizer(NoIntervalModel{Float64}()) bridged_mock = MOI.Bridges.Constraint.LessToGreater{Float64}( MOI.Bridges.Constraint.SplitInterval{Float64}(mock), @@ -231,22 +237,27 @@ function unsupported_constraint_attribute() MOI.LessThan{Float64}, } attr = MOI.Test.UnknownConstraintAttribute() - err = ArgumentError( - "Bridge of type `$(bridge)` does not support accessing " * + message(action) = + "Bridge of type `$(nameof(bridge))` does not support $action " * "the attribute `$attr`. If you encountered this error " * "unexpectedly, it probably means your model has been " * "reformulated using the bridge, and you are attempting to query " * "an attribute that we haven't implemented yet for this bridge. " * "Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new " * "and provide a reproducible example explaining what you were " * - "trying to do.", - ) + "trying to do." x = MOI.add_variable(bridged_mock) ci = MOI.add_constraint(bridged_mock, x, MOI.Interval(0.0, 1.0)) @test !MOI.Bridges.is_bridged(bridged_mock, ci) @test MOI.Bridges.is_bridged(bridged_mock.model, ci) @test !MOI.supports(bridged_mock, attr, typeof(ci)) + err = ArgumentError(message("accessing")) @test_throws err MOI.get(bridged_mock, attr, ci) + err = MOI.UnsupportedAttribute(attr, message("setting a value for")) + @test_throws err MOI.set(bridged_mock, attr, ci, 1) + attr = AttributeNotAllowed() + err = MOI.SetAttributeNotAllowed(attr, message("setting a value for")) + @test_throws err MOI.set(bridged_mock, attr, ci, 1) return end