Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from o
.label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
.suggestion = replace `Self` with the actual type

hir_typeck_self_ctor_from_outer_item_inner_item = `Self` used in this inner item

hir_typeck_slicing_suggestion = consider slicing here

hir_typeck_struct_expr_non_exhaustive =
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,15 @@ pub(crate) struct SelfCtorFromOuterItem {
pub impl_span: Span,
#[subdiagnostic]
pub sugg: Option<ReplaceWithName>,
#[subdiagnostic]
pub item: Option<InnerItem>,
}

#[derive(Subdiagnostic)]
#[label(hir_typeck_self_ctor_from_outer_item_inner_item)]
pub(crate) struct InnerItem {
#[primary_span]
pub span: Span,
}

#[derive(LintDiagnostic)]
Expand All @@ -987,6 +996,8 @@ pub(crate) struct SelfCtorFromOuterItemLint {
pub impl_span: Span,
#[subdiagnostic]
pub sugg: Option<ReplaceWithName>,
#[subdiagnostic]
pub item: Option<InnerItem>,
}

#[derive(Subdiagnostic)]
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,11 +1094,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: path_span,
name: self.tcx.item_name(def.did()).to_ident_string(),
});
let item = match self
.tcx
.hir_node_by_def_id(self.tcx.hir_get_parent_item(hir_id).def_id)
{
hir::Node::Item(item) => Some(errors::InnerItem {
span: item.kind.ident().map(|i| i.span).unwrap_or(item.span),
}),
_ => None,
};
if ty.raw.has_param() {
let guar = self.dcx().emit_err(errors::SelfCtorFromOuterItem {
span: path_span,
impl_span: tcx.def_span(impl_def_id),
sugg,
item,
});
return (Ty::new_error(self.tcx, guar), res);
} else {
Expand All @@ -1109,6 +1119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
errors::SelfCtorFromOuterItemLint {
impl_span: tcx.def_span(impl_def_id),
sugg,
item,
},
);
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ resolve_generic_params_from_outer_item_const = a `const` is a separate item from

resolve_generic_params_from_outer_item_const_param = const parameter from outer item

