mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #155687 - GuillaumeGomez:rollup-aZ7YrAD, r=GuillaumeGomez
Rollup of 7 pull requests Successful merges: - rust-lang/rust#155469 (Account for titlecase in casing lints) - rust-lang/rust#155644 (delegation: support self ty propagation for functions in free to trait reuse) - rust-lang/rust#154957 (Fix ICE when const closure appears inside a non-const trait method) - rust-lang/rust#155442 (Change keyword order for `impl` restrictions) - rust-lang/rust#155561 (Use singular wording for single _ placeholders in type suggestions) - rust-lang/rust#155637 (Fix E0191 suggestion for empty dyn trait args) - rust-lang/rust#155661 (Remove `AttributeLintKind` variants - part 6)
This commit is contained in:
@@ -3786,10 +3786,10 @@ pub struct TraitAlias {
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub struct Trait {
|
||||
pub impl_restriction: ImplRestriction,
|
||||
pub constness: Const,
|
||||
pub safety: Safety,
|
||||
pub is_auto: IsAuto,
|
||||
pub impl_restriction: ImplRestriction,
|
||||
pub ident: Ident,
|
||||
pub generics: Generics,
|
||||
#[visitable(extra = BoundKind::SuperTraits)]
|
||||
|
||||
@@ -143,7 +143,8 @@ pub(crate) fn lower_delegation(
|
||||
|
||||
let (param_count, c_variadic) = self.param_count(sig_id);
|
||||
|
||||
let mut generics = self.uplift_delegation_generics(delegation, sig_id, item_id);
|
||||
let mut generics =
|
||||
self.uplift_delegation_generics(delegation, sig_id, item_id, is_method);
|
||||
|
||||
let body_id = self.lower_delegation_body(
|
||||
delegation,
|
||||
@@ -301,6 +302,8 @@ fn lower_delegation_decl(
|
||||
hir::InferDelegationSig::Output(self.arena.alloc(hir::DelegationGenerics {
|
||||
child_args_segment_id: generics.child.args_segment_id,
|
||||
parent_args_segment_id: generics.parent.args_segment_id,
|
||||
self_ty_id: generics.self_ty_id,
|
||||
propagate_self_ty: generics.propagate_self_ty,
|
||||
})),
|
||||
)),
|
||||
span,
|
||||
@@ -554,6 +557,12 @@ fn finalize_body_lowering(
|
||||
}
|
||||
};
|
||||
|
||||
generics.self_ty_id = match new_path {
|
||||
hir::QPath::Resolved(ty, _) => ty,
|
||||
hir::QPath::TypeRelative(ty, _) => Some(ty),
|
||||
}
|
||||
.map(|ty| ty.hir_id);
|
||||
|
||||
let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span));
|
||||
self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span))
|
||||
};
|
||||
|
||||
@@ -67,6 +67,8 @@ pub(super) struct GenericsGenerationResult<'hir> {
|
||||
pub(super) struct GenericsGenerationResults<'hir> {
|
||||
pub(super) parent: GenericsGenerationResult<'hir>,
|
||||
pub(super) child: GenericsGenerationResult<'hir>,
|
||||
pub(super) self_ty_id: Option<HirId>,
|
||||
pub(super) propagate_self_ty: bool,
|
||||
}
|
||||
|
||||
pub(super) struct GenericArgsPropagationDetails {
|
||||
@@ -209,6 +211,7 @@ pub(super) fn uplift_delegation_generics(
|
||||
delegation: &Delegation,
|
||||
sig_id: DefId,
|
||||
item_id: NodeId,
|
||||
is_method: bool,
|
||||
) -> GenericsGenerationResults<'hir> {
|
||||
let delegation_parent_kind =
|
||||
self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id)));
|
||||
@@ -230,7 +233,12 @@ pub(super) fn uplift_delegation_generics(
|
||||
let child = DelegationGenerics::trait_impl(sig_params, child_user_specified);
|
||||
let child = GenericsGenerationResult::new(child);
|
||||
|
||||
return GenericsGenerationResults { parent, child };
|
||||
return GenericsGenerationResults {
|
||||
parent,
|
||||
child,
|
||||
self_ty_id: None,
|
||||
propagate_self_ty: false,
|
||||
};
|
||||
}
|
||||
|
||||
let delegation_in_free_ctx =
|
||||
@@ -238,13 +246,14 @@ pub(super) fn uplift_delegation_generics(
|
||||
|
||||
let sig_parent = self.tcx.parent(sig_id);
|
||||
let sig_in_trait = matches!(self.tcx.def_kind(sig_parent), DefKind::Trait);
|
||||
let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
|
||||
let generate_self = free_to_trait_delegation && is_method && delegation.qself.is_none();
|
||||
|
||||
let can_add_generics_to_parent = len >= 2
|
||||
&& self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
|
||||
matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
|
||||
});
|
||||
|
||||
let generate_self = delegation_in_free_ctx && sig_in_trait;
|
||||
let parent_generics = if can_add_generics_to_parent {
|
||||
let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params[..];
|
||||
|
||||
@@ -278,6 +287,8 @@ pub(super) fn uplift_delegation_generics(
|
||||
GenericsGenerationResults {
|
||||
parent: GenericsGenerationResult::new(parent_generics),
|
||||
child: GenericsGenerationResult::new(child_generics),
|
||||
self_ty_id: None,
|
||||
propagate_self_ty: free_to_trait_delegation && !generate_self,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -556,10 +556,10 @@ fn lower_item_kind(
|
||||
})
|
||||
}
|
||||
ItemKind::Trait(box Trait {
|
||||
impl_restriction,
|
||||
constness,
|
||||
is_auto,
|
||||
safety,
|
||||
impl_restriction,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
@@ -586,10 +586,10 @@ fn lower_item_kind(
|
||||
},
|
||||
);
|
||||
hir::ItemKind::Trait(
|
||||
impl_restriction,
|
||||
constness,
|
||||
*is_auto,
|
||||
safety,
|
||||
impl_restriction,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
|
||||
@@ -371,10 +371,10 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
self.bclose(item.span, empty, cb);
|
||||
}
|
||||
ast::ItemKind::Trait(box ast::Trait {
|
||||
impl_restriction,
|
||||
constness,
|
||||
safety,
|
||||
is_auto,
|
||||
impl_restriction,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
@@ -382,10 +382,10 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
||||
}) => {
|
||||
let (cb, ib) = self.head("");
|
||||
self.print_visibility(&item.vis);
|
||||
self.print_impl_restriction(impl_restriction);
|
||||
self.print_constness(*constness);
|
||||
self.print_safety(*safety);
|
||||
self.print_is_auto(*is_auto);
|
||||
self.print_impl_restriction(impl_restriction);
|
||||
self.word_nbsp("trait");
|
||||
self.print_ident(*ident);
|
||||
self.print_generic_params(&generics.params);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use rustc_errors::E0232;
|
||||
use rustc_errors::{Diagnostic, E0232};
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::attrs::diagnostic::{
|
||||
Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue,
|
||||
@@ -18,6 +18,10 @@
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::errors::{
|
||||
DisallowedPlaceholder, DisallowedPositionalArgument, IgnoredDiagnosticOption,
|
||||
InvalidFormatSpecifier, MalFormedDiagnosticAttributeLint, WrappedParserError,
|
||||
};
|
||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser};
|
||||
|
||||
pub(crate) mod do_not_recommend;
|
||||
@@ -112,12 +116,12 @@ fn merge<T, S: Stage>(
|
||||
match (first, later) {
|
||||
(Some(_) | None, None) => {}
|
||||
(Some((first_span, _)), Some((later_span, _))) => {
|
||||
cx.emit_lint(
|
||||
let first_span = *first_span;
|
||||
cx.emit_dyn_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::IgnoredDiagnosticOption {
|
||||
first_span: *first_span,
|
||||
later_span,
|
||||
option_name,
|
||||
move |dcx, level| {
|
||||
IgnoredDiagnosticOption { first_span, later_span, option_name }
|
||||
.into_diag(dcx, level)
|
||||
},
|
||||
later_span,
|
||||
);
|
||||
@@ -157,12 +161,15 @@ fn parse_list<'p, S: Stage>(
|
||||
);
|
||||
}
|
||||
ArgParser::NameValue(_) => {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MalFormedDiagnosticAttribute {
|
||||
attribute: mode.as_str(),
|
||||
options: mode.allowed_options(),
|
||||
span,
|
||||
move |dcx, level| {
|
||||
MalFormedDiagnosticAttributeLint {
|
||||
attribute: mode.as_str(),
|
||||
options: mode.allowed_options(),
|
||||
span,
|
||||
}
|
||||
.into_diag(dcx, level)
|
||||
},
|
||||
span,
|
||||
);
|
||||
@@ -188,12 +195,15 @@ fn parse_directive_items<'p, S: Stage>(
|
||||
let span = item.span();
|
||||
|
||||
macro malformed() {{
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::MalFormedDiagnosticAttribute {
|
||||
attribute: mode.as_str(),
|
||||
options: mode.allowed_options(),
|
||||
span,
|
||||
move |dcx, level| {
|
||||
MalFormedDiagnosticAttributeLint {
|
||||
attribute: mode.as_str(),
|
||||
options: mode.allowed_options(),
|
||||
span,
|
||||
}
|
||||
.into_diag(dcx, level)
|
||||
},
|
||||
span,
|
||||
);
|
||||
@@ -210,13 +220,14 @@ fn parse_directive_items<'p, S: Stage>(
|
||||
}}
|
||||
|
||||
macro duplicate($name: ident, $($first_span:tt)*) {{
|
||||
cx.emit_lint(
|
||||
let first_span = $($first_span)*;
|
||||
cx.emit_dyn_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::IgnoredDiagnosticOption {
|
||||
first_span: $($first_span)*,
|
||||
move |dcx, level| IgnoredDiagnosticOption {
|
||||
first_span,
|
||||
later_span: span,
|
||||
option_name: $name,
|
||||
},
|
||||
}.into_diag(dcx, level),
|
||||
span,
|
||||
);
|
||||
}}
|
||||
@@ -245,9 +256,19 @@ fn parse_directive_items<'p, S: Stage>(
|
||||
let (FormatWarning::InvalidSpecifier { span, .. }
|
||||
| FormatWarning::PositionalArgument { span, .. }
|
||||
| FormatWarning::DisallowedPlaceholder { span }) = warning;
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
|
||||
AttributeLintKind::MalformedDiagnosticFormat { warning },
|
||||
move |dcx, level| match warning {
|
||||
FormatWarning::PositionalArgument { .. } => {
|
||||
DisallowedPositionalArgument.into_diag(dcx, level)
|
||||
}
|
||||
FormatWarning::InvalidSpecifier { .. } => {
|
||||
InvalidFormatSpecifier.into_diag(dcx, level)
|
||||
}
|
||||
FormatWarning::DisallowedPlaceholder { .. } => {
|
||||
DisallowedPlaceholder.into_diag(dcx, level)
|
||||
}
|
||||
},
|
||||
span,
|
||||
);
|
||||
}
|
||||
@@ -255,12 +276,15 @@ fn parse_directive_items<'p, S: Stage>(
|
||||
f
|
||||
}
|
||||
Err(e) => {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
|
||||
AttributeLintKind::DiagnosticWrappedParserError {
|
||||
description: e.description,
|
||||
label: e.label,
|
||||
span: slice_span(input.span, e.span, is_snippet),
|
||||
move |dcx, level| {
|
||||
WrappedParserError {
|
||||
description: &e.description,
|
||||
label: &e.label,
|
||||
span: slice_span(input.span, e.span.clone(), is_snippet),
|
||||
}
|
||||
.into_diag(dcx, level)
|
||||
},
|
||||
input.span,
|
||||
);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
use rustc_hir::attrs::{
|
||||
AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow,
|
||||
};
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, edition, sym};
|
||||
use thin_vec::ThinVec;
|
||||
@@ -17,7 +16,8 @@
|
||||
AttrCrateLevelOnly, DocAliasDuplicated, DocAutoCfgExpectsHideOrShow,
|
||||
DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgWrongLiteral,
|
||||
DocTestLiteral, DocTestTakesList, DocTestUnknown, DocUnknownAny, DocUnknownInclude,
|
||||
DocUnknownPasses, DocUnknownPlugins, DocUnknownSpotlight, IllFormedAttributeInput,
|
||||
DocUnknownPasses, DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs,
|
||||
IllFormedAttributeInput, MalformedDoc,
|
||||
};
|
||||
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
|
||||
use crate::session_diagnostics::{
|
||||
@@ -84,18 +84,18 @@ fn expected_name_value<S: Stage>(
|
||||
span: Span,
|
||||
_name: Option<Symbol>,
|
||||
) {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::ExpectedNameValue,
|
||||
|dcx, level| ExpectedNameValue.into_diag(dcx, level),
|
||||
span,
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead.
|
||||
fn expected_no_args<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Span) {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::ExpectedNoArgs,
|
||||
|dcx, level| ExpectedNoArgs.into_diag(dcx, level),
|
||||
span,
|
||||
);
|
||||
}
|
||||
@@ -107,9 +107,9 @@ fn expected_string_literal<S: Stage>(
|
||||
span: Span,
|
||||
_actual_literal: Option<&MetaItemLit>,
|
||||
) {
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
|dcx, level| MalformedDoc.into_diag(dcx, level),
|
||||
span,
|
||||
);
|
||||
}
|
||||
@@ -203,9 +203,9 @@ fn parse_single_test_doc_attr_item<S: Stage>(
|
||||
// FIXME: remove this method once merged and uncomment the line below instead.
|
||||
// cx.expected_list(cx.attr_span, args);
|
||||
let span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
|dcx, level| MalformedDoc.into_diag(dcx, level),
|
||||
span,
|
||||
);
|
||||
return;
|
||||
@@ -399,9 +399,9 @@ fn parse_auto_cfg<S: Stage>(
|
||||
// FIXME: remove this method once merged and uncomment the line
|
||||
// below instead.
|
||||
// cx.expected_identifier(sub_item.path().span());
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
|dcx, level| MalformedDoc.into_diag(dcx, level),
|
||||
sub_item.path().span(),
|
||||
);
|
||||
continue;
|
||||
@@ -605,9 +605,9 @@ macro_rules! string_arg_and_crate_level {
|
||||
// FIXME: remove this method once merged and uncomment the line
|
||||
// below instead.
|
||||
// cx.unexpected_literal(lit.span);
|
||||
cx.emit_lint(
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
|dcx, level| MalformedDoc.into_diag(dcx, level),
|
||||
lit.span,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -325,3 +325,70 @@ pub(crate) struct IncorrectDoNotRecommendLocation {
|
||||
#[label("not a trait implementation")]
|
||||
pub target_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("malformed `doc` attribute input")]
|
||||
#[warning(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
pub(crate) struct MalformedDoc;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("didn't expect any arguments here")]
|
||||
#[warning(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
pub(crate) struct ExpectedNoArgs;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("expected this to be of the form `... = \"...\"`")]
|
||||
#[warning(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
pub(crate) struct ExpectedNameValue;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("malformed `{$attribute}` attribute")]
|
||||
#[help("{$options}")]
|
||||
pub(crate) struct MalFormedDiagnosticAttributeLint {
|
||||
pub attribute: &'static str,
|
||||
pub options: &'static str,
|
||||
#[label("invalid option found here")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("positional format arguments are not allowed here")]
|
||||
#[help(
|
||||
"only named format arguments with the name of one of the generic types are allowed in this context"
|
||||
)]
|
||||
pub(crate) struct DisallowedPositionalArgument;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("format arguments are not allowed here")]
|
||||
#[help("consider removing this format argument")]
|
||||
pub(crate) struct DisallowedPlaceholder;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("invalid format specifier")]
|
||||
#[help("no format specifier are supported in this position")]
|
||||
pub(crate) struct InvalidFormatSpecifier;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("{$description}")]
|
||||
pub(crate) struct WrappedParserError<'a> {
|
||||
pub description: &'a str,
|
||||
#[label("{$label}")]
|
||||
pub span: Span,
|
||||
pub label: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")]
|
||||
pub(crate) struct IgnoredDiagnosticOption {
|
||||
pub option_name: Symbol,
|
||||
#[label("`{$option_name}` is first declared here")]
|
||||
pub first_span: Span,
|
||||
#[label("`{$option_name}` is later redundantly declared here")]
|
||||
pub later_span: Span,
|
||||
}
|
||||
|
||||
@@ -3761,6 +3761,8 @@ pub enum OpaqueTyOrigin<D> {
|
||||
pub struct DelegationGenerics {
|
||||
pub parent_args_segment_id: Option<HirId>,
|
||||
pub child_args_segment_id: Option<HirId>,
|
||||
pub self_ty_id: Option<HirId>,
|
||||
pub propagate_self_ty: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
|
||||
@@ -4455,17 +4457,17 @@ pub fn is_struct_or_union(&self) -> bool {
|
||||
|
||||
expect_trait,
|
||||
(
|
||||
&'hir ImplRestriction<'hir>,
|
||||
Constness,
|
||||
IsAuto,
|
||||
Safety,
|
||||
&'hir ImplRestriction<'hir>,
|
||||
Ident,
|
||||
&'hir Generics<'hir>,
|
||||
GenericBounds<'hir>,
|
||||
&'hir [TraitItemId]
|
||||
),
|
||||
ItemKind::Trait(constness, is_auto, safety, impl_restriction, ident, generics, bounds, items),
|
||||
(*constness, *is_auto, *safety, impl_restriction, *ident, generics, bounds, items);
|
||||
ItemKind::Trait(impl_restriction, constness, is_auto, safety, ident, generics, bounds, items),
|
||||
(impl_restriction, *constness, *is_auto, *safety, *ident, generics, bounds, items);
|
||||
|
||||
expect_trait_alias, (Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
|
||||
ItemKind::TraitAlias(constness, ident, generics, bounds), (*constness, *ident, generics, bounds);
|
||||
@@ -4657,10 +4659,10 @@ pub enum ItemKind<'hir> {
|
||||
Union(Ident, &'hir Generics<'hir>, VariantData<'hir>),
|
||||
/// A trait definition.
|
||||
Trait(
|
||||
&'hir ImplRestriction<'hir>,
|
||||
Constness,
|
||||
IsAuto,
|
||||
Safety,
|
||||
&'hir ImplRestriction<'hir>,
|
||||
Ident,
|
||||
&'hir Generics<'hir>,
|
||||
GenericBounds<'hir>,
|
||||
|
||||
@@ -619,10 +619,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
||||
try_visit!(visitor.visit_variant_data(struct_definition));
|
||||
}
|
||||
ItemKind::Trait(
|
||||
ref impl_restriction,
|
||||
_constness,
|
||||
_is_auto,
|
||||
_safety,
|
||||
ref impl_restriction,
|
||||
ident,
|
||||
ref generics,
|
||||
bounds,
|
||||
|
||||
@@ -895,7 +895,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
||||
let item = tcx.hir_expect_item(def_id);
|
||||
|
||||
let (constness, is_alias, is_auto, safety, impl_restriction) = match item.kind {
|
||||
hir::ItemKind::Trait(constness, is_auto, safety, impl_restriction, ..) => (
|
||||
hir::ItemKind::Trait(impl_restriction, constness, is_auto, safety, ..) => (
|
||||
constness,
|
||||
false,
|
||||
is_auto == hir::IsAuto::Yes,
|
||||
@@ -959,9 +959,9 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
||||
|
||||
ty::TraitDef {
|
||||
def_id: def_id.to_def_id(),
|
||||
impl_restriction,
|
||||
safety,
|
||||
constness,
|
||||
impl_restriction,
|
||||
paren_sugar,
|
||||
has_auto_impl: is_auto,
|
||||
is_marker,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{HirId, PathSegment};
|
||||
use rustc_hir::{DelegationGenerics, HirId, PathSegment};
|
||||
use rustc_middle::ty::{
|
||||
self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
@@ -65,19 +65,35 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
}
|
||||
|
||||
enum SelfPositionKind {
|
||||
AfterLifetimes,
|
||||
AfterLifetimes(bool /* Should propagate self ty */),
|
||||
Zero,
|
||||
None,
|
||||
}
|
||||
|
||||
fn create_self_position_kind(caller_kind: FnKind, callee_kind: FnKind) -> SelfPositionKind {
|
||||
match (caller_kind, callee_kind) {
|
||||
fn get_delegation_generics(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> &DelegationGenerics {
|
||||
tcx.hir_node(tcx.local_def_id_to_hir_id(delegation_id))
|
||||
.fn_sig()
|
||||
.expect("processing delegation")
|
||||
.decl
|
||||
.opt_delegation_generics()
|
||||
.expect("processing delegation")
|
||||
}
|
||||
|
||||
fn create_self_position_kind(
|
||||
tcx: TyCtxt<'_>,
|
||||
delegation_id: LocalDefId,
|
||||
sig_id: DefId,
|
||||
) -> SelfPositionKind {
|
||||
match (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)) {
|
||||
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
|
||||
| (FnKind::AssocTraitImpl, FnKind::AssocTrait)
|
||||
| (FnKind::AssocTrait, FnKind::AssocTrait)
|
||||
| (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero,
|
||||
|
||||
(FnKind::Free, FnKind::AssocTrait) => SelfPositionKind::AfterLifetimes,
|
||||
(FnKind::Free, FnKind::AssocTrait) => {
|
||||
let propagate_self_ty = get_delegation_generics(tcx, delegation_id).propagate_self_ty;
|
||||
SelfPositionKind::AfterLifetimes(propagate_self_ty)
|
||||
}
|
||||
|
||||
_ => SelfPositionKind::None,
|
||||
}
|
||||
@@ -141,8 +157,7 @@ fn create_mapping<'tcx>(
|
||||
) -> FxHashMap<u32, u32> {
|
||||
let mut mapping: FxHashMap<u32, u32> = Default::default();
|
||||
|
||||
let (caller_kind, callee_kind) = (fn_kind(tcx, def_id), fn_kind(tcx, sig_id));
|
||||
let self_pos_kind = create_self_position_kind(caller_kind, callee_kind);
|
||||
let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
|
||||
let is_self_at_zero = matches!(self_pos_kind, SelfPositionKind::Zero);
|
||||
|
||||
// Is self at zero? If so insert mapping, self in sig parent is always at 0.
|
||||
@@ -156,7 +171,7 @@ fn create_mapping<'tcx>(
|
||||
args_index += get_delegation_parent_args_count_without_self(tcx, def_id, sig_id);
|
||||
|
||||
let sig_generics = tcx.generics_of(sig_id);
|
||||
let process_sig_parent_generics = matches!(callee_kind, FnKind::AssocTrait);
|
||||
let process_sig_parent_generics = matches!(fn_kind(tcx, sig_id), FnKind::AssocTrait);
|
||||
|
||||
if process_sig_parent_generics {
|
||||
for i in (sig_generics.has_self as usize)..sig_generics.parent_count {
|
||||
@@ -176,7 +191,9 @@ fn create_mapping<'tcx>(
|
||||
}
|
||||
|
||||
// If self after lifetimes insert mapping, relying that self is at 0 in sig parent.
|
||||
if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes) {
|
||||
// If self ty is propagated (meaning there is no generic param `Self`), the specified
|
||||
// self ty will be inserted in args in `create_generic_args`.
|
||||
if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes { .. }) {
|
||||
mapping.insert(0, args_index as u32);
|
||||
args_index += 1;
|
||||
}
|
||||
@@ -259,6 +276,22 @@ fn get_parent_and_inheritance_kind<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> Ty<'_> {
|
||||
get_delegation_generics(tcx, delegation_id)
|
||||
.self_ty_id
|
||||
.map(|id| {
|
||||
let ctx = ItemCtxt::new(tcx, delegation_id);
|
||||
ctx.lower_ty(tcx.hir_node(id).expect_ty())
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
Ty::new_error_with_message(
|
||||
tcx,
|
||||
tcx.def_span(delegation_id),
|
||||
"the self type must be specified",
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) -> Option<Ty<'tcx>> {
|
||||
let sig_id = tcx.hir_opt_delegation_sig_id(delegation_id).expect("Delegation must have sig_id");
|
||||
let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id));
|
||||
@@ -269,15 +302,19 @@ fn get_delegation_self_ty<'tcx>(tcx: TyCtxt<'tcx>, delegation_id: LocalDefId) ->
|
||||
| (FnKind::Free, FnKind::Free)
|
||||
| (FnKind::AssocTrait, FnKind::Free)
|
||||
| (FnKind::AssocTrait, FnKind::AssocTrait) => {
|
||||
match create_self_position_kind(caller_kind, callee_kind) {
|
||||
match create_self_position_kind(tcx, delegation_id, sig_id) {
|
||||
SelfPositionKind::None => None,
|
||||
SelfPositionKind::AfterLifetimes => {
|
||||
// Both sig parent and child lifetimes are in included in this count.
|
||||
Some(tcx.generics_of(delegation_id).own_counts().lifetimes)
|
||||
SelfPositionKind::AfterLifetimes(propagate_self_ty) => {
|
||||
if propagate_self_ty {
|
||||
Some(get_delegation_self_ty_or_err(tcx, delegation_id))
|
||||
} else {
|
||||
// Both sig parent and child lifetimes are in included in this count.
|
||||
let index = tcx.generics_of(delegation_id).own_counts().lifetimes;
|
||||
Some(Ty::new_param(tcx, index as u32, kw::SelfUpper))
|
||||
}
|
||||
}
|
||||
SelfPositionKind::Zero => Some(0),
|
||||
SelfPositionKind::Zero => Some(Ty::new_param(tcx, 0, kw::SelfUpper)),
|
||||
}
|
||||
.map(|self_index| Ty::new_param(tcx, self_index as u32, kw::SelfUpper))
|
||||
}
|
||||
|
||||
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
|
||||
@@ -366,7 +403,7 @@ fn create_generic_args<'tcx>(
|
||||
|
||||
let mut new_args = vec![];
|
||||
|
||||
let self_pos_kind = create_self_position_kind(caller_kind, callee_kind);
|
||||
let self_pos_kind = create_self_position_kind(tcx, delegation_id, sig_id);
|
||||
let mut lifetimes_end_pos;
|
||||
|
||||
if !parent_args.is_empty() {
|
||||
@@ -374,7 +411,7 @@ fn create_generic_args<'tcx>(
|
||||
parent_args.iter().filter(|a| a.as_region().is_some()).count();
|
||||
|
||||
match self_pos_kind {
|
||||
SelfPositionKind::AfterLifetimes => {
|
||||
SelfPositionKind::AfterLifetimes { .. } => {
|
||||
new_args.extend(&parent_args[1..1 + parent_args_lifetimes_count]);
|
||||
|
||||
lifetimes_end_pos = parent_args_lifetimes_count;
|
||||
@@ -407,6 +444,15 @@ fn create_generic_args<'tcx>(
|
||||
.count();
|
||||
|
||||
new_args.extend_from_slice(args);
|
||||
|
||||
// Parent args are empty, then if we should propagate self ty (meaning Self generic
|
||||
// param was not generated) then we should insert it, as it won't be in `args`.
|
||||
if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)) {
|
||||
new_args.insert(
|
||||
lifetimes_end_pos,
|
||||
ty::GenericArg::from(get_delegation_self_ty_or_err(tcx, delegation_id)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !child_args.is_empty() {
|
||||
@@ -427,7 +473,8 @@ fn create_generic_args<'tcx>(
|
||||
new_args.insert(lifetimes_end_pos + i, child_args[i]);
|
||||
}
|
||||
|
||||
let skip_self = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes);
|
||||
// If self_ty is propagated it means that Self generic param was not generated.
|
||||
let skip_self = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(false));
|
||||
new_args.extend(&child_args[child_lifetimes_count + skip_self as usize..]);
|
||||
}
|
||||
|
||||
@@ -446,6 +493,7 @@ struct PredicatesCollector<'tcx> {
|
||||
preds: Vec<(ty::Clause<'tcx>, Span)>,
|
||||
args: Vec<ty::GenericArg<'tcx>>,
|
||||
folder: ParamIndexRemapper<'tcx>,
|
||||
filter_self_preds: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> PredicatesCollector<'tcx> {
|
||||
@@ -458,6 +506,16 @@ fn with_own_preds(
|
||||
let args = self.args.as_slice();
|
||||
|
||||
for pred in preds.predicates {
|
||||
// If self ty is specified then there will be no generic param `Self`,
|
||||
// so we do not need its predicates.
|
||||
if self.filter_self_preds
|
||||
&& let Some(trait_pred) = pred.0.as_trait_clause()
|
||||
// Rely that `Self` has zero index.
|
||||
&& trait_pred.self_ty().skip_binder().is_param(0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let new_pred = pred.0.fold_with(&mut self.folder);
|
||||
self.preds.push((
|
||||
EarlyBinder::bind(new_pred).instantiate(self.tcx, args).skip_norm_wip(),
|
||||
@@ -484,8 +542,10 @@ fn with_preds(
|
||||
|
||||
let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id);
|
||||
let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args);
|
||||
let collector = PredicatesCollector { tcx, preds: vec![], args, folder };
|
||||
let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id);
|
||||
let filter_self_preds = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true));
|
||||
|
||||
let collector = PredicatesCollector { tcx, preds: vec![], args, folder, filter_self_preds };
|
||||
let (parent, inh_kind) = get_parent_and_inheritance_kind(tcx, def_id, sig_id);
|
||||
|
||||
// `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
|
||||
@@ -573,13 +633,7 @@ fn get_delegation_user_specified_args<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
delegation_id: LocalDefId,
|
||||
) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) {
|
||||
let info = tcx
|
||||
.hir_node(tcx.local_def_id_to_hir_id(delegation_id))
|
||||
.fn_sig()
|
||||
.expect("Lowering delegation")
|
||||
.decl
|
||||
.opt_delegation_generics()
|
||||
.expect("Lowering delegation");
|
||||
let info = get_delegation_generics(tcx, delegation_id);
|
||||
|
||||
let get_segment = |hir_id: HirId| -> Option<(&'tcx PathSegment<'tcx>, DefId)> {
|
||||
let segment = tcx.hir_node(hir_id).expect_path_segment();
|
||||
|
||||
@@ -1115,12 +1115,12 @@ enum Descr {
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// FIXME(fmease): Does not account for `dyn Trait<>` (suggs `dyn Trait<, X = Y>`).
|
||||
let code = if let Some(snippet) = snippet.strip_suffix('>') {
|
||||
// The user wrote `Trait<'a>` or similar and we don't have a term we can suggest,
|
||||
// but at least we can clue them to the correct syntax `Trait<'a, Item = /* ... */>`
|
||||
// while accounting for the `<'a>` in the suggestion.
|
||||
format!("{}, {}>", snippet, bindings.join(", "))
|
||||
let code = if let Some(snippet) = snippet.strip_suffix("<>") {
|
||||
// Empty generics
|
||||
format!("{snippet}<{}>", bindings.join(", "))
|
||||
} else if let Some(snippet) = snippet.strip_suffix('>') {
|
||||
// Non-empty generics
|
||||
format!("{snippet}, {}>", bindings.join(", "))
|
||||
} else if in_expr_or_pat {
|
||||
// The user wrote `Trait`, so we don't have a term we can suggest, but at least we
|
||||
// can clue them to the correct syntax `Trait::<Item = /* ... */>`.
|
||||
|
||||
@@ -758,20 +758,20 @@ fn print_item(&mut self, item: &hir::Item<'_>) {
|
||||
self.bclose(item.span, cb);
|
||||
}
|
||||
hir::ItemKind::Trait(
|
||||
impl_restriction,
|
||||
constness,
|
||||
is_auto,
|
||||
safety,
|
||||
impl_restriction,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
trait_items,
|
||||
) => {
|
||||
let (cb, ib) = self.head("");
|
||||
self.print_impl_restriction(impl_restriction);
|
||||
self.print_constness(constness);
|
||||
self.print_is_auto(is_auto);
|
||||
self.print_safety(safety);
|
||||
self.print_impl_restriction(impl_restriction);
|
||||
self.word_nbsp("trait");
|
||||
self.print_ident(ident);
|
||||
self.print_generic_params(generics.params);
|
||||
|
||||
@@ -1900,7 +1900,7 @@ fn handle_unsatisfied_predicates(
|
||||
entry.1.insert((self_ty.span, String::new()));
|
||||
}
|
||||
Some(Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..),
|
||||
kind: hir::ItemKind::Trait(_, _, rustc_ast::ast::IsAuto::Yes, ..),
|
||||
span: item_span,
|
||||
..
|
||||
})) => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use rustc_data_structures::sync::DynSend;
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level};
|
||||
use rustc_hir::lints::{AttributeLintKind, FormatWarning};
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
|
||||
@@ -43,33 +43,6 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||
.into_diag(dcx, level)
|
||||
}
|
||||
|
||||
&AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level),
|
||||
|
||||
&AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level),
|
||||
|
||||
&AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level),
|
||||
&AttributeLintKind::MalFormedDiagnosticAttribute { attribute, options, span } => {
|
||||
lints::MalFormedDiagnosticAttributeLint { attribute, options, span }
|
||||
.into_diag(dcx, level)
|
||||
}
|
||||
AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning {
|
||||
FormatWarning::PositionalArgument { .. } => {
|
||||
lints::DisallowedPositionalArgument.into_diag(dcx, level)
|
||||
}
|
||||
FormatWarning::InvalidSpecifier { .. } => {
|
||||
lints::InvalidFormatSpecifier.into_diag(dcx, level)
|
||||
}
|
||||
FormatWarning::DisallowedPlaceholder { .. } => {
|
||||
lints::DisallowedPlaceholder.into_diag(dcx, level)
|
||||
}
|
||||
},
|
||||
AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => {
|
||||
lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level)
|
||||
}
|
||||
&AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => {
|
||||
lints::IgnoredDiagnosticOption { option_name, first_span, later_span }
|
||||
.into_diag(dcx, level)
|
||||
}
|
||||
&AttributeLintKind::MissingOptionsForDiagnosticAttribute { attribute, options } => {
|
||||
lints::MissingOptionsForDiagnosticAttribute { attribute, options }
|
||||
.into_diag(dcx, level)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#![feature(box_patterns)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(titlecase)]
|
||||
#![feature(try_blocks)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
||||
@@ -3282,63 +3282,6 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("malformed `doc` attribute input")]
|
||||
#[warning(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
pub(crate) struct MalformedDoc;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("didn't expect any arguments here")]
|
||||
#[warning(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
pub(crate) struct ExpectedNoArgs;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("expected this to be of the form `... = \"...\"`")]
|
||||
#[warning(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
pub(crate) struct ExpectedNameValue;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("positional format arguments are not allowed here")]
|
||||
#[help(
|
||||
"only named format arguments with the name of one of the generic types are allowed in this context"
|
||||
)]
|
||||
pub(crate) struct DisallowedPositionalArgument;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("format arguments are not allowed here")]
|
||||
#[help("consider removing this format argument")]
|
||||
pub(crate) struct DisallowedPlaceholder;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("invalid format specifier")]
|
||||
#[help("no format specifier are supported in this position")]
|
||||
pub(crate) struct InvalidFormatSpecifier;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("{$description}")]
|
||||
pub(crate) struct WrappedParserError<'a> {
|
||||
pub description: &'a str,
|
||||
#[label("{$label}")]
|
||||
pub span: Span,
|
||||
pub label: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")]
|
||||
pub(crate) struct IgnoredDiagnosticOption {
|
||||
pub option_name: Symbol,
|
||||
#[label("`{$option_name}` is first declared here")]
|
||||
pub first_span: Span,
|
||||
#[label("`{$option_name}` is later redundantly declared here")]
|
||||
pub later_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("missing options for `{$attribute}` attribute")]
|
||||
#[help("{$options}")]
|
||||
@@ -3358,13 +3301,3 @@ pub(crate) struct MissingOptionsForDiagnosticAttribute {
|
||||
"only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma"
|
||||
)]
|
||||
pub(crate) struct NonMetaItemDiagnosticAttribute;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("malformed `{$attribute}` attribute")]
|
||||
#[help("{$options}")]
|
||||
pub(crate) struct MalFormedDiagnosticAttributeLint {
|
||||
pub attribute: &'static str,
|
||||
pub options: &'static str,
|
||||
#[label("invalid option found here")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@@ -47,34 +47,46 @@
|
||||
|
||||
declare_lint_pass!(NonCamelCaseTypes => [NON_CAMEL_CASE_TYPES]);
|
||||
|
||||
/// Some unicode characters *have* case, are considered upper case or lower case, but they *can't*
|
||||
/// be upper cased or lower cased. For the purposes of the lint suggestion, we care about being able
|
||||
/// Some unicode characters *have* case, are considered upper, title, or lower case, but they *can't*
|
||||
/// be title cased or lower cased. For the purposes of the lint suggestion, we care about being able
|
||||
/// to change the char's case.
|
||||
fn char_has_case(c: char) -> bool {
|
||||
!c.to_lowercase().eq(c.to_uppercase())
|
||||
!c.to_lowercase().eq(c.to_titlecase())
|
||||
}
|
||||
|
||||
// contains a capitalisable character followed by, or preceded by, an underscore
|
||||
fn has_underscore_case(s: &str) -> bool {
|
||||
/// FIXME: we should add a more efficient version
|
||||
/// in the stdlib for this
|
||||
fn changes_when_titlecased(c: char) -> bool {
|
||||
!c.to_titlecase().eq([c])
|
||||
}
|
||||
|
||||
// contains a capitalisable character followed by, or preceded by, an underscore,
|
||||
// or contains an uppercase character that changes when titlecased,
|
||||
// or contains `__`
|
||||
fn not_camel_case(s: &str) -> bool {
|
||||
let mut last = '\0';
|
||||
s.chars().any(|c| match (std::mem::replace(&mut last, c), c) {
|
||||
('_', cs) | (cs, '_') => char_has_case(cs),
|
||||
_ => false,
|
||||
s.chars().any(|snd| {
|
||||
let fst = std::mem::replace(&mut last, snd);
|
||||
match (fst, snd) {
|
||||
('_', '_') => return true,
|
||||
('_', _) if char_has_case(snd) => return true,
|
||||
(_, '_') if char_has_case(fst) => return true,
|
||||
_ => snd.is_uppercase() && changes_when_titlecased(snd),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_camel_case(name: &str) -> bool {
|
||||
fn is_upper_camel_case(name: &str) -> bool {
|
||||
let name = name.trim_matches('_');
|
||||
let Some(first) = name.chars().next() else {
|
||||
return true;
|
||||
};
|
||||
|
||||
// start with a non-lowercase letter rather than uppercase
|
||||
// ones (some scripts don't have a concept of upper/lowercase)
|
||||
!(first.is_lowercase() || name.contains("__") || has_underscore_case(name))
|
||||
// some scripts don't have a concept of upper/lowercase
|
||||
!(changes_when_titlecased(first) || not_camel_case(name))
|
||||
}
|
||||
|
||||
fn to_camel_case(s: &str) -> String {
|
||||
fn to_upper_camel_case(s: &str) -> String {
|
||||
s.trim_matches('_')
|
||||
.split('_')
|
||||
.filter(|component| !component.is_empty())
|
||||
@@ -83,24 +95,31 @@ fn to_camel_case(s: &str) -> String {
|
||||
|
||||
let mut new_word = true;
|
||||
let mut prev_is_lower_case = true;
|
||||
let mut prev_is_lowercased_sigma = false;
|
||||
|
||||
for c in component.chars() {
|
||||
// Preserve the case if an uppercase letter follows a lowercase letter, so that
|
||||
// `camelCase` is converted to `CamelCase`.
|
||||
if prev_is_lower_case && c.is_uppercase() {
|
||||
if prev_is_lower_case && (c.is_uppercase() | c.is_titlecase()) {
|
||||
new_word = true;
|
||||
}
|
||||
|
||||
if new_word {
|
||||
camel_cased_component.extend(c.to_uppercase());
|
||||
camel_cased_component.extend(c.to_titlecase());
|
||||
} else {
|
||||
camel_cased_component.extend(c.to_lowercase());
|
||||
}
|
||||
|
||||
prev_is_lower_case = c.is_lowercase();
|
||||
prev_is_lower_case = c.is_lowercase() || c.is_titlecase();
|
||||
prev_is_lowercased_sigma = !new_word && c == 'Σ';
|
||||
new_word = false;
|
||||
}
|
||||
|
||||
if prev_is_lowercased_sigma {
|
||||
camel_cased_component.pop();
|
||||
camel_cased_component.push('ς');
|
||||
}
|
||||
|
||||
camel_cased_component
|
||||
})
|
||||
.fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
|
||||
@@ -122,8 +141,8 @@ impl NonCamelCaseTypes {
|
||||
fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
|
||||
let name = ident.name.as_str();
|
||||
|
||||
if !is_camel_case(name) {
|
||||
let cc = to_camel_case(name);
|
||||
if !is_upper_camel_case(name) {
|
||||
let cc = to_upper_camel_case(name);
|
||||
let sub = if *name != cc {
|
||||
NonCamelCaseTypeSub::Suggestion { span: ident.span, replace: cc }
|
||||
} else {
|
||||
@@ -235,14 +254,20 @@ fn to_snake_case(mut name: &str) -> String {
|
||||
continue;
|
||||
}
|
||||
for ch in s.chars() {
|
||||
if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper {
|
||||
words.push(buf);
|
||||
if !buf.is_empty()
|
||||
&& buf != "'"
|
||||
&& (ch.is_uppercase() || ch.is_titlecase())
|
||||
&& !last_upper
|
||||
{
|
||||
// We lowercase only at the end, to handle final sigma correctly
|
||||
words.push(buf.to_lowercase());
|
||||
buf = String::new();
|
||||
}
|
||||
last_upper = ch.is_uppercase();
|
||||
buf.extend(ch.to_lowercase());
|
||||
last_upper = ch.is_uppercase() || ch.is_titlecase();
|
||||
buf.push(ch);
|
||||
}
|
||||
words.push(buf);
|
||||
// We lowercase only at the end, to handle final sigma correctly
|
||||
words.push(buf.to_lowercase());
|
||||
}
|
||||
words.join("_")
|
||||
}
|
||||
@@ -262,7 +287,8 @@ fn is_snake_case(ident: &str) -> bool {
|
||||
|
||||
// This correctly handles letters in languages with and without
|
||||
// cases, as well as numbers and underscores.
|
||||
!ident.chars().any(char::is_uppercase)
|
||||
// FIXME: we should add a standard library impl of `c.to_lowercase().eq([c])`
|
||||
ident.chars().all(|c| c.to_lowercase().eq([c]))
|
||||
}
|
||||
|
||||
let name = ident.name.as_str();
|
||||
@@ -474,10 +500,12 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||
impl NonUpperCaseGlobals {
|
||||
fn check_upper_case(cx: &LateContext<'_>, sort: &str, did: Option<LocalDefId>, ident: &Ident) {
|
||||
let name = ident.name.as_str();
|
||||
if name.chars().any(|c| c.is_lowercase()) {
|
||||
// FIXME: we should add a more efficient version
|
||||
// in the stdlib for `c.to_uppercase().eq([c])`
|
||||
if !name.chars().all(|c| c.to_uppercase().eq([c])) {
|
||||
let uc = NonSnakeCase::to_snake_case(name).to_uppercase();
|
||||
|
||||
// If the item is exported, suggesting changing it's name would be breaking-change
|
||||
// If the item is exported, suggesting changing its name would be a breaking change
|
||||
// and could break users without a "nice" applicable fix, so let's avoid it.
|
||||
let can_change_usages = if let Some(did) = did {
|
||||
!cx.tcx.effective_visibilities(()).is_exported(did)
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
use super::{is_camel_case, to_camel_case};
|
||||
use super::{is_upper_camel_case, to_upper_camel_case};
|
||||
|
||||
#[test]
|
||||
fn camel_case() {
|
||||
assert!(!is_camel_case("userData"));
|
||||
assert_eq!(to_camel_case("userData"), "UserData");
|
||||
assert!(!is_upper_camel_case("userData"));
|
||||
assert_eq!(to_upper_camel_case("userData"), "UserData");
|
||||
|
||||
assert!(is_camel_case("X86_64"));
|
||||
assert!(is_upper_camel_case("X86_64"));
|
||||
|
||||
assert!(!is_camel_case("X86__64"));
|
||||
assert_eq!(to_camel_case("X86__64"), "X86_64");
|
||||
assert!(!is_upper_camel_case("X86__64"));
|
||||
assert_eq!(to_upper_camel_case("X86__64"), "X86_64");
|
||||
|
||||
assert!(!is_camel_case("Abc_123"));
|
||||
assert_eq!(to_camel_case("Abc_123"), "Abc123");
|
||||
assert!(!is_upper_camel_case("Abc_123"));
|
||||
assert_eq!(to_upper_camel_case("Abc_123"), "Abc123");
|
||||
|
||||
assert!(!is_camel_case("A1_b2_c3"));
|
||||
assert_eq!(to_camel_case("A1_b2_c3"), "A1B2C3");
|
||||
assert!(!is_upper_camel_case("A1_b2_c3"));
|
||||
assert_eq!(to_upper_camel_case("A1_b2_c3"), "A1B2C3");
|
||||
|
||||
assert!(!is_camel_case("ONE_TWO_THREE"));
|
||||
assert_eq!(to_camel_case("ONE_TWO_THREE"), "OneTwoThree");
|
||||
assert!(!is_upper_camel_case("ONE_TWO_THREE"));
|
||||
assert_eq!(to_upper_camel_case("ONE_TWO_THREE"), "OneTwoThree");
|
||||
|
||||
// FIXME(@Jules-Bertholet): This test doesn't work due to what I believe
|
||||
// is a Unicode spec bug - uppercase Georgian letters have
|
||||
// incorrect titlecase mappings.
|
||||
// I've reported it to Unicode.
|
||||
// Georgian mtavruli is only used in all-caps
|
||||
//assert!(!is_upper_camel_case("ᲫალაᲔრთობაშია"));
|
||||
//assert_eq!(to_upper_camel_case("ᲫალაᲔრთობაშია"), "ძალა_ერთობაშია");
|
||||
|
||||
assert!(!is_upper_camel_case("LJNJaaaDŽooo"));
|
||||
assert_eq!(to_upper_camel_case("LJNJaaLjNJaDŽooo"), "LjnjaaLjNjaDžooo");
|
||||
|
||||
// Final sigma
|
||||
assert!(!is_upper_camel_case("ΦΙΛΟΣ_ΦΙΛΟΣ"));
|
||||
assert_eq!(to_upper_camel_case("ΦΙΛΟΣ_ΦΙΛΟΣ"), "ΦιλοςΦιλος");
|
||||
assert!(is_upper_camel_case("ΦιλοσΦιλοσ"));
|
||||
}
|
||||
|
||||
@@ -656,13 +656,6 @@ pub enum DeprecatedSinceKind {
|
||||
pub enum AttributeLintKind {
|
||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||
MalformedDoc,
|
||||
ExpectedNoArgs,
|
||||
ExpectedNameValue,
|
||||
MalFormedDiagnosticAttribute { attribute: &'static str, options: &'static str, span: Span },
|
||||
MalformedDiagnosticFormat { warning: FormatWarning },
|
||||
DiagnosticWrappedParserError { description: String, label: String, span: Span },
|
||||
IgnoredDiagnosticOption { option_name: Symbol, first_span: Span, later_span: Span },
|
||||
MissingOptionsForDiagnosticAttribute { attribute: &'static str, options: &'static str },
|
||||
NonMetaItemDiagnosticAttribute,
|
||||
}
|
||||
|
||||
@@ -319,7 +319,17 @@ pub fn hir_body_const_context(self, local_def_id: LocalDefId) -> Option<ConstCon
|
||||
BodyOwnerKind::Fn if self.is_constructor(def_id) => return None,
|
||||
// Const closures use their parent's const context
|
||||
BodyOwnerKind::Closure if self.is_const_fn(def_id) => {
|
||||
return self.hir_body_const_context(self.local_parent(local_def_id));
|
||||
return Some(
|
||||
self.hir_body_const_context(self.local_parent(local_def_id)).unwrap_or_else(
|
||||
|| {
|
||||
assert!(
|
||||
self.dcx().has_errors().is_some(),
|
||||
"`const` closure with no enclosing const context",
|
||||
);
|
||||
ConstContext::ConstFn
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
BodyOwnerKind::Fn if self.is_const_fn(def_id) => ConstContext::ConstFn,
|
||||
BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None,
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
pub struct TraitDef {
|
||||
pub def_id: DefId,
|
||||
|
||||
/// Restrictions on trait implementations.
|
||||
pub impl_restriction: ImplRestrictionKind,
|
||||
|
||||
pub safety: hir::Safety,
|
||||
|
||||
/// Whether this trait is `const`.
|
||||
pub constness: hir::Constness,
|
||||
|
||||
/// Restrictions on trait implementations.
|
||||
pub impl_restriction: ImplRestrictionKind,
|
||||
|
||||
/// If `true`, then this trait had the `#[rustc_paren_sugar]`
|
||||
/// attribute, indicating that it should be used with `Foo()`
|
||||
/// sugar. This is a temporary thing -- eventually any trait will
|
||||
|
||||
@@ -1052,80 +1052,69 @@ fn parse_defaultness(&mut self) -> Defaultness {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is there an `[ impl(in? path) ]? trait` item `dist` tokens ahead?
|
||||
fn is_trait_with_maybe_impl_restriction_in_front(&self, dist: usize) -> bool {
|
||||
// `trait`
|
||||
if self.is_keyword_ahead(dist, &[kw::Trait]) {
|
||||
return true;
|
||||
}
|
||||
// `impl(`
|
||||
if !self.is_keyword_ahead(dist, &[kw::Impl])
|
||||
|| !self.look_ahead(dist + 1, |t| t == &token::OpenParen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// `crate | super | self) trait`
|
||||
if self.is_keyword_ahead(dist + 2, &[kw::Crate, kw::Super, kw::SelfLower])
|
||||
&& self.look_ahead(dist + 3, |t| t == &token::CloseParen)
|
||||
&& self.is_keyword_ahead(dist + 4, &[kw::Trait])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// `impl(in? something) trait`
|
||||
// We catch cases where the `in` keyword is missing to provide a
|
||||
// better error message. This is handled later in
|
||||
// `self.recover_incorrect_impl_restriction`.
|
||||
self.tree_look_ahead(dist + 2, |t| {
|
||||
if let TokenTree::Token(token, _) = t { token.is_keyword(kw::Trait) } else { false }
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Is this an `(const unsafe? auto? [ impl(in? path) ]? | unsafe auto? [ impl(in? path) ]? | auto [ impl(in? path) ]? | [ impl(in? path) ]?) trait` item?
|
||||
/// Is this an `[impl(in? path)]? const? unsafe? auto? trait` item?
|
||||
fn check_trait_front_matter(&mut self) -> bool {
|
||||
// `[ impl(in? path) ]? trait`
|
||||
if self.is_trait_with_maybe_impl_restriction_in_front(0) {
|
||||
return true;
|
||||
const SUFFIXES: &[&[Symbol]] = &[
|
||||
&[kw::Trait],
|
||||
&[kw::Auto, kw::Trait],
|
||||
&[kw::Unsafe, kw::Trait],
|
||||
&[kw::Unsafe, kw::Auto, kw::Trait],
|
||||
&[kw::Const, kw::Trait],
|
||||
&[kw::Const, kw::Auto, kw::Trait],
|
||||
&[kw::Const, kw::Unsafe, kw::Trait],
|
||||
&[kw::Const, kw::Unsafe, kw::Auto, kw::Trait],
|
||||
];
|
||||
// `impl(`
|
||||
if self.check_keyword(exp!(Impl)) && self.look_ahead(1, |t| t == &token::OpenParen) {
|
||||
// `impl(in` unambiguously introduces an `impl` restriction
|
||||
if self.is_keyword_ahead(2, &[kw::In]) {
|
||||
return true;
|
||||
}
|
||||
// `impl(crate | self | super)` + SUFFIX
|
||||
if self.is_keyword_ahead(2, &[kw::Crate, kw::SelfLower, kw::Super])
|
||||
&& self.look_ahead(3, |t| t == &token::CloseParen)
|
||||
&& SUFFIXES.iter().any(|suffix| {
|
||||
suffix.iter().enumerate().all(|(i, kw)| self.is_keyword_ahead(i + 4, &[*kw]))
|
||||
})
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Recover cases like `impl(path::to::module)` + SUFFIX to suggest inserting `in`.
|
||||
SUFFIXES.iter().any(|suffix| {
|
||||
suffix.iter().enumerate().all(|(i, kw)| {
|
||||
self.tree_look_ahead(i + 2, |t| {
|
||||
if let TokenTree::Token(token, _) = t {
|
||||
token.is_keyword(*kw)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
SUFFIXES.iter().any(|suffix| {
|
||||
suffix.iter().enumerate().all(|(i, kw)| {
|
||||
// We use `check_keyword` for the first token to include it in the expected tokens.
|
||||
if i == 0 {
|
||||
match *kw {
|
||||
kw::Const => self.check_keyword(exp!(Const)),
|
||||
kw::Unsafe => self.check_keyword(exp!(Unsafe)),
|
||||
kw::Auto => self.check_keyword(exp!(Auto)),
|
||||
kw::Trait => self.check_keyword(exp!(Trait)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
self.is_keyword_ahead(i, &[*kw])
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// `auto [ impl(in? path) ]? trait`
|
||||
if self.check_keyword(exp!(Auto)) && self.is_trait_with_maybe_impl_restriction_in_front(1) {
|
||||
return true;
|
||||
}
|
||||
// `unsafe auto? [ impl(in? path) ]? trait`
|
||||
if self.check_keyword(exp!(Unsafe))
|
||||
&& (self.is_trait_with_maybe_impl_restriction_in_front(1)
|
||||
|| self.is_keyword_ahead(1, &[kw::Auto])
|
||||
&& self.is_trait_with_maybe_impl_restriction_in_front(2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// `const` ...
|
||||
if !self.check_keyword(exp!(Const)) {
|
||||
return false;
|
||||
}
|
||||
// `const [ impl(in? path) ]? trait`
|
||||
if self.is_trait_with_maybe_impl_restriction_in_front(1) {
|
||||
return true;
|
||||
}
|
||||
// `const (unsafe | auto) [ impl(in? path) ]? trait`
|
||||
if self.is_keyword_ahead(1, &[kw::Unsafe, kw::Auto])
|
||||
&& self.is_trait_with_maybe_impl_restriction_in_front(2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// `const unsafe auto [ impl(in? path) ]? trait`
|
||||
self.is_keyword_ahead(1, &[kw::Unsafe])
|
||||
&& self.is_keyword_ahead(2, &[kw::Auto])
|
||||
&& self.is_trait_with_maybe_impl_restriction_in_front(3)
|
||||
}
|
||||
|
||||
/// Parses `const? unsafe? auto? [impl(in? path)]? trait Foo { ... }` or `trait Foo = Bar;`.
|
||||
///
|
||||
/// FIXME(restrictions): The current keyword order follows the grammar specified in RFC 3323.
|
||||
/// However, whether the restriction should be grouped closer to the visibility modifier
|
||||
/// (e.g., `pub impl(crate) const unsafe auto trait`) remains an unresolved design question.
|
||||
/// This ordering must be kept in sync with the logic in `check_trait_front_matter`.
|
||||
/// Parses `[impl(in? path)]? const? unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
|
||||
fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
|
||||
let impl_restriction = self.parse_impl_restriction()?;
|
||||
let constness = self.parse_constness(Case::Sensitive);
|
||||
if let Const::Yes(span) = constness {
|
||||
self.psess.gated_spans.gate(sym::const_trait_impl, span);
|
||||
@@ -1139,8 +1128,6 @@ fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, Ite
|
||||
IsAuto::No
|
||||
};
|
||||
|
||||
let impl_restriction = self.parse_impl_restriction()?;
|
||||
|
||||
self.expect_keyword(exp!(Trait))?;
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
@@ -1181,10 +1168,10 @@ fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, Ite
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
|
||||
Ok(ItemKind::Trait(Box::new(Trait {
|
||||
impl_restriction,
|
||||
constness,
|
||||
is_auto,
|
||||
safety,
|
||||
impl_restriction,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
@@ -2966,7 +2953,7 @@ pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> b
|
||||
&& !self.is_unsafe_foreign_mod()
|
||||
// Rule out `async gen {` and `async gen move {`
|
||||
&& !self.is_async_gen_block()
|
||||
// Rule out `const unsafe auto` and `const unsafe trait` and `const unsafe impl`.
|
||||
// Rule out `const unsafe auto` and `const unsafe trait` and `const unsafe impl`
|
||||
&& !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
|
||||
)
|
||||
})
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
|
||||
SourceKindMultiSuggestion, SourceKindSubdiag,
|
||||
};
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::{InferCtxt, TyOrConstInferVar};
|
||||
|
||||
pub enum TypeAnnotationNeeded {
|
||||
/// ```compile_fail,E0282
|
||||
@@ -82,13 +82,27 @@ fn can_add_more_info(&self) -> bool {
|
||||
!(self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. }))
|
||||
}
|
||||
|
||||
fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
|
||||
fn where_x_is_kind<'tcx>(&self, infcx: &InferCtxt<'tcx>, in_type: Ty<'tcx>) -> &'static str {
|
||||
if in_type.is_ty_or_numeric_infer() {
|
||||
""
|
||||
} else if self.name == "_" {
|
||||
// FIXME: Consider specializing this message if there is a single `_`
|
||||
// in the type.
|
||||
"underscore"
|
||||
let displayed_ty = infcx
|
||||
.resolve_vars_if_possible(in_type)
|
||||
.fold_with(&mut ClosureEraser { infcx, depth: 0 });
|
||||
if displayed_ty.is_ty_or_numeric_infer() {
|
||||
""
|
||||
} else {
|
||||
match displayed_ty
|
||||
.walk()
|
||||
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
|
||||
.take(2)
|
||||
.count()
|
||||
{
|
||||
0 => "",
|
||||
1 => "underscore_single",
|
||||
_ => "underscore_multiple",
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"has_name"
|
||||
}
|
||||
@@ -555,7 +569,7 @@ pub fn emit_inference_failure_err_with_type_hint(
|
||||
infer_subdiags.push(SourceKindSubdiag::LetLike {
|
||||
span: insert_span,
|
||||
name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
|
||||
x_kind: arg_data.where_x_is_kind(ty),
|
||||
x_kind: arg_data.where_x_is_kind(self.infcx, ty),
|
||||
prefix_kind: arg_data.kind.clone(),
|
||||
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
|
||||
arg_name: arg_data.name,
|
||||
@@ -567,7 +581,7 @@ pub fn emit_inference_failure_err_with_type_hint(
|
||||
infer_subdiags.push(SourceKindSubdiag::LetLike {
|
||||
span: insert_span,
|
||||
name: String::new(),
|
||||
x_kind: arg_data.where_x_is_kind(ty),
|
||||
x_kind: arg_data.where_x_is_kind(self.infcx, ty),
|
||||
prefix_kind: arg_data.kind.clone(),
|
||||
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
|
||||
arg_name: arg_data.name,
|
||||
|
||||
@@ -4142,7 +4142,7 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
||||
let mut is_auto_trait = false;
|
||||
match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
|
||||
Some(Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, is_auto, _, _, ident, _, _, _),
|
||||
kind: hir::ItemKind::Trait(_, _, is_auto, _, ident, _, _, _),
|
||||
..
|
||||
})) => {
|
||||
// FIXME: we should do something else so that it works even on crate foreign
|
||||
|
||||
@@ -277,7 +277,8 @@ pub(crate) enum SourceKindSubdiag<'a> {
|
||||
[const_with_param] value of const parameter
|
||||
[const] value of the constant
|
||||
} `{$arg_name}` is specified
|
||||
[underscore] , where the placeholders `_` are specified
|
||||
[underscore_single] , where the placeholder `_` is specified
|
||||
[underscore_multiple] , where the placeholders `_` are specified
|
||||
*[empty] {\"\"}
|
||||
}",
|
||||
style = "verbose",
|
||||
|
||||
Reference in New Issue
Block a user