From 3bbe95ca0cb50260aa23a507642af05a83652a4e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Jul 2022 19:33:26 +0000 Subject: [PATCH] Combine redundant obligation cause codes --- .../src/infer/error_reporting/mod.rs | 48 +++++++++++-------- .../trait_impl_difference.rs | 5 +- .../src/infer/error_reporting/note.rs | 18 +------ compiler/rustc_infer/src/infer/mod.rs | 27 ++--------- compiler/rustc_middle/src/traits/mod.rs | 12 +---- compiler/rustc_middle/src/ty/assoc.rs | 10 ++++ compiler/rustc_middle/src/ty/error.rs | 8 +--- .../rustc_middle/src/ty/structural_impls.rs | 1 + .../src/traits/error_reporting/mod.rs | 7 +-- .../src/traits/error_reporting/suggestions.rs | 40 ++-------------- compiler/rustc_typeck/src/astconv/mod.rs | 9 +--- .../rustc_typeck/src/check/compare_method.rs | 15 ++++-- .../associated-const-impl-wrong-lifetime.rs | 2 +- ...ssociated-const-impl-wrong-lifetime.stderr | 2 +- .../impl_bounds.stderr | 10 ++-- src/test/ui/nll/trait-associated-constant.rs | 2 +- .../ui/nll/trait-associated-constant.stderr | 2 +- 17 files changed, 80 insertions(+), 138 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index a990c359e0a30..e06af1fac0699 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1883,7 +1883,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { exp_span, exp_found.expected, exp_found.found, ); - if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() { + if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() { return; } @@ -2351,24 +2351,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { GenericKind::Projection(ref p) => format!("the associated type `{}`", p), }; - match origin { - Some(SubregionOrigin::CompareImplMethodObligation { - span, - impl_item_def_id, - trait_item_def_id, - } | SubregionOrigin::CompareImplTypeObligation { + if let Some(SubregionOrigin::CompareImplItemObligation { + span, + impl_item_def_id, + trait_item_def_id, + }) = origin + { + return self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, - }) => { - return self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", bound_kind, sub), - ); - } - _ => {} + &format!("`{}: {}`", bound_kind, sub), + ); } fn binding_suggestion<'tcx, S: fmt::Display>( @@ -2794,8 +2788,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; match self.code() { - CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), - CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"), + CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => { + Error0308("method not compatible with trait") + } + CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => { + Error0308("type not compatible with trait") + } + CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => { + Error0308("const not compatible with trait") + } MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => { Error0308(match source { hir::MatchSource::TryDesugar => "`?` operator has incompatible types", @@ -2829,8 +2830,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { fn as_requirement_str(&self) -> &'static str { use crate::traits::ObligationCauseCode::*; match self.code() { - CompareImplMethodObligation { .. } => "method type is compatible with trait", - CompareImplTypeObligation { .. } => "associated type is compatible with trait", + CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => { + "method type is compatible with trait" + } + CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => { + "associated type is compatible with trait" + } + CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => { + "const is compatible with trait" + } ExprAssignable => "expression is assignable", IfExpression { .. } => "`if` and `else` have incompatible types", IfExpressionWithNoElse => "`if` missing an `else` returns `()`", diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 6123e6cc66e7d..da465a7642992 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -3,7 +3,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::Subtype; -use crate::traits::ObligationCauseCode::{CompareImplMethodObligation, CompareImplTypeObligation}; +use crate::traits::ObligationCauseCode::CompareImplItemObligation; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -33,8 +33,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin) && let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty() && let sup_expected_found @ Some(_) = sup_trace.values.ty() - && let CompareImplMethodObligation { trait_item_def_id, .. } - | CompareImplTypeObligation { trait_item_def_id, .. } = sub_trace.cause.code() + && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code() && sup_expected_found == sub_expected_found { let guar = diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index b6d41bedd56d8..c1940c5c0824a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -86,13 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "...so that the declared lifetime parameter bounds are satisfied", ); } - infer::CompareImplMethodObligation { span, .. } => { - label_or_note( - span, - "...so that the definition in impl matches the definition from the trait", - ); - } - infer::CompareImplTypeObligation { span, .. } => { + infer::CompareImplItemObligation { span, .. } => { label_or_note( span, "...so that the definition in impl matches the definition from the trait", @@ -329,15 +323,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); err } - infer::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id } => { - self.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - ) - } - infer::CompareImplTypeObligation { span, impl_item_def_id, trait_item_def_id } => self + infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self .report_extra_impl_obligation( span, impl_item_def_id, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 85692e109be4a..5e7c0661728aa 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -405,15 +405,7 @@ pub enum SubregionOrigin<'tcx> { /// Comparing the signature and requirements of an impl method against /// the containing trait. - CompareImplMethodObligation { - span: Span, - impl_item_def_id: LocalDefId, - trait_item_def_id: DefId, - }, - - /// Comparing the signature and requirements of an impl associated type - /// against the containing trait - CompareImplTypeObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId }, + CompareImplItemObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId }, /// Checking that the bounds of a trait's associated type hold for a given impl CheckAssociatedTypeBounds { @@ -1945,8 +1937,7 @@ impl<'tcx> SubregionOrigin<'tcx> { ReborrowUpvar(a, _) => a, DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, - CompareImplMethodObligation { span, .. } => span, - CompareImplTypeObligation { span, .. } => span, + CompareImplItemObligation { span, .. } => span, CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), } } @@ -1960,19 +1951,11 @@ impl<'tcx> SubregionOrigin<'tcx> { SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) } - traits::ObligationCauseCode::CompareImplMethodObligation { - impl_item_def_id, - trait_item_def_id, - } => SubregionOrigin::CompareImplMethodObligation { - span: cause.span, - impl_item_def_id, - trait_item_def_id, - }, - - traits::ObligationCauseCode::CompareImplTypeObligation { + traits::ObligationCauseCode::CompareImplItemObligation { impl_item_def_id, trait_item_def_id, - } => SubregionOrigin::CompareImplTypeObligation { + kind: _, + } => SubregionOrigin::CompareImplItemObligation { span: cause.span, impl_item_def_id, trait_item_def_id, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c55971557fac1..72b848c3ee2dd 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -311,18 +311,10 @@ pub enum ObligationCauseCode<'tcx> { }, /// Error derived when matching traits/impls; see ObligationCause for more details - CompareImplConstObligation, - - /// Error derived when matching traits/impls; see ObligationCause for more details - CompareImplMethodObligation { - impl_item_def_id: LocalDefId, - trait_item_def_id: DefId, - }, - - /// Error derived when matching traits/impls; see ObligationCause for more details - CompareImplTypeObligation { + CompareImplItemObligation { impl_item_def_id: LocalDefId, trait_item_def_id: DefId, + kind: ty::AssocKind, }, /// Checking that the bounds of a trait's associated type hold for a given impl diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 2c93af506679d..eb732148e3eb4 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -105,6 +105,16 @@ impl AssocKind { } } +impl std::fmt::Display for AssocKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AssocKind::Fn => write!(f, "method"), + AssocKind::Const => write!(f, "associated const"), + AssocKind::Type => write!(f, "associated type"), + } + } +} + /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name. /// /// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 49a518b101dd1..91246051316fa 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -660,12 +660,8 @@ impl Trait for X { | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }), ) ); - let impl_comparison = matches!( - cause_code, - ObligationCauseCode::CompareImplMethodObligation { .. } - | ObligationCauseCode::CompareImplTypeObligation { .. } - | ObligationCauseCode::CompareImplConstObligation - ); + let impl_comparison = + matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. }); let assoc = self.associated_item(proj_ty.item_def_id); if !callable_scope || impl_comparison { // We do not want to suggest calling functions when the reason of the diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a4be3d02d1935..7467d9cf995f4 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -224,6 +224,7 @@ TrivialTypeTraversalAndLiftImpls! { // general `Region`. crate::ty::BoundRegionKind, crate::ty::AssocItem, + crate::ty::AssocKind, crate::ty::Placeholder, crate::ty::ClosureKind, crate::ty::FreeRegion, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 2f92a77a7957d..41c5087c43d42 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -301,13 +301,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span = obligation.cause.span; } } - if let ObligationCauseCode::CompareImplMethodObligation { - impl_item_def_id, - trait_item_def_id, - } - | ObligationCauseCode::CompareImplTypeObligation { + if let ObligationCauseCode::CompareImplItemObligation { impl_item_def_id, trait_item_def_id, + kind: _, } = *obligation.cause.code() { self.report_extra_impl_obligation( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7ab85e7fa663e..89d7c050c408b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2682,11 +2682,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) }); } - ObligationCauseCode::CompareImplMethodObligation { trait_item_def_id, .. } => { + ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => { let item_name = self.tcx.item_name(trait_item_def_id); let msg = format!( - "the requirement `{}` appears on the impl method `{}` but not on the \ - corresponding trait method", + "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \ + corresponding trait's {kind}", predicate, item_name, ); let sp = self @@ -2697,7 +2697,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut assoc_span: MultiSpan = sp.into(); assoc_span.push_span_label( sp, - format!("this trait method doesn't have the requirement `{}`", predicate), + format!("this trait's {kind} doesn't have the requirement `{}`", predicate), ); if let Some(ident) = self .tcx @@ -2708,38 +2708,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } err.span_note(assoc_span, &msg); } - ObligationCauseCode::CompareImplTypeObligation { trait_item_def_id, .. } => { - let item_name = self.tcx.item_name(trait_item_def_id); - let msg = format!( - "the requirement `{}` appears on the associated impl type `{}` but not on the \ - corresponding associated trait type", - predicate, item_name, - ); - let sp = self.tcx.def_span(trait_item_def_id); - let mut assoc_span: MultiSpan = sp.into(); - assoc_span.push_span_label( - sp, - format!( - "this trait associated type doesn't have the requirement `{}`", - predicate, - ), - ); - if let Some(ident) = self - .tcx - .opt_associated_item(trait_item_def_id) - .and_then(|i| self.tcx.opt_item_ident(i.container.id())) - { - assoc_span.push_span_label(ident.span, "in this trait"); - } - err.span_note(assoc_span, &msg); - } - ObligationCauseCode::CompareImplConstObligation => { - err.note(&format!( - "the requirement `{}` appears on the associated impl constant \ - but not on the corresponding associated trait constant", - predicate - )); - } ObligationCauseCode::TrivialBound => { err.help("see issue #48214"); if tcx.sess.opts.unstable_features.is_nightly_build() { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7111812f0b090..04f2eb459cf43 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1150,17 +1150,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .expect("missing associated type"); if !assoc_item.vis.is_accessible_from(def_scope, tcx) { - let kind = match assoc_item.kind { - ty::AssocKind::Type => "type", - ty::AssocKind::Const => "const", - _ => unreachable!(), - }; tcx.sess .struct_span_err( binding.span, - &format!("associated {kind} `{}` is private", binding.item_name), + &format!("{} `{}` is private", assoc_item.kind, binding.item_name), ) - .span_label(binding.span, &format!("private associated {kind}")) + .span_label(binding.span, &format!("private {}", assoc_item.kind)) .emit(); } tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 91364ac35cb11..af77efc3c2d57 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -90,9 +90,10 @@ fn compare_predicate_entailment<'tcx>( let mut cause = ObligationCause::new( impl_m_span, impl_m_hir_id, - ObligationCauseCode::CompareImplMethodObligation { + ObligationCauseCode::CompareImplItemObligation { impl_item_def_id: impl_m.def_id.expect_local(), trait_item_def_id: trait_m.def_id, + kind: impl_m.kind, }, ); @@ -223,9 +224,10 @@ fn compare_predicate_entailment<'tcx>( let cause = ObligationCause::new( span, impl_m_hir_id, - ObligationCauseCode::CompareImplMethodObligation { + ObligationCauseCode::CompareImplItemObligation { impl_item_def_id: impl_m.def_id.expect_local(), trait_item_def_id: trait_m.def_id, + kind: impl_m.kind, }, ); ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate)); @@ -1079,7 +1081,11 @@ pub(crate) fn compare_const_impl<'tcx>( let mut cause = ObligationCause::new( impl_c_span, impl_c_hir_id, - ObligationCauseCode::CompareImplConstObligation, + ObligationCauseCode::CompareImplItemObligation { + impl_item_def_id: impl_c.def_id.expect_local(), + trait_item_def_id: trait_c.def_id, + kind: impl_c.kind, + }, ); // There is no "body" here, so just pass dummy id. @@ -1249,9 +1255,10 @@ fn compare_type_predicate_entailment<'tcx>( let cause = ObligationCause::new( span, impl_ty_hir_id, - ObligationCauseCode::CompareImplTypeObligation { + ObligationCauseCode::CompareImplItemObligation { impl_item_def_id: impl_ty.def_id.expect_local(), trait_item_def_id: trait_ty.def_id, + kind: impl_ty.kind, }, ); ocx.register_obligations(obligations); diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs index 08260ec8f4d63..63bac96135b42 100644 --- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs +++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.rs @@ -5,7 +5,7 @@ trait Foo { impl<'a> Foo for &'a () { const NAME: &'a str = "unit"; - //~^ ERROR mismatched types [E0308] + //~^ ERROR const not compatible with trait } fn main() {} diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr index f71fb2ee18aa1..de1d9589e9961 100644 --- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched types +error[E0308]: const not compatible with trait --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5 | LL | const NAME: &'a str = "unit"; diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index c3311e21959fc..ce79c635add69 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -47,14 +47,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy` | LL | #[derive(Copy, Clone)] | ^^^^ -note: the requirement `Fooy: Copy` appears on the associated impl type `C` but not on the corresponding associated trait type - --> $DIR/impl_bounds.rs:7:5 +note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type + --> $DIR/impl_bounds.rs:7:10 | LL | trait Foo { | --- in this trait ... LL | type C where Self: Clone; - | ^^^^^^ this trait associated type doesn't have the requirement `Fooy: Copy` + | ^ this trait's associated type doesn't have the requirement `Fooy: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -72,14 +72,14 @@ note: required because of the requirements on the impl of `Copy` for `Fooy` | LL | #[derive(Copy, Clone)] | ^^^^ -note: the requirement `Fooy: Copy` appears on the impl method `d` but not on the corresponding trait method +note: the requirement `Fooy: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method --> $DIR/impl_bounds.rs:8:8 | LL | trait Foo { | --- in this trait ... LL | fn d() where Self: Clone; - | ^ this trait method doesn't have the requirement `Fooy: Copy` + | ^ this trait's method doesn't have the requirement `Fooy: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | diff --git a/src/test/ui/nll/trait-associated-constant.rs b/src/test/ui/nll/trait-associated-constant.rs index 31dc58185e90a..e13ae80f918b2 100644 --- a/src/test/ui/nll/trait-associated-constant.rs +++ b/src/test/ui/nll/trait-associated-constant.rs @@ -19,7 +19,7 @@ struct FailStruct { } impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { const AC: Option<&'c str> = None; - //~^ ERROR: mismatched types + //~^ ERROR: const not compatible with trait } struct OKStruct2 { } diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index 000ebc716572a..ae0ffd904e799 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -1,4 +1,4 @@ -error[E0308]: mismatched types +error[E0308]: const not compatible with trait --> $DIR/trait-associated-constant.rs:21:5 | LL | const AC: Option<&'c str> = None;