resolve_generic_params_from_outer_item_inner_item = {$is_self ->
[true] `Self`
*[false] generic parameter
} used in this inner {$descr}

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
Expand Down
20 changes: 16 additions & 4 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use crate::errors::{
MaybeMissingMacroRulesName,
};
use crate::imports::{Import, ImportKind};
use crate::late::{PatternSource, Rib};
use crate::late::{DiagMetadata, PatternSource, Rib};
use crate::{
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize,
ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
Expand Down Expand Up @@ -553,11 +553,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
resolution_error: ResolutionError<'ra>,
) -> Diag<'_> {
match resolution_error {
ResolutionError::GenericParamsFromOuterItem(
ResolutionError::GenericParamsFromOuterItem {
outer_res,
has_generic_params,
def_kind,
) => {
inner_item,
} => {
use errs::GenericParamsFromOuterItemLabel as Label;
let static_or_const = match def_kind {
DefKind::Static { .. } => {
Expand All @@ -575,6 +576,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
sugg: None,
static_or_const,
is_self,
item: inner_item.as_ref().map(|(span, kind)| {
errs::GenericParamsFromOuterItemInnerItem {
span: *span,
descr: kind.descr().to_string(),
}
}),
};

let sm = self.tcx.sess.source_map();
Expand Down Expand Up @@ -608,7 +615,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
};

if let HasGenericParams::Yes(span) = has_generic_params {
if let HasGenericParams::Yes(span) = has_generic_params
&& !matches!(inner_item, Some((_, ItemKind::Delegation(..))))
{
let name = self.tcx.item_name(def_id);
let (span, snippet) = if span.is_empty() {
let snippet = format!("<{name}>");
Expand Down Expand Up @@ -2401,6 +2410,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module: Option<ModuleOrUniformRoot<'ra>>,
failed_segment_idx: usize,
ident: Ident,
diag_metadata: Option<&DiagMetadata<'_>>,
) -> (String, Option<Suggestion>) {
let is_last = failed_segment_idx == path.len() - 1;
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
Expand Down Expand Up @@ -2506,6 +2516,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
&ribs[ns_to_try],
ignore_binding,
diag_metadata,
) {
// we found a locally-imported or available item/module
Some(LexicalScopeBinding::Item(binding)) => Some(binding),
Expand Down Expand Up @@ -2556,6 +2567,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
&ribs[ValueNS],
ignore_binding,
diag_metadata,
)
} else {
None
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ pub(crate) struct GenericParamsFromOuterItem {
#[subdiagnostic]
pub(crate) static_or_const: Option<GenericParamsFromOuterItemStaticOrConst>,
pub(crate) is_self: bool,
#[subdiagnostic]
pub(crate) item: Option<GenericParamsFromOuterItemInnerItem>,
}

#[derive(Subdiagnostic)]
#[label(resolve_generic_params_from_outer_item_inner_item)]
pub(crate) struct GenericParamsFromOuterItemInnerItem {
#[primary_span]
pub(crate) span: Span,
pub(crate) descr: String,
}

#[derive(Subdiagnostic)]
Expand All @@ -47,7 +57,12 @@ pub(crate) enum GenericParamsFromOuterItemLabel {
}

#[derive(Subdiagnostic)]
#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")]
#[suggestion(
resolve_suggestion,
code = "{snippet}",
applicability = "maybe-incorrect",
style = "verbose"
)]
pub(crate) struct GenericParamsFromOuterItemSugg {
#[primary_span]
pub(crate) span: Span,
Expand Down
50 changes: 43 additions & 7 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use tracing::{debug, instrument};

use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::imports::{Import, NameResolution};
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
use crate::late::{
ConstantHasGenerics, DiagMetadata, NoConstantGenericsReason, PathSource, Rib, RibKind,
};
use crate::macros::{MacroRulesScope, sub_namespace_match};
use crate::{
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
Expand Down Expand Up @@ -295,6 +297,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
finalize: Option<Finalize>,
ribs: &[Rib<'ra>],
ignore_binding: Option<NameBinding<'ra>>,
diag_metadata: Option<&DiagMetadata<'_>>,
) -> Option<LexicalScopeBinding<'ra>> {
assert!(ns == TypeNS || ns == ValueNS);
let orig_ident = ident;
Expand Down Expand Up @@ -326,6 +329,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
finalize.map(|finalize| finalize.path_span),
*original_rib_ident_def,
ribs,
diag_metadata,
)));
} else if let RibKind::Block(Some(module)) = rib.kind
&& let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
Expand Down Expand Up @@ -1193,6 +1197,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
finalize: Option<Span>,
original_rib_ident_def: Ident,
all_ribs: &[Rib<'ra>],
diag_metadata: Option<&DiagMetadata<'_>>,
) -> Res {
debug!("validate_res_from_ribs({:?})", res);
let ribs = &all_ribs[rib_index + 1..];
Expand Down Expand Up @@ -1391,13 +1396,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};

if let Some(span) = finalize {
let item = if let Some(diag_metadata) = diag_metadata
&& let Some(current_item) = diag_metadata.current_item
{
let span = current_item
.kind
.ident()
.map(|i| i.span)
.unwrap_or(current_item.span);
Some((span, current_item.kind.clone()))
} else {
None
};
self.report_error(
span,
ResolutionError::GenericParamsFromOuterItem(
res,
ResolutionError::GenericParamsFromOuterItem {
outer_res: res,
has_generic_params,
def_kind,
),
inner_item: item,
},
);
}
return Res::Err;
Expand Down Expand Up @@ -1466,13 +1484,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

// This was an attempt to use a const parameter outside its scope.
if let Some(span) = finalize {
let item = if let Some(diag_metadata) = diag_metadata
&& let Some(current_item) = diag_metadata.current_item
{
let span = current_item
.kind
.ident()
.map(|i| i.span)
.unwrap_or(current_item.span);
Some((span, current_item.kind.clone()))
} else {
None
};
self.report_error(
span,
ResolutionError::GenericParamsFromOuterItem(
res,
ResolutionError::GenericParamsFromOuterItem {
outer_res: res,
has_generic_params,
def_kind,
),
inner_item: item,
},
);
}
return Res::Err;
Expand Down Expand Up @@ -1501,6 +1532,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
None,
ignore_import,
None,
)
}
#[instrument(level = "debug", skip(self))]
Expand All @@ -1522,6 +1554,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
ignore_binding,
ignore_import,
None,
)
}

