Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve 'generic param from outer item' error for Self and inside static/const items #119939

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 12 additions & 2 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,27 @@ resolve_forward_declared_generic_param =
.label = defaulted generic parameters cannot be forward declared

resolve_generic_params_from_outer_item =
can't use generic parameters from outer item
.label = use of generic parameter from outer item
can't use {$is_self ->
[true] `Self`
*[false] generic parameters
} from outer item
.label = use of {$is_self ->
[true] `Self`
*[false] generic parameter
} 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


Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,13 +561,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
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 is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
let mut err = errs::GenericParamsFromOuterItem {
span,
label: None,
refer_to_type_directly: None,
sugg: None,
static_or_const,
is_self,
};

let sm = self.tcx.sess.source_map();
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ 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>,
pub(crate) is_self: bool,
}

#[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)]
Expand Down
30 changes: 20 additions & 10 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ use rustc_span::symbol::{kw, Ident};
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};
Expand Down Expand Up @@ -1090,7 +1088,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
| 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.
Expand Down Expand Up @@ -1155,7 +1153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
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(..)
Expand Down Expand Up @@ -1213,7 +1211,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}

// 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(
Expand All @@ -1231,15 +1231,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
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;
}
}
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(..)
Expand Down Expand Up @@ -1276,7 +1280,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
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(
Expand All @@ -1295,7 +1301,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
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;
Expand Down
46 changes: 26 additions & 20 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -221,7 +221,7 @@ impl RibKind<'_> {
| RibKind::MacroDefinition(_)
| RibKind::ConstParamTy
| RibKind::InlineAsmSym => false,
RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true,
RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true,
}
}

Expand Down Expand Up @@ -866,11 +866,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
}
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,
Expand All @@ -882,7 +883,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
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,
Expand All @@ -892,7 +893,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
);
}
ForeignItemKind::Static(..) => {
self.with_static_rib(|this| {
self.with_static_rib(def_kind, |this| {
visit::walk_foreign_item(this, foreign_item);
});
}
Expand Down Expand Up @@ -2268,10 +2269,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {

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,
Expand Down Expand Up @@ -2345,11 +2347,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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,
Expand All @@ -2362,7 +2365,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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,
Expand Down Expand Up @@ -2401,7 +2404,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// 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,
Expand All @@ -2422,7 +2425,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// 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,
Expand Down Expand Up @@ -2456,7 +2459,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
}

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);
});
Expand All @@ -2471,11 +2474,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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,
Expand Down Expand Up @@ -2560,7 +2566,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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)));
};
Expand Down Expand Up @@ -2695,8 +2701,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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))
}

Expand Down Expand Up @@ -2877,7 +2883,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// 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,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -1207,6 +1207,10 @@ impl<'tcx> Resolver<'_, 'tcx> {
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,
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/error-codes/E0401.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ LL | fn baz<U,
LL | (y: T) {
| ^ use of generic parameter from outer item

error[E0401]: can't use generic parameters from outer item
error[E0401]: can't use `Self` from outer item
--> $DIR/E0401.rs:24:25
|
LL | impl<T> Iterator for A<T> {
Expand All @@ -29,7 +29,7 @@ LL | impl<T> Iterator for A<T> {
LL | fn helper(sel: &Self) -> u8 {
| ^^^^
| |
| use of generic parameter from outer item
| use of `Self` from outer item
| refer to the type directly here instead

error[E0283]: type annotations needed
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/inner-static-type-parameter.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

Expand Down