Rollup merge of #101162 - rajputrajat:master, r=davidtwco

Migrate rustc_resolve to use SessionDiagnostic, part # 1

crate a somewhat on larger size, so plz allow some time to get it finished.
This commit is contained in:
Matthias Krüger 2022-11-18 14:13:35 +01:00 committed by GitHub
commit 3e5965722c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 884 additions and 362 deletions

View File

@ -4045,6 +4045,7 @@ dependencies = [
"rustc_feature", "rustc_feature",
"rustc_hir", "rustc_hir",
"rustc_index", "rustc_index",
"rustc_macros",
"rustc_metadata", "rustc_metadata",
"rustc_middle", "rustc_middle",
"rustc_query_system", "rustc_query_system",

View File

@ -0,0 +1,211 @@
resolve_parent_module_reset_for_binding =
parent module is reset for binding
resolve_ampersand_used_without_explicit_lifetime_name =
`&` without an explicit lifetime name cannot be used here
.note = explicit lifetime name needed here
resolve_underscore_lifetime_name_cannot_be_used_here =
`'_` cannot be used here
.note = `'_` is a reserved lifetime name
resolve_crate_may_not_be_imported =
`$crate` may not be imported
resolve_crate_root_imports_must_be_named_explicitly =
crate root imports need to be explicitly named: `use crate as name;`
resolve_generic_params_from_outer_function =
can't use generic parameters from outer function
.label = use of generic parameter from outer function
.suggestion = try using a local generic parameter instead
resolve_self_type_implicitly_declared_by_impl =
`Self` type implicitly declared here, by this `impl`
resolve_cannot_use_self_type_here =
can't use `Self` here
resolve_use_a_type_here_instead =
use a type here instead
resolve_type_param_from_outer_fn =
type parameter from outer function
resolve_const_param_from_outer_fn =
const parameter from outer function
resolve_try_using_local_generic_parameter =
try using a local generic parameter instead
resolve_try_adding_local_generic_param_on_method =
try adding a local generic parameter in this method instead
resolve_help_try_using_local_generic_param =
try using a local generic paramter instead
resolve_name_is_already_used_as_generic_parameter =
the name `{$name}` is already used for a generic parameter in this item's generic parameters
.label = already used
.first_use_of_name = first use of `{$name}`
resolve_method_not_member_of_trait =
method `{$method}` is not a member of trait `{$trait_}`
.label = not a member of trait `{$trait_}`
resolve_associated_fn_with_similar_name_exists =
there is an associated function with a similar name
resolve_type_not_member_of_trait =
type `{$type_}` is not a member of trait `{$trait_}`
.label = not a member of trait `{$trait_}`
resolve_associated_type_with_similar_name_exists =
there is an associated type with a similar name
resolve_const_not_member_of_trait =
const `{$const_}` is not a member of trait `{$trait_}`
.label = not a member of trait `{$trait_}`
resolve_associated_const_with_similar_name_exists =
there is an associated constant with a similar name
resolve_variable_bound_with_different_mode =
variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
.label = bound in different ways
.first_binding_span = first binding
resolve_ident_bound_more_than_once_in_parameter_list =
identifier `{$identifier}` is bound more than once in this parameter list
.label = used as parameter more than once
resolve_ident_bound_more_than_once_in_same_pattern =
identifier `{$identifier}` is bound more than once in the same pattern
.label = used in a pattern more than once
resolve_undeclared_label =
use of undeclared label `{$name}`
.label = undeclared label `{$name}`
resolve_label_with_similar_name_reachable =
a label with a similar name is reachable
resolve_try_using_similarly_named_label =
try using similarly named label
resolve_unreachable_label_with_similar_name_exists =
a label with a similar name exists but is unreachable
resolve_self_import_can_only_appear_once_in_the_list =
`self` import can only appear once in an import list
.label = can only appear once in an import list
resolve_self_import_only_in_import_list_with_non_empty_prefix =
`self` import can only appear in an import list with a non-empty prefix
.label = can only appear in an import list with a non-empty prefix
resolve_cannot_capture_dynamic_environment_in_fn_item =
can't capture dynamic environment in a fn item
.help = use the `|| {"{"} ... {"}"}` closure form instead
resolve_attempt_to_use_non_constant_value_in_constant =
attempt to use a non-constant value in a constant
resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion =
consider using `{$suggestion}` instead of `{$current}`
resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion =
non-constant value
resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
this would need to be a `{$suggestion}`
resolve_self_imports_only_allowed_within =
`self` imports are only allowed within a {"{"} {"}"} list
resolve_self_imports_only_allowed_within_suggestion =
consider importing the module directly
resolve_self_imports_only_allowed_within_multipart_suggestion =
alternatively, use the multi-path `use` syntax to import `self`
resolve_binding_shadows_something_unacceptable =
{$shadowing_binding}s cannot shadow {$shadowed_binding}s
.label = cannot be named the same as {$article} {$shadowed_binding}
.label_shadowed_binding = the {$shadowed_binding} `{$name}` is {$participle} here
resolve_binding_shadows_something_unacceptable_suggestion =
try specify the pattern arguments
resolve_forward_declared_generic_param =
generic parameters with a default cannot use forward declared identifiers
.label = defaulted generic parameters cannot be forward declared
resolve_param_in_ty_of_const_param =
the type of const parameters must not depend on other generic parameters
.label = the type must not depend on the parameter `{$name}`
resolve_self_in_generic_param_default =
generic parameters cannot use `Self` in their defaults
.label = `Self` in generic parameter default
resolve_param_in_non_trivial_anon_const =
generic parameters may not be used in const operations
.label = cannot perform const operation using `{$name}`
resolve_param_in_non_trivial_anon_const_help =
use `#![feature(generic_const_exprs)]` to allow generic const expressions
resolve_param_in_non_trivial_anon_const_sub_type =
type parameters may not be used in const expressions
resolve_param_in_non_trivial_anon_const_sub_non_type =
const parameters may only be used as standalone arguments, i.e. `{$name}`
resolve_unreachable_label =
use of unreachable label `{$name}`
.label = unreachable label `{$name}`
.label_definition_span = unreachable label defined here
.note = labels are unreachable through functions, closures, async blocks and modules
resolve_unreachable_label_suggestion_use_similarly_named =
try using similarly named label
resolve_unreachable_label_similar_name_reachable =
a label with a similar name is reachable
resolve_unreachable_label_similar_name_unreachable =
a label with a similar name exists but is also unreachable
resolve_trait_impl_mismatch =
item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`
.label = does not match trait
.label_trait_item = item in trait
resolve_invalid_asm_sym =
invalid `sym` operand
.label = is a local variable
.help = `sym` operands must refer to either a function or a static
resolve_trait_impl_duplicate =
duplicate definitions with name `{$name}`:
.label = duplicate definition
.old_span_label = previous definition here
.trait_item_span = item in trait
resolve_relative_2018 =
relative paths are not supported in visibilities in 2018 edition or later
.suggestion = try
resolve_ancestor_only =
visibilities can only be restricted to ancestor modules
resolve_expected_found =
expected module, found {$res} `{$path_str}`
.label = not a module
resolve_indeterminate =
cannot determine resolution for the visibility
resolve_module_only =
visibility must resolve to a module

View File

@ -63,6 +63,7 @@ fluent_messages! {
plugin_impl => "../locales/en-US/plugin_impl.ftl", plugin_impl => "../locales/en-US/plugin_impl.ftl",
privacy => "../locales/en-US/privacy.ftl", privacy => "../locales/en-US/privacy.ftl",
query_system => "../locales/en-US/query_system.ftl", query_system => "../locales/en-US/query_system.ftl",
resolve => "../locales/en-US/resolve.ftl",
save_analysis => "../locales/en-US/save_analysis.ftl", save_analysis => "../locales/en-US/save_analysis.ftl",
session => "../locales/en-US/session.ftl", session => "../locales/en-US/session.ftl",
symbol_mangling => "../locales/en-US/symbol_mangling.ftl", symbol_mangling => "../locales/en-US/symbol_mangling.ftl",

View File

@ -211,6 +211,12 @@ impl IntoDiagnosticArg for DiagnosticSymbolList {
} }
} }
impl<Id> IntoDiagnosticArg for hir::def::Res<Id> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(self.descr()))
}
}
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
let mut diag; let mut diag;

View File

@ -19,6 +19,7 @@ rustc_expand = { path = "../rustc_expand" }
rustc_feature = { path = "../rustc_feature" } rustc_feature = { path = "../rustc_feature" }
rustc_hir = { path = "../rustc_hir" } rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" } rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" } rustc_metadata = { path = "../rustc_metadata" }
rustc_query_system = { path = "../rustc_query_system" } rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" } rustc_session = { path = "../rustc_session" }

View File

@ -26,6 +26,7 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, SyntaxContext}; use rustc_span::{BytePos, Span, SyntaxContext};
use crate::errors as errs;
use crate::imports::{Import, ImportKind, ImportResolver}; use crate::imports::{Import, ImportKind, ImportResolver};
use crate::late::{PatternSource, Rib}; use crate::late::{PatternSource, Rib};
use crate::path_names_to_string; use crate::path_names_to_string;
@ -597,78 +598,41 @@ impl<'a> Resolver<'a> {
err err
} }
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => { ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
let mut err = struct_span_err!( .session
self.session, .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
span,
E0403,
"the name `{}` is already used for a generic \
parameter in this item's generic parameters",
name,
);
err.span_label(span, "already used");
err.span_label(first_use_span, format!("first use of `{}`", name));
err
}
ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => { ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
let mut err = struct_span_err!( self.session.create_err(errs::MethodNotMemberOfTrait {
self.session,
span, span,
E0407,
"method `{}` is not a member of trait `{}`",
method, method,
trait_ trait_,
); sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists {
err.span_label(span, format!("not a member of trait `{}`", trait_)); span: method.span,
if let Some(candidate) = candidate { candidate: c,
err.span_suggestion( }),
method.span, })
"there is an associated function with a similar name",
candidate.to_ident_string(),
Applicability::MaybeIncorrect,
);
}
err
} }
ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => { ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
let mut err = struct_span_err!( self.session.create_err(errs::TypeNotMemberOfTrait {
self.session,
span, span,
E0437,
"type `{}` is not a member of trait `{}`",
type_, type_,
trait_ trait_,
); sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists {
err.span_label(span, format!("not a member of trait `{}`", trait_)); span: type_.span,
if let Some(candidate) = candidate { candidate: c,
err.span_suggestion( }),
type_.span, })
"there is an associated type with a similar name",
candidate.to_ident_string(),
Applicability::MaybeIncorrect,
);
}
err
} }
ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => { ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
let mut err = struct_span_err!( self.session.create_err(errs::ConstNotMemberOfTrait {
self.session,
span, span,
E0438,
"const `{}` is not a member of trait `{}`",
const_, const_,
trait_ trait_,
); sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists {
err.span_label(span, format!("not a member of trait `{}`", trait_)); span: const_.span,
if let Some(candidate) = candidate { candidate: c,
err.span_suggestion( }),
const_.span, })
"there is an associated constant with a similar name",
candidate.to_ident_string(),
Applicability::MaybeIncorrect,
);
}
err
} }
ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => { ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
let BindingError { name, target, origin, could_be_path } = binding_error; let BindingError { name, target, origin, could_be_path } = binding_error;
@ -730,128 +694,78 @@ impl<'a> Resolver<'a> {
err err
} }
ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => { ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
let mut err = struct_span_err!( self.session.create_err(errs::VariableBoundWithDifferentMode {
self.session,
span, span,
E0409, first_binding_span,
"variable `{}` is bound inconsistently across alternatives separated by `|`", variable_name,
variable_name })
);
err.span_label(span, "bound in different ways");
err.span_label(first_binding_span, "first binding");
err
}
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
let mut err = struct_span_err!(
self.session,
span,
E0415,
"identifier `{}` is bound more than once in this parameter list",
identifier
);
err.span_label(span, "used as parameter more than once");
err
}
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
let mut err = struct_span_err!(
self.session,
span,
E0416,
"identifier `{}` is bound more than once in the same pattern",
identifier
);
err.span_label(span, "used in a pattern more than once");
err
} }
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
.session
.create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
.session
.create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
ResolutionError::UndeclaredLabel { name, suggestion } => { ResolutionError::UndeclaredLabel { name, suggestion } => {
let mut err = struct_span_err!( let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
self.session, {
span,
E0426,
"use of undeclared label `{}`",
name
);
err.span_label(span, format!("undeclared label `{}`", name));
match suggestion {
// A reachable label with a similar name exists. // A reachable label with a similar name exists.
Some((ident, true)) => { Some((ident, true)) => (
err.span_label(ident.span, "a label with a similar name is reachable"); (
err.span_suggestion( Some(errs::LabelWithSimilarNameReachable(ident.span)),
span, Some(errs::TryUsingSimilarlyNamedLabel {
"try using similarly named label", span,
ident.name, ident_name: ident.name,
Applicability::MaybeIncorrect, }),
); ),
} None,
),
// An unreachable label with a similar name exists. // An unreachable label with a similar name exists.
Some((ident, false)) => { Some((ident, false)) => (
err.span_label( (None, None),
ident.span, Some(errs::UnreachableLabelWithSimilarNameExists {
"a label with a similar name exists but is unreachable", ident_span: ident.span,
); }),
} ),
// No similarly-named labels exist. // No similarly-named labels exist.
None => (), None => ((None, None), None),
} };
self.session.create_err(errs::UndeclaredLabel {
err span,
name,
sub_reachable,
sub_reachable_suggestion,
sub_unreachable,
})
} }
ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => { ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
let mut err = struct_span_err!(
self.session,
span,
E0429,
"{}",
"`self` imports are only allowed within a { } list"
);
// None of the suggestions below would help with a case like `use self`. // None of the suggestions below would help with a case like `use self`.
if !root { let (suggestion, mpart_suggestion) = if root {
(None, None)
} else {
// use foo::bar::self -> foo::bar // use foo::bar::self -> foo::bar
// use foo::bar::self as abc -> foo::bar as abc // use foo::bar::self as abc -> foo::bar as abc
err.span_suggestion( let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
span,
"consider importing the module directly",
"",
Applicability::MachineApplicable,
);
// use foo::bar::self -> foo::bar::{self} // use foo::bar::self -> foo::bar::{self}
// use foo::bar::self as abc -> foo::bar::{self as abc} // use foo::bar::self as abc -> foo::bar::{self as abc}
let braces = vec![ let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
(span_with_rename.shrink_to_lo(), "{".to_string()), multipart_start: span_with_rename.shrink_to_lo(),
(span_with_rename.shrink_to_hi(), "}".to_string()), multipart_end: span_with_rename.shrink_to_hi(),
]; };
err.multipart_suggestion( (Some(suggestion), Some(mpart_suggestion))
"alternatively, use the multi-path `use` syntax to import `self`", };
braces, self.session.create_err(errs::SelfImportsOnlyAllowedWithin {
Applicability::MachineApplicable, span,
); suggestion,
} mpart_suggestion,
err })
} }
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
let mut err = struct_span_err!( self.session.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
self.session,
span,
E0430,
"`self` import can only appear once in an import list"
);
err.span_label(span, "can only appear once in an import list");
err
} }
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
let mut err = struct_span_err!( self.session.create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
self.session,
span,
E0431,
"`self` import can only appear in an import list with \
a non-empty prefix"
);
err.span_label(span, "can only appear in an import list with a non-empty prefix");
err
} }
ResolutionError::FailedToResolve { label, suggestion } => { ResolutionError::FailedToResolve { label, suggestion } => {
let mut err = let mut err =
@ -869,23 +783,9 @@ impl<'a> Resolver<'a> {
err err
} }
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
let mut err = struct_span_err!( self.session.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
self.session,
span,
E0434,
"{}",
"can't capture dynamic environment in a fn item"
);
err.help("use the `|| { ... }` closure form instead");
err
} }
ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg, current) => { ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => {
let mut err = struct_span_err!(
self.session,
span,
E0435,
"attempt to use a non-constant value in a constant"
);
// let foo =... // let foo =...
// ^^^ given this Span // ^^^ given this Span
// ------- get this Span to have an applicable suggestion // ------- get this Span to have an applicable suggestion
@ -899,23 +799,34 @@ impl<'a> Resolver<'a> {
.source_map() .source_map()
.span_extend_to_prev_str(ident.span, current, true, false); .span_extend_to_prev_str(ident.span, current, true, false);
match sp { let ((with, with_label), without) = match sp {
Some(sp) if !self.session.source_map().is_multiline(sp) => { Some(sp) if !self.session.source_map().is_multiline(sp) => {
let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32))); let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32)));
err.span_suggestion( (
sp, (Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
&format!("consider using `{}` instead of `{}`", sugg, current), span: sp,
format!("{} {}", sugg, ident), ident,
Applicability::MaybeIncorrect, suggestion,
); current,
err.span_label(span, "non-constant value"); }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})),
None,
)
} }
_ => { _ => (
err.span_label(ident.span, &format!("this would need to be a `{}`", sugg)); (None, None),
} Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
} ident_span: ident.span,
suggestion,
}),
),
};
err self.session.create_err(errs::AttemptToUseNonConstantValueInConstant {
span,
with,
with_label,
without,
})
} }
ResolutionError::BindingShadowsSomethingUnacceptable { ResolutionError::BindingShadowsSomethingUnacceptable {
shadowing_binding, shadowing_binding,
@ -924,135 +835,80 @@ impl<'a> Resolver<'a> {
article, article,
shadowed_binding, shadowed_binding,
shadowed_binding_span, shadowed_binding_span,
} => { } => self.session.create_err(errs::BindingShadowsSomethingUnacceptable {
let shadowed_binding_descr = shadowed_binding.descr(); span,
let mut err = struct_span_err!( shadowing_binding,
self.session, shadowed_binding,
span, article,
E0530, sub_suggestion: match (shadowing_binding, shadowed_binding) {
"{}s cannot shadow {}s",
shadowing_binding.descr(),
shadowed_binding_descr,
);
err.span_label(
span,
format!("cannot be named the same as {} {}", article, shadowed_binding_descr),
);
match (shadowing_binding, shadowed_binding) {
( (
PatternSource::Match, PatternSource::Match,
Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _), Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
) => { ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }),
err.span_suggestion( _ => None,
span, },
"try specify the pattern arguments", shadowed_binding_span,
format!("{}(..)", name), participle,
Applicability::Unspecified, name,
); }),
}
_ => (),
}
let msg =
format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle);
err.span_label(shadowed_binding_span, msg);
err
}
ResolutionError::ForwardDeclaredGenericParam => { ResolutionError::ForwardDeclaredGenericParam => {
let mut err = struct_span_err!( self.session.create_err(errs::ForwardDeclaredGenericParam { span })
self.session,
span,
E0128,
"generic parameters with a default cannot use \
forward declared identifiers"
);
err.span_label(span, "defaulted generic parameters cannot be forward declared");
err
} }
ResolutionError::ParamInTyOfConstParam(name) => { ResolutionError::ParamInTyOfConstParam(name) => {
let mut err = struct_span_err!( self.session.create_err(errs::ParamInTyOfConstParam { span, name })
self.session,
span,
E0770,
"the type of const parameters must not depend on other generic parameters"
);
err.span_label(
span,
format!("the type must not depend on the parameter `{}`", name),
);
err
} }
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
let mut err = self.session.struct_span_err( self.session.create_err(errs::ParamInNonTrivialAnonConst {
span, span,
"generic parameters may not be used in const operations", name,
); sub_is_type: if is_type {
err.span_label(span, &format!("cannot perform const operation using `{}`", name)); errs::ParamInNonTrivialAnonConstIsType::AType
} else {
if is_type { errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
err.note("type parameters may not be used in const expressions"); },
} else { help: self
err.help(&format!( .session
"const parameters may only be used as standalone arguments, i.e. `{}`", .is_nightly_build()
name .then_some(errs::ParamInNonTrivialAnonConstHelp),
)); })
}
if self.session.is_nightly_build() {
err.help(
"use `#![feature(generic_const_exprs)]` to allow generic const expressions",
);
}
err
} }
ResolutionError::SelfInGenericParamDefault => { ResolutionError::SelfInGenericParamDefault => {
let mut err = struct_span_err!( self.session.create_err(errs::SelfInGenericParamDefault { span })
self.session,
span,
E0735,
"generic parameters cannot use `Self` in their defaults"
);
err.span_label(span, "`Self` in generic parameter default");
err
} }
ResolutionError::UnreachableLabel { name, definition_span, suggestion } => { ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
let mut err = struct_span_err!( let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
self.session, match suggestion {
// A reachable label with a similar name exists.
Some((ident, true)) => (
(
Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }),
Some(errs::UnreachableLabelSubSuggestion {
span,
// intentionally taking 'ident.name' instead of 'ident' itself, as this
// could be used in suggestion context
ident_name: ident.name,
}),
),
None,
),
// An unreachable label with a similar name exists.
Some((ident, false)) => (
(None, None),
Some(errs::UnreachableLabelSubLabelUnreachable {
ident_span: ident.span,
}),
),
// No similarly-named labels exist.
None => ((None, None), None),
};
self.session.create_err(errs::UnreachableLabel {
span, span,
E0767,
"use of unreachable label `{}`",
name, name,
); definition_span,
sub_suggestion,
err.span_label(definition_span, "unreachable label defined here"); sub_suggestion_label,
err.span_label(span, format!("unreachable label `{}`", name)); sub_unreachable_label,
err.note( })
"labels are unreachable through functions, closures, async blocks and modules",
);
match suggestion {
// A reachable label with a similar name exists.
Some((ident, true)) => {
err.span_label(ident.span, "a label with a similar name is reachable");
err.span_suggestion(
span,
"try using similarly named label",
ident.name,
Applicability::MaybeIncorrect,
);
}
// An unreachable label with a similar name exists.
Some((ident, false)) => {
err.span_label(
ident.span,
"a label with a similar name exists but is also unreachable",
);
}
// No similarly-named labels exist.
None => (),
}
err
} }
ResolutionError::TraitImplMismatch { ResolutionError::TraitImplMismatch {
name, name,
@ -1073,25 +929,10 @@ impl<'a> Resolver<'a> {
err.span_label(trait_item_span, "item in trait"); err.span_label(trait_item_span, "item in trait");
err err
} }
ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => { ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
let mut err = struct_span_err!( .session
self.session, .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
span, ResolutionError::InvalidAsmSym => self.session.create_err(errs::InvalidAsmSym { span }),
E0201,
"duplicate definitions with name `{}`:",
name,
);
err.span_label(old_span, "previous definition here");
err.span_label(trait_item_span, "item in trait");
err.span_label(span, "duplicate definition");
err
}
ResolutionError::InvalidAsmSym => {
let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
err.span_label(span, "is a local variable");
err.help("`sym` operands must refer to either a function or a static");
err
}
} }
} }
@ -1101,48 +942,27 @@ impl<'a> Resolver<'a> {
) -> ErrorGuaranteed { ) -> ErrorGuaranteed {
match vis_resolution_error { match vis_resolution_error {
VisResolutionError::Relative2018(span, path) => { VisResolutionError::Relative2018(span, path) => {
let mut err = self.session.struct_span_err( self.session.create_err(errs::Relative2018 {
span, span,
"relative paths are not supported in visibilities in 2018 edition or later", path_span: path.span,
); // intentionally converting to String, as the text would also be used as
err.span_suggestion( // in suggestion context
path.span, path_str: pprust::path_to_string(&path),
"try", })
format!("crate::{}", pprust::path_to_string(&path)), }
Applicability::MaybeIncorrect, VisResolutionError::AncestorOnly(span) => {
); self.session.create_err(errs::AncestorOnly(span))
err
} }
VisResolutionError::AncestorOnly(span) => struct_span_err!(
self.session,
span,
E0742,
"visibilities can only be restricted to ancestor modules"
),
VisResolutionError::FailedToResolve(span, label, suggestion) => { VisResolutionError::FailedToResolve(span, label, suggestion) => {
self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion }) self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion })
} }
VisResolutionError::ExpectedFound(span, path_str, res) => { VisResolutionError::ExpectedFound(span, path_str, res) => {
let mut err = struct_span_err!( self.session.create_err(errs::ExpectedFound { span, res, path_str })
self.session,
span,
E0577,
"expected module, found {} `{}`",
res.descr(),
path_str
);
err.span_label(span, "not a module");
err
} }
VisResolutionError::Indeterminate(span) => struct_span_err!( VisResolutionError::Indeterminate(span) => {
self.session, self.session.create_err(errs::Indeterminate(span))
span,
E0578,
"cannot determine resolution for the visibility"
),
VisResolutionError::ModuleOnly(span) => {
self.session.struct_span_err(span, "visibility must resolve to a module")
} }
VisResolutionError::ModuleOnly(span) => self.session.create_err(errs::ModuleOnly(span)),
} }
.emit() .emit()
} }

View File

@ -0,0 +1,474 @@
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{
symbol::{Ident, Symbol},
Span,
};
use crate::{late::PatternSource, Res};
#[derive(Diagnostic)]
#[diag(resolve_parent_module_reset_for_binding, code = "E0637")]
pub(crate) struct ParentModuleResetForBinding;
#[derive(Diagnostic)]
#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = "E0637")]
#[note]
pub(crate) struct AmpersandUsedWithoutExplicitLifetimeName(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = "E0637")]
#[note]
pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_crate_may_not_be_imported)]
pub(crate) struct CrateMayNotBeImprted(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
pub(crate) struct NameAlreadyUsedInParameterList {
#[primary_span]
#[label]
pub(crate) span: Span,
#[label(first_use_of_name)]
pub(crate) first_use_span: Span,
pub(crate) name: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_method_not_member_of_trait, code = "E0407")]
pub(crate) struct MethodNotMemberOfTrait {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) method: Ident,
pub(crate) trait_: String,
#[subdiagnostic]
pub(crate) sub: Option<AssociatedFnWithSimilarNameExists>,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_associated_fn_with_similar_name_exists,
code = "{candidate}",
applicability = "maybe-incorrect"
)]
pub(crate) struct AssociatedFnWithSimilarNameExists {
#[primary_span]
pub(crate) span: Span,
pub(crate) candidate: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_type_not_member_of_trait, code = "E0437")]
pub(crate) struct TypeNotMemberOfTrait {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) type_: Ident,
pub(crate) trait_: String,
#[subdiagnostic]
pub(crate) sub: Option<AssociatedTypeWithSimilarNameExists>,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_associated_type_with_similar_name_exists,
code = "{candidate}",
applicability = "maybe-incorrect"
)]
pub(crate) struct AssociatedTypeWithSimilarNameExists {
#[primary_span]
pub(crate) span: Span,
pub(crate) candidate: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_const_not_member_of_trait, code = "E0438")]
pub(crate) struct ConstNotMemberOfTrait {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) const_: Ident,
pub(crate) trait_: String,
#[subdiagnostic]
pub(crate) sub: Option<AssociatedConstWithSimilarNameExists>,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_associated_const_with_similar_name_exists,
code = "{candidate}",
applicability = "maybe-incorrect"
)]
pub(crate) struct AssociatedConstWithSimilarNameExists {
#[primary_span]
pub(crate) span: Span,
pub(crate) candidate: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_variable_bound_with_different_mode, code = "E0409")]
pub(crate) struct VariableBoundWithDifferentMode {
#[primary_span]
#[label]
pub(crate) span: Span,
#[label(first_binding_span)]
pub(crate) first_binding_span: Span,
pub(crate) variable_name: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = "E0415")]
pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) identifier: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = "E0416")]
pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) identifier: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_undeclared_label, code = "E0426")]
pub(crate) struct UndeclaredLabel {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) sub_reachable: Option<LabelWithSimilarNameReachable>,
#[subdiagnostic]
pub(crate) sub_reachable_suggestion: Option<TryUsingSimilarlyNamedLabel>,
#[subdiagnostic]
pub(crate) sub_unreachable: Option<UnreachableLabelWithSimilarNameExists>,
}
#[derive(Subdiagnostic)]
#[label(resolve_label_with_similar_name_reachable)]
pub(crate) struct LabelWithSimilarNameReachable(#[primary_span] pub(crate) Span);
#[derive(Subdiagnostic)]
#[suggestion(
resolve_try_using_similarly_named_label,
code = "{ident_name}",
applicability = "maybe-incorrect"
)]
pub(crate) struct TryUsingSimilarlyNamedLabel {
#[primary_span]
pub(crate) span: Span,
pub(crate) ident_name: Symbol,
}
#[derive(Subdiagnostic)]
#[label(resolve_unreachable_label_with_similar_name_exists)]
pub(crate) struct UnreachableLabelWithSimilarNameExists {
#[primary_span]
pub(crate) ident_span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = "E0430")]
pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
#[primary_span]
#[label]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = "E0431")]
pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
#[primary_span]
#[label]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = "E0434")]
#[help]
pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = "E0435")]
pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> {
#[primary_span]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) with: Option<AttemptToUseNonConstantValueInConstantWithSuggestion<'a>>,
#[subdiagnostic]
pub(crate) with_label: Option<AttemptToUseNonConstantValueInConstantLabelWithSuggestion>,
#[subdiagnostic]
pub(crate) without: Option<AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a>>,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion,
code = "{suggestion} {ident}",
applicability = "maybe-incorrect"
)]
pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> {
#[primary_span]
pub(crate) span: Span,
pub(crate) ident: Ident,
pub(crate) suggestion: &'a str,
pub(crate) current: &'a str,
}
#[derive(Subdiagnostic)]
#[label(resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion)]
pub(crate) struct AttemptToUseNonConstantValueInConstantLabelWithSuggestion {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[label(resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion)]
pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
#[primary_span]
pub(crate) ident_span: Span,
pub(crate) suggestion: &'a str,
}
#[derive(Diagnostic)]
#[diag(resolve_self_imports_only_allowed_within, code = "E0429")]
pub(crate) struct SelfImportsOnlyAllowedWithin {
#[primary_span]
pub(crate) span: Span,
#[subdiagnostic]
pub(crate) suggestion: Option<SelfImportsOnlyAllowedWithinSuggestion>,
#[subdiagnostic]
pub(crate) mpart_suggestion: Option<SelfImportsOnlyAllowedWithinMultipartSuggestion>,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_self_imports_only_allowed_within_suggestion,
code = "",
applicability = "machine-applicable"
)]
pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
resolve_self_imports_only_allowed_within_multipart_suggestion,
applicability = "machine-applicable"
)]
pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
#[suggestion_part(code = "{{")]
pub(crate) multipart_start: Span,
#[suggestion_part(code = "}}")]
pub(crate) multipart_end: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_binding_shadows_something_unacceptable, code = "E0530")]
pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) shadowing_binding: PatternSource,
pub(crate) shadowed_binding: Res,
pub(crate) article: &'a str,
#[subdiagnostic]
pub(crate) sub_suggestion: Option<BindingShadowsSomethingUnacceptableSuggestion>,
#[label(label_shadowed_binding)]
pub(crate) shadowed_binding_span: Span,
pub(crate) participle: &'a str,
pub(crate) name: Symbol,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_binding_shadows_something_unacceptable_suggestion,
code = "{name}(..)",
applicability = "unspecified"
)]
pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion {
#[primary_span]
pub(crate) span: Span,
pub(crate) name: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_forward_declared_generic_param, code = "E0128")]
pub(crate) struct ForwardDeclaredGenericParam {
#[primary_span]
#[label]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_param_in_ty_of_const_param, code = "E0770")]
pub(crate) struct ParamInTyOfConstParam {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_self_in_generic_param_default, code = "E0735")]
pub(crate) struct SelfInGenericParamDefault {
#[primary_span]
#[label]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_param_in_non_trivial_anon_const)]
pub(crate) struct ParamInNonTrivialAnonConst {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[subdiagnostic]
pub(crate) sub_is_type: ParamInNonTrivialAnonConstIsType,
#[subdiagnostic]
pub(crate) help: Option<ParamInNonTrivialAnonConstHelp>,
}
#[derive(Subdiagnostic)]
#[help(resolve_param_in_non_trivial_anon_const_help)]
pub(crate) struct ParamInNonTrivialAnonConstHelp;
#[derive(Subdiagnostic)]
pub(crate) enum ParamInNonTrivialAnonConstIsType {
#[note(resolve_param_in_non_trivial_anon_const_sub_type)]
AType,
#[help(resolve_param_in_non_trivial_anon_const_sub_non_type)]
NotAType { name: Symbol },
}
#[derive(Diagnostic)]
#[diag(resolve_unreachable_label, code = "E0767")]
#[note]
pub(crate) struct UnreachableLabel {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
#[label(label_definition_span)]
pub(crate) definition_span: Span,
#[subdiagnostic]
pub(crate) sub_suggestion: Option<UnreachableLabelSubSuggestion>,
#[subdiagnostic]
pub(crate) sub_suggestion_label: Option<UnreachableLabelSubLabel>,
#[subdiagnostic]
pub(crate) sub_unreachable_label: Option<UnreachableLabelSubLabelUnreachable>,
}
#[derive(Subdiagnostic)]
#[suggestion(
resolve_unreachable_label_suggestion_use_similarly_named,
code = "{ident_name}",
applicability = "maybe-incorrect"
)]
pub(crate) struct UnreachableLabelSubSuggestion {
#[primary_span]
pub(crate) span: Span,
pub(crate) ident_name: Symbol,
}
#[derive(Subdiagnostic)]
#[label(resolve_unreachable_label_similar_name_reachable)]
pub(crate) struct UnreachableLabelSubLabel {
#[primary_span]
pub(crate) ident_span: Span,
}
#[derive(Subdiagnostic)]
#[label(resolve_unreachable_label_similar_name_unreachable)]
pub(crate) struct UnreachableLabelSubLabelUnreachable {
#[primary_span]
pub(crate) ident_span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_trait_impl_mismatch, code = "{code}")]
pub(crate) struct TraitImplMismatch {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
pub(crate) kind: String,
#[label(label_trait_item)]
pub(crate) trait_item_span: Span,
pub(crate) trait_path: String,
pub(crate) code: String,
}
#[derive(Diagnostic)]
#[diag(resolve_invalid_asm_sym)]
#[help]
pub(crate) struct InvalidAsmSym {
#[primary_span]
#[label]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_trait_impl_duplicate, code = "E0201")]
pub(crate) struct TraitImplDuplicate {
#[primary_span]
#[label]
pub(crate) span: Span,
#[label(old_span_label)]
pub(crate) old_span: Span,
#[label(trait_item_span)]
pub(crate) trait_item_span: Span,
pub(crate) name: Symbol,
}
#[derive(Diagnostic)]
#[diag(resolve_relative_2018)]
pub(crate) struct Relative2018 {
#[primary_span]
pub(crate) span: Span,
#[suggestion(code = "crate::{path_str}", applicability = "maybe-incorrect")]
pub(crate) path_span: Span,
pub(crate) path_str: String,
}
#[derive(Diagnostic)]
#[diag(resolve_ancestor_only, code = "E0742")]
pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_expected_found, code = "E0577")]
pub(crate) struct ExpectedFound {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) res: Res,
pub(crate) path_str: String,
}
#[derive(Diagnostic)]
#[diag(resolve_indeterminate, code = "E0578")]
pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span);
#[derive(Diagnostic)]
#[diag(resolve_module_only)]
pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);

View File

@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
use rustc_ast::*; use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::DiagnosticId; use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@ -31,6 +31,7 @@ use smallvec::{smallvec, SmallVec};
use rustc_span::source_map::{respan, Spanned}; use rustc_span::source_map::{respan, Spanned};
use std::assert_matches::debug_assert_matches; use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::collections::{hash_map::Entry, BTreeSet}; use std::collections::{hash_map::Entry, BTreeSet};
use std::mem::{replace, swap, take}; use std::mem::{replace, swap, take};
@ -78,6 +79,12 @@ impl PatternSource {
} }
} }
impl IntoDiagnosticArg for PatternSource {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(self.descr()))
}
}
/// Denotes whether the context for the set of already bound bindings is a `Product` /// Denotes whether the context for the set of already bound bindings is a `Product`
/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`. /// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
/// See those functions for more information. /// See those functions for more information.

View File

@ -73,6 +73,7 @@ mod check_unused;
mod def_collector; mod def_collector;
mod diagnostics; mod diagnostics;
mod effective_visibilities; mod effective_visibilities;
mod errors;
mod ident; mod ident;
mod imports; mod imports;
mod late; mod late;