Skip to content

support a way to check bitflags are exhaustive #149907

@lcnr

Description

@lcnr

Right now you just have to hope that whoever adds a new option to CodegenFnAttrFlags correctly updates all the places where it is relevant, e.g.

let mut attrs = Cow::Borrowed(self.codegen_fn_attrs(instance_kind.def_id()));
// Drop the `#[naked]` attribute on non-item `InstanceKind`s, like the shims that
// are generated for indirect function calls.
if !matches!(instance_kind, InstanceKind::Item(_)) {
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
attrs.to_mut().flags.remove(CodegenFnAttrFlags::NAKED);
}
}
// A shim created by `#[track_caller]` should not inherit any attributes
// that modify the symbol name. Failing to remove these attributes from
// the shim leads to errors like `symbol `foo` is already defined`.
//
// A `ClosureOnceShim` with the track_caller attribute does not have a symbol,
// and therefore can be skipped here.
if let InstanceKind::ReifyShim(_, _) = instance_kind
&& attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
{
if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
attrs.to_mut().flags.remove(CodegenFnAttrFlags::NO_MANGLE);
}
if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
attrs.to_mut().flags.remove(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
}
if attrs.symbol_name.is_some() {
attrs.to_mut().symbol_name = None;
}
}
attrs

cc @jdonszelmann #146348

This is quite fragile and I certainly wouldn't have caught this omission in review.

A way to prevent such bugs is by exhaustively matching on all options in such places, e.g.

let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128);
let possible_floats = [
ty::SimplifiedType::Float(ty::FloatTy::F16),
ty::SimplifiedType::Float(ty::FloatTy::F32),
ty::SimplifiedType::Float(ty::FloatTy::F64),
ty::SimplifiedType::Float(ty::FloatTy::F128),
];

fn has_only_region_constraints<I: Interner>(response: ty::Canonical<I, Response<I>>) -> bool {
let ExternalConstraintsData {
region_constraints: _,
ref opaque_types,
ref normalization_nested_goals,
} = *response.value.external_constraints;
response.value.var_values.is_identity_modulo_regions()
&& opaque_types.is_empty()
&& normalization_nested_goals.is_empty()
}

Imo we should extend our bitflags macro to also emit an enum of all options to enable us to exhaustively match on them in cases where this is likely useful.

Metadata

Metadata

Assignees

Labels

needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions