summaryrefslogtreecommitdiff
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/messages.ftl33
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs24
-rw-r--r--compiler/rustc_resolve/src/errors.rs55
-rw-r--r--compiler/rustc_resolve/src/ident.rs127
-rw-r--r--compiler/rustc_resolve/src/late.rs295
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs70
-rw-r--r--compiler/rustc_resolve/src/lib.rs16
7 files changed, 407 insertions, 213 deletions
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 32409499047..345255c4c69 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -145,6 +145,15 @@ resolve_param_in_ty_of_const_param =
the type of const parameters must not depend on other generic parameters
.label = the type must not depend on the parameter `{$name}`
+resolve_type_param_in_ty_of_const_param =
+ type parameters may not be used in the type of const parameters
+
+resolve_const_param_in_ty_of_const_param =
+ const parameters may not be used in the type of const parameters
+
+resolve_lifetime_param_in_ty_of_const_param =
+ lifetime parameters may not be used in the type of const parameters
+
resolve_self_in_generic_param_default =
generic parameters cannot use `Self` in their defaults
.label = `Self` in generic parameter default
@@ -156,12 +165,15 @@ resolve_param_in_non_trivial_anon_const =
resolve_param_in_non_trivial_anon_const_help =
use `#![feature(generic_const_exprs)]` to allow generic const expressions
-resolve_param_in_non_trivial_anon_const_sub_type =
+resolve_type_param_in_non_trivial_anon_const =
type parameters may not be used in const expressions
-resolve_param_in_non_trivial_anon_const_sub_non_type =
+resolve_const_param_in_non_trivial_anon_const =
const parameters may only be used as standalone arguments, i.e. `{$name}`
+resolve_lifetime_param_in_non_trivial_anon_const =
+ lifetime parameters may not be used in const expressions
+
resolve_unreachable_label =
use of unreachable label `{$name}`
.label = unreachable label `{$name}`
@@ -187,6 +199,10 @@ resolve_invalid_asm_sym =
.label = is a local variable
.help = `sym` operands must refer to either a function or a static
+resolve_lowercase_self =
+ attempt to use a non-constant value in a constant
+ .suggestion = try using `Self`
+
resolve_trait_impl_duplicate =
duplicate definitions with name `{$name}`:
.label = duplicate definition
@@ -233,3 +249,16 @@ resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern
resolve_accessible_unsure = not sure whether the path is accessible or not
.note = the type may have associated items, but we are currently not checking them
+
+resolve_param_in_enum_discriminant =
+ generic parameters may not be used in enum discriminant values
+ .label = cannot perform const operation using `{$name}`
+
+resolve_type_param_in_enum_discriminant =
+ type parameters may not be used in enum discriminant values
+
+resolve_const_param_in_enum_discriminant =
+ const parameters may not be used in enum discriminant values
+
+resolve_lifetime_param_in_enum_discriminant =
+ lifetime parameters may not be used in enum discriminant values
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index fae7d549592..59eda9db97f 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -550,7 +550,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let sm = self.tcx.sess.source_map();
let def_id = match outer_res {
- Res::SelfTyParam { .. } | Res::SelfCtor(_) => {
+ Res::SelfTyParam { .. } => {
err.span_label(span, "can't use `Self` here");
return err;
}
@@ -864,18 +864,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::ForwardDeclaredGenericParam => {
self.tcx.sess.create_err(errs::ForwardDeclaredGenericParam { span })
}
- ResolutionError::ParamInTyOfConstParam(name) => {
- self.tcx.sess.create_err(errs::ParamInTyOfConstParam { span, name })
- }
- ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
+ ResolutionError::ParamInTyOfConstParam { name, param_kind: is_type } => self
+ .tcx
+ .sess
+ .create_err(errs::ParamInTyOfConstParam { span, name, param_kind: is_type }),
+ ResolutionError::ParamInNonTrivialAnonConst { name, param_kind: is_type } => {
self.tcx.sess.create_err(errs::ParamInNonTrivialAnonConst {
span,
name,
- sub_is_type: if is_type {
- errs::ParamInNonTrivialAnonConstIsType::AType
- } else {
- errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
- },
+ param_kind: is_type,
help: self
.tcx
.sess
@@ -883,6 +880,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
.then_some(errs::ParamInNonTrivialAnonConstHelp),
})
}
+ ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
+ .tcx
+ .sess
+ .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
ResolutionError::SelfInGenericParamDefault => {
self.tcx.sess.create_err(errs::SelfInGenericParamDefault { span })
}
@@ -947,6 +948,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::InvalidAsmSym => {
self.tcx.sess.create_err(errs::InvalidAsmSym { span })
}
+ ResolutionError::LowercaseSelf => {
+ self.tcx.sess.create_err(errs::LowercaseSelf { span })
+ }
}
}
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 4f9f1c7e856..2ab55f12637 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -326,6 +326,18 @@ pub(crate) struct ParamInTyOfConstParam {
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
+ #[subdiagnostic]
+ pub(crate) param_kind: Option<ParamKindInTyOfConstParam>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ParamKindInTyOfConstParam {
+ #[note(resolve_type_param_in_ty_of_const_param)]
+ Type,
+ #[note(resolve_const_param_in_ty_of_const_param)]
+ Const,
+ #[note(resolve_lifetime_param_in_ty_of_const_param)]
+ Lifetime,
}
#[derive(Diagnostic)]
@@ -344,7 +356,7 @@ pub(crate) struct ParamInNonTrivialAnonConst {
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
- pub(crate) sub_is_type: ParamInNonTrivialAnonConstIsType,
+ pub(crate) param_kind: ParamKindInNonTrivialAnonConst,
#[subdiagnostic]
pub(crate) help: Option<ParamInNonTrivialAnonConstHelp>,
}
@@ -354,11 +366,13 @@ pub(crate) struct ParamInNonTrivialAnonConst {
pub(crate) struct ParamInNonTrivialAnonConstHelp;
#[derive(Subdiagnostic)]
-pub(crate) enum ParamInNonTrivialAnonConstIsType {
- #[note(resolve_param_in_non_trivial_anon_const_sub_type)]
- AType,
- #[help(resolve_param_in_non_trivial_anon_const_sub_non_type)]
- NotAType { name: Symbol },
+pub(crate) enum ParamKindInNonTrivialAnonConst {
+ #[note(resolve_type_param_in_non_trivial_anon_const)]
+ Type,
+ #[help(resolve_const_param_in_non_trivial_anon_const)]
+ Const { name: Symbol },
+ #[note(resolve_lifetime_param_in_non_trivial_anon_const)]
+ Lifetime,
}
#[derive(Diagnostic)]
@@ -429,6 +443,14 @@ pub(crate) struct InvalidAsmSym {
}
#[derive(Diagnostic)]
+#[diag(resolve_lowercase_self)]
+pub(crate) struct LowercaseSelf {
+ #[primary_span]
+ #[suggestion(code = "Self", applicability = "maybe-incorrect", style = "short")]
+ pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(resolve_trait_impl_duplicate, code = "E0201")]
pub(crate) struct TraitImplDuplicate {
#[primary_span]
@@ -539,3 +561,24 @@ pub(crate) struct CfgAccessibleUnsure {
#[primary_span]
pub(crate) span: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(resolve_param_in_enum_discriminant)]
+pub(crate) struct ParamInEnumDiscriminant {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) name: Symbol,
+ #[subdiagnostic]
+ pub(crate) param_kind: ParamKindInEnumDiscriminant,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ParamKindInEnumDiscriminant {
+ #[note(resolve_type_param_in_enum_discriminant)]
+ Type,
+ #[note(resolve_const_param_in_enum_discriminant)]
+ Const,
+ #[note(resolve_lifetime_param_in_enum_discriminant)]
+ Lifetime,
+}
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 2db1d83d4fd..f065c4ddd2e 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -13,8 +13,9 @@ use rustc_span::{Span, DUMMY_SP};
use std::ptr;
+use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::late::{
- ConstantHasGenerics, ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind,
+ ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
};
use crate::macros::{sub_namespace_match, MacroRulesScope};
use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
@@ -1125,35 +1126,38 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
RibKind::ConstantItem(_, item) => {
// Still doesn't deal with upvars
if let Some(span) = finalize {
- let (span, resolution_error) =
- if let Some((ident, constant_item_kind)) = item {
- let kind_str = match constant_item_kind {
- ConstantItemKind::Const => "const",
- ConstantItemKind::Static => "static",
- };
- (
- span,
- AttemptToUseNonConstantValueInConstant(
- ident, "let", kind_str,
- ),
- )
- } else {
- (
- rib_ident.span,
- AttemptToUseNonConstantValueInConstant(
- original_rib_ident_def,
- "const",
- "let",
- ),
- )
- };
+ let (span, resolution_error) = match item {
+ None if rib_ident.as_str() == "self" => (span, LowercaseSelf),
+ None => (
+ rib_ident.span,
+ AttemptToUseNonConstantValueInConstant(
+ original_rib_ident_def,
+ "const",
+ "let",
+ ),
+ ),
+ Some((ident, kind)) => (
+ span,
+ AttemptToUseNonConstantValueInConstant(
+ ident,
+ "let",
+ kind.as_str(),
+ ),
+ ),
+ };
self.report_error(span, resolution_error);
}
return Res::Err;
}
RibKind::ConstParamTy => {
if let Some(span) = finalize {
- self.report_error(span, ParamInTyOfConstParam(rib_ident.name));
+ self.report_error(
+ span,
+ ParamInTyOfConstParam {
+ name: rib_ident.name,
+ param_kind: None,
+ },
+ );
}
return Res::Err;
}
@@ -1170,10 +1174,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return Res::Err;
}
}
- Res::Def(DefKind::TyParam, _)
- | Res::SelfTyParam { .. }
- | Res::SelfTyAlias { .. }
- | Res::SelfCtor(_) => {
+ Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
for rib in ribs {
let has_generic_params: HasGenericParams = match rib.kind {
RibKind::Normal
@@ -1188,11 +1189,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
RibKind::ConstantItem(trivial, _) => {
- let features = self.tcx.sess.features_untracked();
- // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
- if !(trivial == ConstantHasGenerics::Yes
- || features.generic_const_exprs)
- {
+ if let ConstantHasGenerics::No(cause) = trivial {
// HACK(min_const_generics): If we encounter `Self` in an anonymous
// constant we can't easily tell if it's generic at this stage, so
// we instead remember this and then enforce the self type to be
@@ -1210,13 +1207,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
} else {
if let Some(span) = finalize {
- self.report_error(
- span,
- ResolutionError::ParamInNonTrivialAnonConst {
- name: rib_ident.name,
- is_type: true,
- },
- );
+ let error = match cause {
+ NoConstantGenericsReason::IsEnumDiscriminant => {
+ ResolutionError::ParamInEnumDiscriminant {
+ name: rib_ident.name,
+ param_kind: ParamKindInEnumDiscriminant::Type,
+ }
+ }
+ NoConstantGenericsReason::NonTrivialConstArg => {
+ ResolutionError::ParamInNonTrivialAnonConst {
+ name: rib_ident.name,
+ param_kind:
+ ParamKindInNonTrivialAnonConst::Type,
+ }
+ }
+ };
+ self.report_error(span, error);
self.tcx.sess.delay_span_bug(span, CG_BUG_STR);
}
@@ -1233,7 +1239,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let Some(span) = finalize {
self.report_error(
span,
- ResolutionError::ParamInTyOfConstParam(rib_ident.name),
+ ResolutionError::ParamInTyOfConstParam {
+ name: rib_ident.name,
+ param_kind: Some(errors::ParamKindInTyOfConstParam::Type),
+ },
);
}
return Res::Err;
@@ -1264,20 +1273,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
| RibKind::ForwardGenericParamBan => continue,
RibKind::ConstantItem(trivial, _) => {
- let features = self.tcx.sess.features_untracked();
- // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
- if !(trivial == ConstantHasGenerics::Yes
- || features.generic_const_exprs)
- {
+ if let ConstantHasGenerics::No(cause) = trivial {
if let Some(span) = finalize {
- self.report_error(
- span,
- ResolutionError::ParamInNonTrivialAnonConst {
- name: rib_ident.name,
- is_type: false,
- },
- );
- self.tcx.sess.delay_span_bug(span, CG_BUG_STR);
+ let error = match cause {
+ NoConstantGenericsReason::IsEnumDiscriminant => {
+ ResolutionError::ParamInEnumDiscriminant {
+ name: rib_ident.name,
+ param_kind: ParamKindInEnumDiscriminant::Const,
+ }
+ }
+ NoConstantGenericsReason::NonTrivialConstArg => {
+ ResolutionError::ParamInNonTrivialAnonConst {
+ name: rib_ident.name,
+ param_kind: ParamKindInNonTrivialAnonConst::Const {
+ name: rib_ident.name,
+ },
+ }
+ }
+ };
+ self.report_error(span, error);
}
return Res::Err;
@@ -1291,7 +1305,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let Some(span) = finalize {
self.report_error(
span,
- ResolutionError::ParamInTyOfConstParam(rib_ident.name),
+ ResolutionError::ParamInTyOfConstParam {
+ name: rib_ident.name,
+ param_kind: Some(errors::ParamKindInTyOfConstParam::Const),
+ },
);
}
return Res::Err;
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6f5d54bcf87..c053ea222a0 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -66,6 +66,15 @@ enum IsRepeatExpr {
Yes,
}
+/// Describes whether an `AnonConst` is a type level const arg or
+/// some other form of anon const (i.e. inline consts or enum discriminants)
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum AnonConstKind {
+ EnumDiscriminant,
+ InlineConst,
+ ConstArg(IsRepeatExpr),
+}
+
impl PatternSource {
fn descr(self) -> &'static str {
match self {
@@ -105,7 +114,7 @@ pub(crate) enum HasGenericParams {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum ConstantHasGenerics {
Yes,
- No,
+ No(NoConstantGenericsReason),
}
impl ConstantHasGenerics {
@@ -114,12 +123,42 @@ impl ConstantHasGenerics {
}
}
+/// Reason for why an anon const is not allowed to reference generic parameters
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub(crate) enum NoConstantGenericsReason {
+ /// Const arguments are only allowed to use generic parameters when:
+ /// - `feature(generic_const_exprs)` is enabled
+ /// or
+ /// - the const argument is a sole const generic paramater, i.e. `foo::<{ N }>()`
+ ///
+ /// If neither of the above are true then this is used as the cause.
+ NonTrivialConstArg,
+ /// Enum discriminants are not allowed to reference generic parameters ever, this
+ /// is used when an anon const is in the following position:
+ ///
+ /// ```rust,compile_fail
+ /// enum Foo<const N: isize> {
+ /// Variant = { N }, // this anon const is not allowed to use generics
+ /// }
+ /// ```
+ IsEnumDiscriminant,
+}
+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum ConstantItemKind {
Const,
Static,
}
+impl ConstantItemKind {
+ pub(crate) fn as_str(&self) -> &'static str {
+ match self {
+ Self::Const => "const",
+ Self::Static => "static",
+ }
+ }
+}
+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum RecordPartialRes {
Yes,
@@ -273,15 +312,18 @@ enum LifetimeRibKind {
/// Signal we cannot find which should be the anonymous lifetime.
ElisionFailure,
- /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
- /// generics. We are disallowing this until we can decide on how we want to handle non-'static
- /// lifetimes in const generics. See issue #74052 for discussion.
- ConstGeneric,
+ /// This rib forbids usage of generic parameters inside of const parameter types.
+ ///
+ /// While this is desirable to support eventually, it is difficult to do and so is
+ /// currently forbidden. See rust-lang/project-const-generics#28 for more info.
+ ConstParamTy,
- /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
- /// This function will emit an error if `generic_const_exprs` is not enabled, the body
- /// identified by `body_id` is an anonymous constant and `lifetime_ref` is non-static.
- AnonConst,
+ /// Usage of generic parameters is forbidden in various positions for anon consts:
+ /// - const arguments when `generic_const_exprs` is not enabled
+ /// - enum discriminant values
+ ///
+ /// This rib emits an error when a lifetime would resolve to a lifetime parameter.
+ ConcreteAnonConst(NoConstantGenericsReason),
/// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
Item,
@@ -648,13 +690,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
self.resolve_block(block);
self.parent_scope.macro_rules = old_macro_rules;
}
- fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
- // We deal with repeat expressions explicitly in `resolve_expr`.
- self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| {
- this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
- this.resolve_anon_const(constant, IsRepeatExpr::No);
- })
- })
+ fn visit_anon_const(&mut self, _constant: &'ast AnonConst) {
+ bug!("encountered anon const without a manual call to `resolve_anon_const`");
}
fn visit_expr(&mut self, expr: &'ast Expr) {
self.resolve_expr(expr, None);
@@ -676,7 +713,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
fn visit_ty(&mut self, ty: &'ast Ty) {
let prev = self.diagnostic_metadata.current_trait_object;
let prev_ty = self.diagnostic_metadata.current_type_path;
- match ty.kind {
+ match &ty.kind {
TyKind::Ref(None, _) => {
// Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
// NodeId `ty.id`.
@@ -685,7 +722,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
self.resolve_elided_lifetime(ty.id, span);
visit::walk_ty(self, ty);
}
- TyKind::Path(ref qself, ref path) => {
+ TyKind::Path(qself, path) => {
self.diagnostic_metadata.current_type_path = Some(ty);
self.smart_resolve_path(ty.id, &qself, path, PathSource::Type);
@@ -730,11 +767,11 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
visit::walk_ty(self, ty);
self.lifetime_elision_candidates = candidates;
}
- TyKind::TraitObject(ref bounds, ..) => {
+ TyKind::TraitObject(bounds, ..) => {
self.diagnostic_metadata.current_trait_object = Some(&bounds[..]);
visit::walk_ty(self, ty)
}
- TyKind::BareFn(ref bare_fn) => {
+ TyKind::BareFn(bare_fn) => {
let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo());
self.with_generic_param_rib(
&bare_fn.generic_params,
@@ -769,6 +806,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
},
)
}
+ TyKind::Array(element_ty, length) => {
+ self.visit_ty(element_ty);
+ self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
+ }
+ TyKind::Typeof(ct) => {
+ self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
+ }
_ => visit::walk_ty(self, ty),
}
self.diagnostic_metadata.current_trait_object = prev;
@@ -994,36 +1038,25 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
// namespace first, and if that fails we try again in the value namespace. If
// resolution in the value namespace succeeds, we have an generic const argument on
// our hands.
- if let TyKind::Path(ref qself, ref path) = ty.kind {
+ if let TyKind::Path(None, ref path) = ty.kind {
// We cannot disambiguate multi-segment paths right now as that requires type
// checking.
- if path.segments.len() == 1 && path.segments[0].args.is_none() {
+ if path.is_potential_trivial_const_arg() {
let mut check_ns = |ns| {
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
.is_some()
};
if !check_ns(TypeNS) && check_ns(ValueNS) {
- // This must be equivalent to `visit_anon_const`, but we cannot call it
- // directly due to visitor lifetimes so we have to copy-paste some code.
- //
- // Note that we might not be inside of an repeat expression here,
- // but considering that `IsRepeatExpr` is only relevant for
- // non-trivial constants this is doesn't matter.
- self.with_constant_rib(
- IsRepeatExpr::No,
- ConstantHasGenerics::Yes,
- None,
+ self.resolve_anon_const_manual(
+ true,
+ AnonConstKind::ConstArg(IsRepeatExpr::No),
|this| {
this.smart_resolve_path(
ty.id,
- qself,
+ &None,
path,
PathSource::Expr(None),
);
-
- if let Some(ref qself) = *qself {
- this.visit_ty(&qself.ty);
- }
this.visit_path(path, ty.id);
},
);
@@ -1037,7 +1070,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
self.visit_ty(ty);
}
GenericArg::Lifetime(lt) => self.visit_lifetime(lt, visit::LifetimeCtxt::GenericArg),
- GenericArg::Const(ct) => self.visit_anon_const(ct),
+ GenericArg::Const(ct) => {
+ self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
+ }
}
self.diagnostic_metadata.currently_processing_generics = prev;
}
@@ -1053,7 +1088,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
match constraint.kind {
AssocConstraintKind::Equality { ref term } => match term {
Term::Ty(ty) => self.visit_ty(ty),
- Term::Const(c) => self.visit_anon_const(c),
+ Term::Const(c) => {
+ self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No))
+ }
},
AssocConstraintKind::Bound { ref bounds } => {
walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
@@ -1102,8 +1139,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
| LifetimeRibKind::AnonymousReportError
| LifetimeRibKind::Elided(_)
| LifetimeRibKind::ElisionFailure
- | LifetimeRibKind::AnonConst
- | LifetimeRibKind::ConstGeneric => {}
+ | LifetimeRibKind::ConcreteAnonConst(_)
+ | LifetimeRibKind::ConstParamTy => {}
}
}
}
@@ -1164,7 +1201,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
InlineAsmOperand::Const { anon_const, .. } => {
// Although this is `DefKind::AnonConst`, it is allowed to reference outer
// generic parameters like an inline const.
- self.resolve_inline_const(anon_const);
+ self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
}
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
}
@@ -1188,6 +1225,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
visit::walk_variant(self, v)
}
+ fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
+ self.resolve_anon_const(discr, AnonConstKind::EnumDiscriminant);
+ }
+
fn visit_field_def(&mut self, f: &'ast FieldDef) {
self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
visit::walk_field_def(self, f)
@@ -1386,7 +1427,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
- this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
+ this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
this.visit_ty(ty)
});
this.ribs[TypeNS].pop().unwrap();
@@ -1395,9 +1436,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
if let Some(ref expr) = default {
this.ribs[TypeNS].push(forward_ty_ban_rib);
this.ribs[ValueNS].push(forward_const_ban_rib);
- this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
- this.resolve_anon_const(expr, IsRepeatExpr::No)
- });
+ this.resolve_anon_const(
+ expr,
+ AnonConstKind::ConstArg(IsRepeatExpr::No),
+ );
forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
}
@@ -1449,7 +1491,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
- if let LifetimeRes::Param { param, .. } = res {
+ if let LifetimeRes::Param { param, binder } = res {
match self.lifetime_uses.entry(param) {
Entry::Vacant(v) => {
debug!("First use of {:?} at {:?}", res, ident.span);
@@ -1463,10 +1505,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
LifetimeRibKind::Item
| LifetimeRibKind::AnonymousReportError
| LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
- // An anonymous lifetime is legal here, go ahead.
- LifetimeRibKind::AnonymousCreateParameter { .. } => {
- Some(LifetimeUseSet::One { use_span: ident.span, use_ctxt })
- }
+ // An anonymous lifetime is legal here, and bound to the right
+ // place, go ahead.
+ LifetimeRibKind::AnonymousCreateParameter {
+ binder: anon_binder,
+ ..
+ } => Some(if binder == anon_binder {
+ LifetimeUseSet::One { use_span: ident.span, use_ctxt }
+ } else {
+ LifetimeUseSet::Many
+ }),
// Only report if eliding the lifetime would have the same
// semantics.
LifetimeRibKind::Elided(r) => Some(if res == r {
@@ -1475,8 +1523,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
LifetimeUseSet::Many
}),
LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric => None,
- LifetimeRibKind::AnonConst => {
+ | LifetimeRibKind::ConstParamTy => None,
+ LifetimeRibKind::ConcreteAnonConst(_) => {
span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
}
})
@@ -1495,8 +1543,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
match rib.kind {
LifetimeRibKind::Item => break,
- LifetimeRibKind::ConstGeneric => {
- self.emit_non_static_lt_in_const_generic_error(lifetime);
+ LifetimeRibKind::ConstParamTy => {
+ self.emit_non_static_lt_in_const_param_ty_error(lifetime);
self.record_lifetime_res(
lifetime.id,
LifetimeRes::Error,
@@ -1504,8 +1552,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
);
return;
}
- LifetimeRibKind::AnonConst => {
- self.maybe_emit_forbidden_non_static_lifetime_error(lifetime);
+ LifetimeRibKind::ConcreteAnonConst(cause) => {
+ self.emit_forbidden_non_static_lifetime_error(cause, lifetime);
self.record_lifetime_res(
lifetime.id,
LifetimeRes::Error,
@@ -1604,9 +1652,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
return;
}
LifetimeRibKind::Item => break,
- LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
- LifetimeRibKind::AnonConst => {
- // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+ LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
+ LifetimeRibKind::ConcreteAnonConst(_) => {
+ // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`.
span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
}
}
@@ -1826,9 +1874,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
break;
}
- LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
- LifetimeRibKind::AnonConst => {
- // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+ LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
+ LifetimeRibKind::ConcreteAnonConst(_) => {
+ // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`.
span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
}
}
@@ -2560,7 +2608,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
}
- // HACK(min_const_generics,const_evaluatable_unchecked): We
+ // HACK(min_const_generics, generic_const_exprs): We
// want to keep allowing `[0; std::mem::size_of::<*mut T>()]`
// with a future compat lint for now. We do this by adding an
// additional special case for repeat expressions.
@@ -2576,18 +2624,26 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
item: Option<(Ident, ConstantItemKind)>,
f: impl FnOnce(&mut Self),
) {
- self.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
- this.with_rib(
- TypeNS,
- RibKind::ConstantItem(
- may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
- item,
- ),
- |this| {
- this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
- },
- )
- });
+ let f = |this: &mut Self| {
+ this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
+ this.with_rib(
+ TypeNS,
+ RibKind::ConstantItem(
+ may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
+ item,
+ ),
+ |this| {
+ this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
+ },
+ )
+ })
+ };
+
+ if let ConstantHasGenerics::No(cause) = may_use_generics {
+ self.with_lifetime_rib(LifetimeRibKind::ConcreteAnonConst(cause), f)
+ } else {
+ f(self)
+ }
}
fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
@@ -3487,10 +3543,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
//
// Similar thing, for types, happens in `report_errors` above.
let report_errors_for_call = |this: &mut Self, parent_err: Spanned<ResolutionError<'a>>| {
- if !source.is_call() {
- return Some(parent_err);
- }
-
// Before we start looking for candidates, we have to get our hands
// on the type user is trying to perform invocation on; basically:
// we're transforming `HashMap::new` into just `HashMap`.
@@ -3924,24 +3976,54 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
debug!("(resolving block) leaving block");
}
- fn resolve_anon_const(&mut self, constant: &'ast AnonConst, is_repeat: IsRepeatExpr) {
- debug!("resolve_anon_const {:?} is_repeat: {:?}", constant, is_repeat);
- self.with_constant_rib(
- is_repeat,
- if constant.value.is_potential_trivial_const_param() {
- ConstantHasGenerics::Yes
- } else {
- ConstantHasGenerics::No
- },
- None,
- |this| visit::walk_anon_const(this, constant),
+ fn resolve_anon_const(&mut self, constant: &'ast AnonConst, anon_const_kind: AnonConstKind) {
+ debug!(
+ "resolve_anon_const(constant: {:?}, anon_const_kind: {:?})",
+ constant, anon_const_kind
);
+
+ self.resolve_anon_const_manual(
+ constant.value.is_potential_trivial_const_arg(),
+ anon_const_kind,
+ |this| this.resolve_expr(&constant.value, None),
+ )
}
- fn resolve_inline_const(&mut self, constant: &'ast AnonConst) {
- debug!("resolve_anon_const {constant:?}");
- self.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, None, |this| {
- visit::walk_anon_const(this, constant)
+ /// There are a few places that we need to resolve an anon const but we did not parse an
+ /// anon const so cannot provide an `&'ast AnonConst`. Right now this is just unbraced
+ /// const arguments that were parsed as type arguments, and `legact_const_generics` which
+ /// parse as normal function argument expressions. To avoid duplicating the code for resolving
+ /// an anon const we have this function which lets the caller manually call `resolve_expr` or
+ /// `smart_resolve_path`.
+ fn resolve_anon_const_manual(
+ &mut self,
+ is_trivial_const_arg: bool,
+ anon_const_kind: AnonConstKind,
+ resolve_expr: impl FnOnce(&mut Self),
+ ) {
+ let is_repeat_expr = match anon_const_kind {
+ AnonConstKind::ConstArg(is_repeat_expr) => is_repeat_expr,
+ _ => IsRepeatExpr::No,
+ };
+
+ let may_use_generics = match anon_const_kind {
+ AnonConstKind::EnumDiscriminant => {
+ ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
+ }
+ AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
+ AnonConstKind::ConstArg(_) => {
+ if self.r.tcx.features().generic_const_exprs || is_trivial_const_arg {
+ ConstantHasGenerics::Yes
+ } else {
+ ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
+ }
+ }
+ };
+
+ self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| {
+ this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+ resolve_expr(this);
+ });
});
}
@@ -4046,17 +4128,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// Constant arguments need to be treated as AnonConst since
// that is how they will be later lowered to HIR.
if const_args.contains(&idx) {
- self.with_constant_rib(
- IsRepeatExpr::No,
- if argument.is_potential_trivial_const_param() {
- ConstantHasGenerics::Yes
- } else {
- ConstantHasGenerics::No
- },
- None,
- |this| {
- this.resolve_expr(argument, None);
- },
+ self.resolve_anon_const_manual(
+ argument.is_potential_trivial_const_arg(),
+ AnonConstKind::ConstArg(IsRepeatExpr::No),
+ |this| this.resolve_expr(argument, None),
);
} else {
self.resolve_expr(argument, None);
@@ -4115,14 +4190,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}
ExprKind::Repeat(ref elem, ref ct) => {
self.visit_expr(elem);
- self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| {
- this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
- this.resolve_anon_const(ct, IsRepeatExpr::Yes)
- })
- });
+ self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
}
ExprKind::ConstBlock(ref ct) => {
- self.resolve_inline_const(ct);
+ self.resolve_anon_const(ct, AnonConstKind::InlineConst);
}
ExprKind::Index(ref elem, ref idx) => {
self.resolve_expr(elem, Some(expr));
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 42d498c7ee0..c9131d8c8a9 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1,7 +1,7 @@
use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
use crate::late::{LifetimeBinderKind, LifetimeRes, LifetimeRibKind, LifetimeUseSet};
-use crate::path_names_to_string;
+use crate::{errors, path_names_to_string};
use crate::{Module, ModuleKind, ModuleOrUniformRoot};
use crate::{PathResult, PathSource, Segment};
@@ -22,7 +22,6 @@ use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::PrimTy;
use rustc_session::lint;
-use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
@@ -35,6 +34,8 @@ use std::ops::Deref;
use thin_vec::ThinVec;
+use super::NoConstantGenericsReason;
+
type Res = def::Res<ast::NodeId>;
/// A field or associated item from self type suggested in case of resolution failure.
@@ -2316,37 +2317,56 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
- pub(crate) fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) {
- struct_span_err!(
- self.r.tcx.sess,
- lifetime_ref.ident.span,
- E0771,
- "use of non-static lifetime `{}` in const generic",
- lifetime_ref.ident
- )
- .note(
- "for more information, see issue #74052 \
- <https://github.com/rust-lang/rust/issues/74052>",
- )
- .emit();
+ pub(crate) fn emit_non_static_lt_in_const_param_ty_error(&self, lifetime_ref: &ast::Lifetime) {
+ self.r
+ .tcx
+ .sess
+ .create_err(errors::ParamInTyOfConstParam {
+ span: lifetime_ref.ident.span,
+ name: lifetime_ref.ident.name,
+ param_kind: Some(errors::ParamKindInTyOfConstParam::Lifetime),
+ })
+ .emit();
}
/// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
/// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
- pub(crate) fn maybe_emit_forbidden_non_static_lifetime_error(
+ pub(crate) fn emit_forbidden_non_static_lifetime_error(
&self,
+ cause: NoConstantGenericsReason,
lifetime_ref: &ast::Lifetime,
) {
- let feature_active = self.r.tcx.sess.features_untracked().generic_const_exprs;
- if !feature_active {
- feature_err(
- &self.r.tcx.sess.parse_sess,
- sym::generic_const_exprs,
- lifetime_ref.ident.span,
- "a non-static lifetime is not allowed in a `const`",
- )
- .emit();
+ match cause {
+ NoConstantGenericsReason::IsEnumDiscriminant => {
+ self.r
+ .tcx
+ .sess
+ .create_err(errors::ParamInEnumDiscriminant {
+ span: lifetime_ref.ident.span,
+ name: lifetime_ref.ident.name,
+ param_kind: errors::ParamKindInEnumDiscriminant::Lifetime,
+ })
+ .emit();
+ }
+ NoConstantGenericsReason::NonTrivialConstArg => {
+ assert!(!self.r.tcx.features().generic_const_exprs);
+ self.r
+ .tcx
+ .sess
+ .create_err(errors::ParamInNonTrivialAnonConst {
+ span: lifetime_ref.ident.span,
+ name: lifetime_ref.ident.name,
+ param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime,
+ help: self
+ .r
+ .tcx
+ .sess
+ .is_nightly_build()
+ .then_some(errors::ParamInNonTrivialAnonConstHelp),
+ })
+ .emit();
+ }
}
}
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index e46463579fe..323b78fcd98 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -21,6 +21,9 @@
#[macro_use]
extern crate tracing;
+use errors::{
+ ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam,
+};
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, attr, NodeId, CRATE_NODE_ID};
@@ -44,6 +47,7 @@ use rustc_index::IndexVec;
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::privacy::EffectiveVisibilities;
+use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
@@ -223,11 +227,15 @@ enum ResolutionError<'a> {
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
ForwardDeclaredGenericParam,
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
- ParamInTyOfConstParam(Symbol),
+ ParamInTyOfConstParam { name: Symbol, param_kind: Option<ParamKindInTyOfConstParam> },
/// generic parameters must not be used inside const evaluations.
///
/// This error is only emitted when using `min_const_generics`.
- ParamInNonTrivialAnonConst { name: Symbol, is_type: bool },
+ ParamInNonTrivialAnonConst { name: Symbol, param_kind: ParamKindInNonTrivialAnonConst },
+ /// generic parameters must not be used inside enum discriminants.
+ ///
+ /// This error is emitted even with `generic_const_exprs`.
+ ParamInEnumDiscriminant { name: Symbol, param_kind: ParamKindInEnumDiscriminant },
/// Error E0735: generic parameters with a default cannot use `Self`
SelfInGenericParamDefault,
/// Error E0767: use of unreachable label
@@ -244,6 +252,8 @@ enum ResolutionError<'a> {
TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
/// Inline asm `sym` operand must refer to a `fn` or `static`.
InvalidAsmSym,
+ /// `self` used instead of `Self` in a generic parameter
+ LowercaseSelf,
}
enum VisResolutionError<'a> {
@@ -2017,6 +2027,6 @@ impl Finalize {
}
}
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
providers.registered_tools = macros::registered_tools;
}