Expand All @@ -1535,6 +1568,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_import: Option<Import<'ra>>,
diag_metadata: Option<&DiagMetadata<'_>>,
) -> PathResult<'ra> {
let mut module = None;
let mut module_had_parse_errors = false;
Expand Down Expand Up @@ -1675,6 +1709,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
finalize,
&ribs[ns],
ignore_binding,
diag_metadata,
) {
// we found a locally-imported or available item/module
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
Expand Down Expand Up @@ -1800,6 +1835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module,
segment_idx,
ident,
diag_metadata,
)
},
);
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ pub(crate) struct UnnecessaryQualification<'ra> {
}

#[derive(Default, Debug)]
struct DiagMetadata<'ast> {
pub(crate) struct DiagMetadata<'ast> {
/// The current trait's associated items' ident, used for diagnostic suggestions.
current_trait_assoc_items: Option<&'ast [Box<AssocItem>]>,

Expand All @@ -677,8 +677,8 @@ struct DiagMetadata<'ast> {
/// The current self item if inside an ADT (used for better errors).
current_self_item: Option<NodeId>,

/// The current trait (used to suggest).
current_item: Option<&'ast Item>,
/// The current item being evaluated (used for suggestions and more detail in errors).
pub(crate) current_item: Option<&'ast Item>,

/// When processing generic arguments and encountering an unresolved ident not found,
/// suggest introducing a type or const param depending on the context.
Expand Down Expand Up @@ -1457,6 +1457,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
None,
&self.ribs[ns],
None,
Some(&self.diag_metadata),
)
}

Expand All @@ -1474,6 +1475,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
finalize,
&self.ribs[ns],
ignore_binding,
Some(&self.diag_metadata),
)
}

Expand All @@ -1493,6 +1495,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
Some(&self.ribs),
None,
None,
Some(&self.diag_metadata),
)
}

Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,12 @@ struct BindingError {
#[derive(Debug)]
enum ResolutionError<'ra> {
/// Error E0401: can't use type or const parameters from outer item.
GenericParamsFromOuterItem(Res, HasGenericParams, DefKind),
GenericParamsFromOuterItem {
outer_res: Res,
has_generic_params: HasGenericParams,
def_kind: DefKind,
inner_item: Option<(Span, ast::ItemKind)>,
},
/// Error E0403: the name is already used for a type or const parameter in this generic
/// parameter list.
NameAlreadyUsedInParameterList(Ident, Span),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<const X: u32>() {
| - const parameter from outer item
LL | fn bar() -> u32 {
| - help: try introducing a local generic parameter here: `<X>`
| --- generic parameter used in this inner function
LL | X
| ^ use of generic parameter from outer item
|
help: try introducing a local generic parameter here
|
LL | fn bar<X>() -> u32 {
| +++

error: aborting due to 1 previous error

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/delegation/target-expr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0401]: can't use generic parameters from outer item
LL | fn bar<T: Default>(_: T) {
| - type parameter from outer item
LL | reuse Trait::static_method {
| - help: try introducing a local generic parameter here: `T,`
| ------------- generic parameter used in this inner delegated function
LL |
LL | let _ = T::Default();
| ^^^^^^^^^^ use of generic parameter from outer item
Expand Down
Loading
Loading