Add note to resolve error about generics from inside static/const

This commit is contained in:
clubby789 2024-01-13 19:14:02 +00:00
parent 1d8d7b16cb
commit 511bf6e1c7
11 changed files with 98 additions and 32 deletions

View file

@ -119,12 +119,16 @@ resolve_generic_params_from_outer_item =
.refer_to_type_directly = refer to the type directly here instead
.suggestion = try introducing a local generic parameter here
resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it
resolve_generic_params_from_outer_item_const_param = const parameter from outer item
resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`
resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here
resolve_generic_params_from_outer_item_static = a `static` is a separate item from the item that contains it
resolve_generic_params_from_outer_item_ty_param = type parameter from outer item

View file

@ -561,13 +561,19 @@ pub(crate) fn into_struct_error(
resolution_error: ResolutionError<'a>,
) -> DiagnosticBuilder<'_> {
match resolution_error {
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => {
use errs::GenericParamsFromOuterItemLabel as Label;
let static_or_const = match def_kind {
DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static),
DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const),
_ => None,
};
let mut err = errs::GenericParamsFromOuterItem {
span,
label: None,
refer_to_type_directly: None,
sugg: None,
static_or_const,
};
let sm = self.tcx.sess.source_map();

View file

@ -44,6 +44,16 @@ pub(crate) struct GenericParamsFromOuterItem {
pub(crate) refer_to_type_directly: Option<Span>,
#[subdiagnostic]
pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>,
#[subdiagnostic]
pub(crate) static_or_const: Option<GenericParamsFromOuterItemStaticOrConst>,
}
#[derive(Subdiagnostic)]
pub(crate) enum GenericParamsFromOuterItemStaticOrConst {
#[note(resolve_generic_params_from_outer_item_static)]
Static,
#[note(resolve_generic_params_from_outer_item_const)]
Const,
}
#[derive(Subdiagnostic)]

View file

@ -10,9 +10,7 @@
use rustc_span::Span;
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::late::{
ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
};
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
use crate::macros::{sub_namespace_match, MacroRulesScope};
use crate::BindingKey;
use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
@ -1090,7 +1088,7 @@ fn validate_res_from_ribs(
| RibKind::ForwardGenericParamBan => {
// Nothing to do. Continue.
}
RibKind::Item(_) | RibKind::AssocItem => {
RibKind::Item(..) | RibKind::AssocItem => {
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
@ -1155,7 +1153,7 @@ fn validate_res_from_ribs(
}
Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
for rib in ribs {
let has_generic_params: HasGenericParams = match rib.kind {
let (has_generic_params, def_kind) = match rib.kind {
RibKind::Normal
| RibKind::FnOrCoroutine
| RibKind::Module(..)
@ -1213,7 +1211,9 @@ fn validate_res_from_ribs(
}
// This was an attempt to use a type parameter outside its scope.
RibKind::Item(has_generic_params) => has_generic_params,
RibKind::Item(has_generic_params, def_kind) => {
(has_generic_params, def_kind)
}
RibKind::ConstParamTy => {
if let Some(span) = finalize {
self.report_error(
@ -1231,7 +1231,11 @@ fn validate_res_from_ribs(
if let Some(span) = finalize {
self.report_error(
span,
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
ResolutionError::GenericParamsFromOuterItem(
res,
has_generic_params,
def_kind,
),
);
}
return Res::Err;
@ -1239,7 +1243,7 @@ fn validate_res_from_ribs(
}
Res::Def(DefKind::ConstParam, _) => {
for rib in ribs {
let has_generic_params = match rib.kind {
let (has_generic_params, def_kind) = match rib.kind {
RibKind::Normal
| RibKind::FnOrCoroutine
| RibKind::Module(..)
@ -1276,7 +1280,9 @@ fn validate_res_from_ribs(
continue;
}
RibKind::Item(has_generic_params) => has_generic_params,
RibKind::Item(has_generic_params, def_kind) => {
(has_generic_params, def_kind)
}
RibKind::ConstParamTy => {
if let Some(span) = finalize {
self.report_error(
@ -1295,7 +1301,11 @@ fn validate_res_from_ribs(
if let Some(span) = finalize {
self.report_error(
span,
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
ResolutionError::GenericParamsFromOuterItem(
res,
has_generic_params,
def_kind,
),
);
}
return Res::Err;

View file

@ -181,7 +181,7 @@ pub(crate) enum RibKind<'a> {
FnOrCoroutine,
/// We passed through an item scope. Disallow upvars.
Item(HasGenericParams),
Item(HasGenericParams, DefKind),
/// We're in a constant item. Can't refer to dynamic stuff.
///
@ -221,7 +221,7 @@ pub(crate) fn contains_params(&self) -> bool {
| RibKind::MacroDefinition(_)
| RibKind::ConstParamTy
| RibKind::InlineAsmSym => false,
RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true,
RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true,
}
}
@ -866,11 +866,12 @@ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
let def_kind = self.r.local_def_kind(foreign_item.id);
match foreign_item.kind {
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
LifetimeRibKind::Generics {
binder: foreign_item.id,
kind: LifetimeBinderKind::Item,
@ -882,7 +883,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
LifetimeRibKind::Generics {
binder: foreign_item.id,
kind: LifetimeBinderKind::Function,
@ -892,7 +893,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
);
}
ForeignItemKind::Static(..) => {
self.with_static_rib(|this| {
self.with_static_rib(def_kind, |this| {
visit::walk_foreign_item(this, foreign_item);
});
}
@ -2268,10 +2269,11 @@ fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
debug!("resolve_adt");
let kind = self.r.local_def_kind(item.id);
self.with_current_self_item(item, |this| {
this.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), kind),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2345,11 +2347,12 @@ fn resolve_item(&mut self, item: &'ast Item) {
let name = item.ident.name;
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
let def_kind = self.r.local_def_kind(item.id);
match item.kind {
ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2362,7 +2365,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
ItemKind::Fn(box Fn { ref generics, .. }) => {
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Function,
@ -2401,7 +2404,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2422,7 +2425,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2456,7 +2459,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
}
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
self.with_static_rib(|this| {
self.with_static_rib(def_kind, |this| {
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
this.visit_ty(ty);
});
@ -2471,11 +2474,14 @@ fn resolve_item(&mut self, item: &'ast Item) {
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
self.with_generic_param_rib(
&generics.params,
RibKind::Item(if self.r.tcx.features().generic_const_items {
HasGenericParams::Yes(generics.span)
} else {
HasGenericParams::No
}),
RibKind::Item(
if self.r.tcx.features().generic_const_items {
HasGenericParams::Yes(generics.span)
} else {
HasGenericParams::No
},
def_kind,
),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::ConstItem,
@ -2560,7 +2566,7 @@ fn with_generic_param_rib<'c, F>(
let mut add_bindings_for_ns = |ns| {
let parent_rib = self.ribs[ns]
.iter()
.rfind(|r| matches!(r.kind, RibKind::Item(_)))
.rfind(|r| matches!(r.kind, RibKind::Item(..)))
.expect("associated item outside of an item");
seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
};
@ -2695,8 +2701,8 @@ fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
self.label_ribs.pop();
}
fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
let kind = RibKind::Item(HasGenericParams::No);
fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) {
let kind = RibKind::Item(HasGenericParams::No, def_kind);
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
}
@ -2877,7 +2883,7 @@ fn resolve_implementation(
// If applicable, create a rib for the type parameters.
self.with_generic_param_rib(
&generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span)),
RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)),
LifetimeRibKind::Generics {
span: generics.span,
binder: item_id,

View file

@ -185,7 +185,7 @@ struct BindingError {
#[derive(Debug)]
enum ResolutionError<'a> {
/// Error E0401: can't use type or const parameters from outer item.
GenericParamsFromOuterItem(Res, HasGenericParams),
GenericParamsFromOuterItem(Res, HasGenericParams, DefKind),
/// Error E0403: the name is already used for a type or const parameter in this generic
/// parameter list.
NameAlreadyUsedInParameterList(Symbol, Span),
@ -1207,6 +1207,10 @@ fn local_def_id(&self, node: NodeId) -> LocalDefId {
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
}
fn local_def_kind(&self, node: NodeId) -> DefKind {
self.tcx.def_kind(self.local_def_id(node))
}
/// Adds a definition with a parent definition.
fn create_def(
&mut self,

View file

@ -5,6 +5,8 @@ LL | fn foo<T>() {
| - type parameter from outer item
LL | static a: Bar<T> = Bar::What;
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error[E0392]: parameter `T` is never used
--> $DIR/inner-static-type-parameter.rs:3:10

View file

@ -5,6 +5,8 @@ LL | fn outer<T: Tr>() { // outer function
| - type parameter from outer item
LL | const K: u32 = T::C;
| ^^^^ use of generic parameter from outer item
|
= note: a `const` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24
@ -14,6 +16,8 @@ LL | impl<T> Tr for T { // outer impl block
LL | const C: u32 = {
LL | const I: u32 = T::C;
| ^^^^ use of generic parameter from outer item
|
= note: a `const` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20
@ -22,6 +26,8 @@ LL | struct S<T: Tr>(U32<{ // outer struct
| - type parameter from outer item
LL | const _: u32 = T::C;
| ^^^^ use of generic parameter from outer item
|
= note: a `const` is a separate item from the item that contains it
error: aborting due to 3 previous errors

View file

@ -7,6 +7,8 @@ LL | const K: u32 = T::C;
| - ^^^^ use of generic parameter from outer item
| |
| help: try introducing a local generic parameter here: `<T>`
|
= note: a `const` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24
@ -18,6 +20,8 @@ LL | const I: u32 = T::C;
| - ^^^^ use of generic parameter from outer item
| |
| help: try introducing a local generic parameter here: `<T>`
|
= note: a `const` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20
@ -28,6 +32,8 @@ LL | const _: u32 = T::C;
| - ^^^^ use of generic parameter from outer item
| |
| help: try introducing a local generic parameter here: `<T>`
|
= note: a `const` is a separate item from the item that contains it
error: aborting due to 3 previous errors

View file

@ -6,6 +6,8 @@ LL | unsafe fn foo<A>() {
LL | extern "C" {
LL | static baz: *const A;
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error: aborting due to 1 previous error

View file

@ -6,6 +6,8 @@ LL | fn f<T>() {
LL | extern "C" {
LL | static a: *const T;
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/issue-65035-static-with-parent-generics.rs:9:22
@ -14,6 +16,8 @@ LL | fn g<T: Default>() {
| - type parameter from outer item
LL | static a: *const T = Default::default();
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/issue-65035-static-with-parent-generics.rs:15:24
@ -23,6 +27,8 @@ LL | fn h<const N: usize>() {
LL | extern "C" {
LL | static a: [u8; N];
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/issue-65035-static-with-parent-generics.rs:21:20
@ -31,6 +37,8 @@ LL | fn i<const N: usize>() {
| - const parameter from outer item
LL | static a: [u8; N] = [0; N];
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error[E0401]: can't use generic parameters from outer item
--> $DIR/issue-65035-static-with-parent-generics.rs:21:29
@ -39,6 +47,8 @@ LL | fn i<const N: usize>() {
| - const parameter from outer item
LL | static a: [u8; N] = [0; N];
| ^ use of generic parameter from outer item
|
= note: a `static` is a separate item from the item that contains it
error: aborting due to 5 previous errors