Merge ref 'db3e99bbab' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh.
Upstream ref: rust-lang/rust@db3e99bbab
Filtered ref: rust-lang/compiler-builtins@970db0bc6d
Upstream diff: 44e34e1ac6...db3e99bbab
This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
f043a16ffb
678 changed files with 20412 additions and 8995 deletions
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
|
|
@ -165,9 +165,6 @@ jobs:
|
|||
- name: install sccache
|
||||
run: src/ci/scripts/install-sccache.sh
|
||||
|
||||
- name: select Xcode
|
||||
run: src/ci/scripts/select-xcode.sh
|
||||
|
||||
- name: install clang
|
||||
run: src/ci/scripts/install-clang.sh
|
||||
|
||||
|
|
|
|||
27
Cargo.lock
27
Cargo.lock
|
|
@ -3543,7 +3543,6 @@ dependencies = [
|
|||
"rustc_ast_pretty",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_lexer",
|
||||
"rustc_macros",
|
||||
|
|
@ -3636,7 +3635,6 @@ dependencies = [
|
|||
"rustc_codegen_ssa",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_fs_util",
|
||||
"rustc_hashes",
|
||||
"rustc_hir",
|
||||
|
|
@ -3684,7 +3682,6 @@ dependencies = [
|
|||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
"rustc_middle",
|
||||
"rustc_query_system",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
|
|
@ -3780,7 +3777,6 @@ dependencies = [
|
|||
"rustc_ast_lowering",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_borrowck",
|
||||
"rustc_builtin_macros",
|
||||
"rustc_codegen_ssa",
|
||||
|
|
@ -3789,13 +3785,10 @@ dependencies = [
|
|||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir_analysis",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_hir_typeck",
|
||||
"rustc_incremental",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_interface",
|
||||
"rustc_lexer",
|
||||
"rustc_lint",
|
||||
|
|
@ -3804,21 +3797,16 @@ dependencies = [
|
|||
"rustc_metadata",
|
||||
"rustc_middle",
|
||||
"rustc_mir_build",
|
||||
"rustc_mir_dataflow",
|
||||
"rustc_mir_transform",
|
||||
"rustc_monomorphize",
|
||||
"rustc_parse",
|
||||
"rustc_passes",
|
||||
"rustc_pattern_analysis",
|
||||
"rustc_privacy",
|
||||
"rustc_public",
|
||||
"rustc_query_system",
|
||||
"rustc_resolve",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_trait_selection",
|
||||
"rustc_ty_utils",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"tracing",
|
||||
|
|
@ -4054,7 +4042,6 @@ dependencies = [
|
|||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_fs_util",
|
||||
"rustc_graphviz",
|
||||
"rustc_hashes",
|
||||
|
|
@ -4093,7 +4080,6 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
|
|
@ -4124,7 +4110,6 @@ dependencies = [
|
|||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_fs_util",
|
||||
"rustc_hir",
|
||||
"rustc_hir_analysis",
|
||||
|
|
@ -4229,6 +4214,8 @@ dependencies = [
|
|||
name = "rustc_macros"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"fluent-bundle",
|
||||
"fluent-syntax",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
|
|
@ -4336,11 +4323,10 @@ dependencies = [
|
|||
"polonius-engine",
|
||||
"regex",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_graphviz",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
|
|
@ -4354,7 +4340,6 @@ name = "rustc_mir_transform"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"hashbrown 0.16.1",
|
||||
"itertools",
|
||||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
|
|
@ -4384,7 +4369,6 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
|
|
@ -4497,7 +4481,6 @@ dependencies = [
|
|||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
|
|
@ -4565,14 +4548,12 @@ dependencies = [
|
|||
name = "rustc_query_system"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
"parking_lot",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hashes",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
|
|
@ -4654,7 +4635,6 @@ dependencies = [
|
|||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_fs_util",
|
||||
"rustc_hashes",
|
||||
"rustc_hir",
|
||||
|
|
@ -4810,7 +4790,6 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hashes",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
|
|
|
|||
|
|
@ -510,19 +510,6 @@ impl DroplessArena {
|
|||
}
|
||||
}
|
||||
|
||||
/// Used by `Lift` to check whether this slice is allocated
|
||||
/// in this arena.
|
||||
#[inline]
|
||||
pub fn contains_slice<T>(&self, slice: &[T]) -> bool {
|
||||
for chunk in self.chunks.borrow_mut().iter_mut() {
|
||||
let ptr = slice.as_ptr().cast::<u8>().cast_mut();
|
||||
if chunk.start() <= ptr && chunk.end() >= ptr {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Allocates a string slice that is copied into the `DroplessArena`, returning a
|
||||
/// reference to it. Will panic if passed an empty string.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -354,7 +354,13 @@ fn make_attr_token_stream(
|
|||
FrameData { open_delim_sp: Some((delim, span, spacing)), inner: vec![] },
|
||||
));
|
||||
} else if let Some(delim) = kind.close_delim() {
|
||||
let frame_data = mem::replace(&mut stack_top, stack_rest.pop().unwrap());
|
||||
// If there's no matching opening delimiter, the token stream is malformed,
|
||||
// likely due to a improper delimiter positions in the source code.
|
||||
// It's not delimiter mismatch, and lexer can not detect it, so we just ignore it here.
|
||||
let Some(frame) = stack_rest.pop() else {
|
||||
return AttrTokenStream::new(stack_top.inner);
|
||||
};
|
||||
let frame_data = mem::replace(&mut stack_top, frame);
|
||||
let (open_delim, open_sp, open_spacing) = frame_data.open_delim_sp.unwrap();
|
||||
assert!(
|
||||
open_delim.eq_ignoring_invisible_origin(&delim),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ rustc_ast = { path = "../rustc_ast" }
|
|||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
|
|
|
|||
|
|
@ -1,246 +0,0 @@
|
|||
attr_parsing_as_needed_compatibility =
|
||||
linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds
|
||||
|
||||
attr_parsing_bundle_needs_static =
|
||||
linking modifier `bundle` is only compatible with `static` linking kind
|
||||
|
||||
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
|
||||
|
||||
attr_parsing_deprecated_item_suggestion =
|
||||
suggestions on deprecated items are unstable
|
||||
.help = add `#![feature(deprecated_suggestion)]` to the crate root
|
||||
.note = see #94785 for more details
|
||||
|
||||
attr_parsing_doc_alias_bad_char =
|
||||
{$char_} character isn't allowed in {$attr_str}
|
||||
|
||||
attr_parsing_doc_alias_empty =
|
||||
{$attr_str} attribute cannot have empty value
|
||||
|
||||
attr_parsing_doc_alias_malformed =
|
||||
doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
|
||||
|
||||
attr_parsing_doc_alias_start_end =
|
||||
{$attr_str} cannot start or end with ' '
|
||||
|
||||
attr_parsing_doc_attr_not_crate_level =
|
||||
`#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
|
||||
|
||||
attr_parsing_doc_attribute_not_attribute =
|
||||
nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]`
|
||||
.help = only existing builtin attributes are allowed in core/std
|
||||
|
||||
attr_parsing_doc_keyword_not_keyword =
|
||||
nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]`
|
||||
.help = only existing keywords are allowed in core/std
|
||||
|
||||
attr_parsing_empty_confusables =
|
||||
expected at least one confusable name
|
||||
|
||||
attr_parsing_empty_link_name =
|
||||
link name must not be empty
|
||||
.label = empty link name
|
||||
|
||||
attr_parsing_expected_single_version_literal =
|
||||
expected single version literal
|
||||
|
||||
attr_parsing_expected_version_literal =
|
||||
expected a version literal
|
||||
|
||||
attr_parsing_expects_feature_list =
|
||||
`{$name}` expects a list of feature names
|
||||
|
||||
attr_parsing_expects_features =
|
||||
`{$name}` expects feature names
|
||||
|
||||
attr_parsing_import_name_type_raw =
|
||||
import name type can only be used with link kind `raw-dylib`
|
||||
|
||||
attr_parsing_import_name_type_x86 =
|
||||
import name type is only supported on x86
|
||||
|
||||
attr_parsing_incompatible_wasm_link =
|
||||
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
|
||||
|
||||
attr_parsing_incorrect_repr_format_align_one_arg =
|
||||
incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
|
||||
|
||||
attr_parsing_incorrect_repr_format_expect_literal_integer =
|
||||
incorrect `repr(align)` attribute format: `align` expects a literal integer as argument
|
||||
|
||||
attr_parsing_incorrect_repr_format_generic =
|
||||
incorrect `repr({$repr_arg})` attribute format
|
||||
.suggestion = use parentheses instead
|
||||
|
||||
attr_parsing_incorrect_repr_format_packed_expect_integer =
|
||||
incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument
|
||||
|
||||
attr_parsing_incorrect_repr_format_packed_one_or_zero_arg =
|
||||
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
|
||||
|
||||
attr_parsing_invalid_alignment_value =
|
||||
invalid alignment value: {$error_part}
|
||||
|
||||
attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
|
||||
.label = this is not an unsafe attribute
|
||||
.suggestion = remove the `unsafe(...)`
|
||||
.note = extraneous unsafe is not allowed in attributes
|
||||
|
||||
attr_parsing_invalid_issue_string =
|
||||
`issue` must be a non-zero numeric string or "none"
|
||||
.must_not_be_zero = `issue` must not be "0", use "none" instead
|
||||
.empty = cannot parse integer from empty string
|
||||
.invalid_digit = invalid digit found in string
|
||||
.pos_overflow = number too large to fit in target type
|
||||
.neg_overflow = number too small to fit in target type
|
||||
|
||||
attr_parsing_invalid_link_modifier =
|
||||
invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
|
||||
|
||||
attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr}
|
||||
.remove_neg_sugg = negative numbers are not literals, try removing the `-` sign
|
||||
.quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
|
||||
.label = {$descr}s are not allowed here
|
||||
|
||||
attr_parsing_invalid_predicate =
|
||||
invalid predicate `{$predicate}`
|
||||
|
||||
attr_parsing_invalid_repr_align_need_arg =
|
||||
invalid `repr(align)` attribute: `align` needs an argument
|
||||
.suggestion = supply an argument here
|
||||
|
||||
attr_parsing_invalid_repr_generic =
|
||||
invalid `repr({$repr_arg})` attribute: {$error_part}
|
||||
|
||||
attr_parsing_invalid_repr_hint_no_paren =
|
||||
invalid representation hint: `{$name}` does not take a parenthesized argument list
|
||||
|
||||
attr_parsing_invalid_repr_hint_no_value =
|
||||
invalid representation hint: `{$name}` does not take a value
|
||||
|
||||
attr_parsing_invalid_since =
|
||||
'since' must be a Rust version number, such as "1.31.0"
|
||||
|
||||
attr_parsing_invalid_target = `#[{$name}]` attribute cannot be used on {$target}
|
||||
.help = `#[{$name}]` can {$only}be applied to {$applied}
|
||||
.suggestion = remove the attribute
|
||||
|
||||
attr_parsing_limit_invalid =
|
||||
`limit` must be a non-negative integer
|
||||
.label = {$error_str}
|
||||
attr_parsing_link_arg_unstable =
|
||||
link kind `link-arg` is unstable
|
||||
|
||||
attr_parsing_link_cfg_unstable =
|
||||
link cfg is unstable
|
||||
|
||||
attr_parsing_link_framework_apple =
|
||||
link kind `framework` is only supported on Apple targets
|
||||
|
||||
attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
|
||||
.note = the value may not exceed `u16::MAX`
|
||||
|
||||
attr_parsing_link_requires_name =
|
||||
`#[link]` attribute requires a `name = "string"` argument
|
||||
.label = missing `name` argument
|
||||
|
||||
attr_parsing_meta_bad_delim = wrong meta list delimiters
|
||||
attr_parsing_meta_bad_delim_suggestion = the delimiters should be `(` and `)`
|
||||
|
||||
attr_parsing_missing_feature =
|
||||
missing 'feature'
|
||||
|
||||
attr_parsing_missing_issue =
|
||||
missing 'issue'
|
||||
|
||||
attr_parsing_missing_note =
|
||||
missing 'note'
|
||||
|
||||
attr_parsing_missing_since =
|
||||
missing 'since'
|
||||
|
||||
attr_parsing_multiple_modifiers =
|
||||
multiple `{$modifier}` modifiers in a single `modifiers` argument
|
||||
|
||||
attr_parsing_multiple_stability_levels =
|
||||
multiple stability levels
|
||||
|
||||
attr_parsing_naked_functions_incompatible_attribute =
|
||||
attribute incompatible with `#[unsafe(naked)]`
|
||||
.label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]`
|
||||
.naked_attribute = function marked with `#[unsafe(naked)]` here
|
||||
|
||||
attr_parsing_non_ident_feature =
|
||||
'feature' is not an identifier
|
||||
|
||||
attr_parsing_null_on_export = `export_name` may not contain null characters
|
||||
|
||||
attr_parsing_null_on_link_section = `link_section` may not contain null characters
|
||||
|
||||
attr_parsing_null_on_objc_class = `objc::class!` may not contain null characters
|
||||
|
||||
attr_parsing_null_on_objc_selector = `objc::selector!` may not contain null characters
|
||||
|
||||
attr_parsing_objc_class_expected_string_literal = `objc::class!` expected a string literal
|
||||
|
||||
attr_parsing_objc_selector_expected_string_literal = `objc::selector!` expected a string literal
|
||||
|
||||
attr_parsing_raw_dylib_elf_unstable =
|
||||
link kind `raw-dylib` is unstable on ELF platforms
|
||||
|
||||
attr_parsing_raw_dylib_no_nul =
|
||||
link name must not contain NUL characters if link kind is `raw-dylib`
|
||||
|
||||
attr_parsing_raw_dylib_only_windows =
|
||||
link kind `raw-dylib` is only supported on Windows targets
|
||||
|
||||
attr_parsing_repr_ident =
|
||||
meta item in `repr` must be an identifier
|
||||
|
||||
attr_parsing_rustc_allowed_unstable_pairing =
|
||||
`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
|
||||
|
||||
attr_parsing_rustc_promotable_pairing =
|
||||
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
|
||||
|
||||
attr_parsing_rustc_scalable_vector_count_out_of_range = element count in `rustc_scalable_vector` is too large: `{$n}`
|
||||
.note = the value may not exceed `u16::MAX`
|
||||
|
||||
attr_parsing_soft_no_args =
|
||||
`soft` should not have any arguments
|
||||
|
||||
attr_parsing_stability_outside_std = stability attributes may not be used outside of the standard library
|
||||
|
||||
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
|
||||
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
|
||||
|
||||
attr_parsing_unknown_version_literal =
|
||||
unknown version literal format, assuming it refers to a future version
|
||||
|
||||
attr_parsing_unrecognized_repr_hint =
|
||||
unrecognized representation hint
|
||||
.help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
|
||||
.note = for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
|
||||
|
||||
attr_parsing_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
|
||||
.label = usage of unsafe attribute
|
||||
attr_parsing_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
|
||||
|
||||
attr_parsing_unstable_cfg_target_compact =
|
||||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
||||
attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable
|
||||
.help = if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
|
||||
|
||||
attr_parsing_unsupported_instruction_set = target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`
|
||||
|
||||
attr_parsing_unsupported_literal_suggestion =
|
||||
consider removing the prefix
|
||||
|
||||
attr_parsing_unused_multiple =
|
||||
multiple `{$name}` attributes
|
||||
.suggestion = remove this attribute
|
||||
.note = attribute also specified here
|
||||
|
||||
attr_parsing_whole_archive_needs_static =
|
||||
linking modifier `whole-archive` is only compatible with `static` linking kind
|
||||
|
|
@ -3,14 +3,14 @@ use std::convert::identity;
|
|||
use rustc_ast::token::Delimiter;
|
||||
use rustc_ast::tokenstream::DelimSpan;
|
||||
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_errors::{Applicability, PResult, inline_fluent};
|
||||
use rustc_feature::{
|
||||
AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template,
|
||||
};
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrPath, RustcVersion, Target};
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::parser::{ForceCollect, Parser, Recovery};
|
||||
use rustc_parse::{exp, parse_in};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
|
|
@ -25,7 +25,7 @@ use crate::session_diagnostics::{
|
|||
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
|
||||
ParsedDescription,
|
||||
};
|
||||
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics};
|
||||
use crate::{AttributeParser, parse_version, session_diagnostics};
|
||||
|
||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
||||
List: &["predicate"],
|
||||
|
|
@ -141,7 +141,7 @@ fn parse_cfg_entry_target<S: Stage>(
|
|||
cx.sess(),
|
||||
sym::cfg_target_compact,
|
||||
meta_span,
|
||||
fluent_generated::attr_parsing_unstable_cfg_target_compact,
|
||||
inline_fluent!("compact `cfg(target(..))` is experimental and subject to change"),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
|
@ -360,8 +360,10 @@ fn parse_cfg_attr_internal<'a>(
|
|||
) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> {
|
||||
// Parse cfg predicate
|
||||
let pred_start = parser.token.span;
|
||||
let meta =
|
||||
MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?;
|
||||
let meta = MetaItemOrLitParser::parse_single(
|
||||
parser,
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
)?;
|
||||
let pred_span = pred_start.with_hi(parser.token.span.hi());
|
||||
|
||||
let cfg_predicate = AttributeParser::parse_single_args(
|
||||
|
|
@ -376,7 +378,7 @@ fn parse_cfg_attr_internal<'a>(
|
|||
CRATE_NODE_ID,
|
||||
Target::Crate,
|
||||
features,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&CFG_ATTR_TEMPLATE,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_feature::{AttributeTemplate, Features};
|
|||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::{AttrPath, Target};
|
||||
use rustc_parse::exp;
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_parse::parser::{Parser, Recovery};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{ErrorGuaranteed, Span, sym};
|
||||
|
||||
|
|
@ -78,9 +78,11 @@ pub fn parse_cfg_select(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let meta =
|
||||
MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true })
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let meta = MetaItemOrLitParser::parse_single(
|
||||
p,
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
)
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let cfg_span = meta.span();
|
||||
let cfg = AttributeParser::parse_single_args(
|
||||
sess,
|
||||
|
|
@ -95,7 +97,7 @@ pub fn parse_cfg_select(
|
|||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
features,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&AttributeTemplate::default(),
|
||||
|
|
|
|||
|
|
@ -274,3 +274,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoBuiltinsParser {
|
|||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcPreserveUbChecksParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcPreserveUbChecksParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,42 @@ fn check_attr_crate_level<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Spa
|
|||
true
|
||||
}
|
||||
|
||||
// FIXME: To be removed once merged and replace with `cx.expected_name_value(span, _name)`.
|
||||
fn expected_name_value<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
span: Span,
|
||||
_name: Option<Symbol>,
|
||||
) {
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::ExpectedNameValue,
|
||||
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(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::ExpectedNoArgs,
|
||||
span,
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead.
|
||||
// cx.expected_string_literal(span, _actual_literal);
|
||||
fn expected_string_literal<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
span: Span,
|
||||
_actual_literal: Option<&MetaItemLit>,
|
||||
) {
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
span,
|
||||
);
|
||||
}
|
||||
|
||||
fn parse_keyword_and_attribute<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
path: &OwnedPathParser,
|
||||
|
|
@ -78,12 +114,12 @@ fn parse_keyword_and_attribute<S: Stage>(
|
|||
attr_name: Symbol,
|
||||
) {
|
||||
let Some(nv) = args.name_value() else {
|
||||
cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym());
|
||||
expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym());
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(value) = nv.value_as_str() else {
|
||||
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit()));
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -127,12 +163,21 @@ impl DocParser {
|
|||
match path.word_sym() {
|
||||
Some(sym::no_crate_inject) => {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
expected_no_args(cx, span);
|
||||
return;
|
||||
}
|
||||
|
||||
if self.attribute.no_crate_inject.is_some() {
|
||||
cx.duplicate_key(path.span(), sym::no_crate_inject);
|
||||
if let Some(used_span) = self.attribute.no_crate_inject {
|
||||
let unused_span = path.span();
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::UnusedDuplicate {
|
||||
this: unused_span,
|
||||
other: used_span,
|
||||
warning: true,
|
||||
},
|
||||
unused_span,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +189,14 @@ impl DocParser {
|
|||
}
|
||||
Some(sym::attr) => {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
// 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(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
span,
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -246,7 +298,7 @@ impl DocParser {
|
|||
inline: DocInline,
|
||||
) {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
expected_no_args(cx, span);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +380,14 @@ impl DocParser {
|
|||
match sub_item.args() {
|
||||
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
|
||||
let Some(name) = sub_item.path().word_sym() else {
|
||||
cx.expected_identifier(sub_item.path().span());
|
||||
// FIXME: remove this method once merged and uncomment the line
|
||||
// below instead.
|
||||
// cx.expected_identifier(sub_item.path().span());
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
sub_item.path().span(),
|
||||
);
|
||||
continue;
|
||||
};
|
||||
if let Ok(CfgEntry::NameValue { name, value, .. }) =
|
||||
|
|
@ -391,7 +450,7 @@ impl DocParser {
|
|||
macro_rules! no_args {
|
||||
($ident: ident) => {{
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
expected_no_args(cx, span);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +469,7 @@ impl DocParser {
|
|||
macro_rules! no_args_and_not_crate_level {
|
||||
($ident: ident) => {{
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
expected_no_args(cx, span);
|
||||
return;
|
||||
}
|
||||
let span = path.span();
|
||||
|
|
@ -423,7 +482,7 @@ impl DocParser {
|
|||
macro_rules! no_args_and_crate_level {
|
||||
($ident: ident) => {{
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
expected_no_args(cx, span);
|
||||
return;
|
||||
}
|
||||
let span = path.span();
|
||||
|
|
@ -436,12 +495,12 @@ impl DocParser {
|
|||
macro_rules! string_arg_and_crate_level {
|
||||
($ident: ident) => {{
|
||||
let Some(nv) = args.name_value() else {
|
||||
cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym());
|
||||
expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym());
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(s) = nv.value_as_str() else {
|
||||
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit()));
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -512,7 +571,14 @@ impl DocParser {
|
|||
self.parse_single_test_doc_attr_item(cx, mip);
|
||||
}
|
||||
MetaItemOrLitParser::Lit(lit) => {
|
||||
cx.unexpected_literal(lit.span);
|
||||
// FIXME: remove this method once merged and uncomment the line
|
||||
// below instead.
|
||||
// cx.unexpected_literal(lit.span);
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::MalformedDoc,
|
||||
lit.span,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -582,7 +648,7 @@ impl DocParser {
|
|||
let suggestions = cx.suggestions();
|
||||
let span = cx.attr_span;
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None },
|
||||
span,
|
||||
);
|
||||
|
|
@ -595,14 +661,14 @@ impl DocParser {
|
|||
self.parse_single_doc_attr_item(cx, mip);
|
||||
}
|
||||
MetaItemOrLitParser::Lit(lit) => {
|
||||
cx.expected_name_value(lit.span, None);
|
||||
expected_name_value(cx, lit.span, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ArgParser::NameValue(nv) => {
|
||||
if nv.value_as_str().is_none() {
|
||||
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit()));
|
||||
} else {
|
||||
unreachable!(
|
||||
"Should have been handled at the same time as sugar-syntaxed doc comments"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_errors::inline_fluent;
|
||||
use rustc_feature::Features;
|
||||
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
|
||||
use rustc_hir::attrs::*;
|
||||
|
|
@ -10,12 +11,11 @@ use rustc_target::spec::{Arch, BinaryFormat};
|
|||
use super::prelude::*;
|
||||
use super::util::parse_single_integer;
|
||||
use crate::attributes::cfg::parse_cfg_entry;
|
||||
use crate::fluent_generated;
|
||||
use crate::session_diagnostics::{
|
||||
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86,
|
||||
IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange,
|
||||
LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows,
|
||||
WholeArchiveNeedsStatic,
|
||||
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic,
|
||||
ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier,
|
||||
LinkFrameworkApple, LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers,
|
||||
NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, WholeArchiveNeedsStatic,
|
||||
};
|
||||
|
||||
pub(crate) struct LinkNameParser;
|
||||
|
|
@ -165,6 +165,14 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
|
|||
cx.emit_err(BundleNeedsStatic { span });
|
||||
}
|
||||
|
||||
(sym::export_symbols, Some(NativeLibKind::Static { export_symbols, .. })) => {
|
||||
assign_modifier(export_symbols)
|
||||
}
|
||||
|
||||
(sym::export_symbols, _) => {
|
||||
cx.emit_err(ExportSymbolsNeedsStatic { span });
|
||||
}
|
||||
|
||||
(sym::verbatim, _) => assign_modifier(&mut verbatim),
|
||||
|
||||
(
|
||||
|
|
@ -190,6 +198,7 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
|
|||
span,
|
||||
&[
|
||||
sym::bundle,
|
||||
sym::export_symbols,
|
||||
sym::verbatim,
|
||||
sym::whole_dash_archive,
|
||||
sym::as_dash_needed,
|
||||
|
|
@ -285,7 +294,9 @@ impl LinkParser {
|
|||
};
|
||||
|
||||
let link_kind = match link_kind {
|
||||
kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kw::Static => {
|
||||
NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }
|
||||
}
|
||||
sym::dylib => NativeLibKind::Dylib { as_needed: None },
|
||||
sym::framework => {
|
||||
if !sess.target.is_like_darwin {
|
||||
|
|
@ -305,7 +316,7 @@ impl LinkParser {
|
|||
sess,
|
||||
sym::raw_dylib_elf,
|
||||
nv.value_span,
|
||||
fluent_generated::attr_parsing_raw_dylib_elf_unstable,
|
||||
inline_fluent!("link kind `raw-dylib` is unstable on ELF platforms"),
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
|
|
@ -320,7 +331,7 @@ impl LinkParser {
|
|||
sess,
|
||||
sym::link_arg_attribute,
|
||||
nv.value_span,
|
||||
fluent_generated::attr_parsing_link_arg_unstable,
|
||||
inline_fluent!("link kind `link-arg` is unstable"),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
|
@ -385,13 +396,8 @@ impl LinkParser {
|
|||
return true;
|
||||
};
|
||||
if !features.link_cfg() {
|
||||
feature_err(
|
||||
sess,
|
||||
sym::link_cfg,
|
||||
item.span(),
|
||||
fluent_generated::attr_parsing_link_cfg_unstable,
|
||||
)
|
||||
.emit();
|
||||
feature_err(sess, sym::link_cfg, item.span(), inline_fluent!("link cfg is unstable"))
|
||||
.emit();
|
||||
}
|
||||
*cfg = parse_cfg_entry(cx, link_cfg).ok();
|
||||
true
|
||||
|
|
|
|||
|
|
@ -7,36 +7,36 @@ use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
|
|||
use crate::context::Stage;
|
||||
use crate::target_checking::AllowedTargets;
|
||||
|
||||
pub(crate) struct RustcDumpUserArgs;
|
||||
pub(crate) struct RustcDumpUserArgsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpUserArgs {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpUserArgsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_user_args];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpDefParents;
|
||||
pub(crate) struct RustcDumpDefParentsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpDefParents {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpDefParentsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_def_parents];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpItemBounds;
|
||||
pub(crate) struct RustcDumpItemBoundsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBounds {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpPredicates;
|
||||
pub(crate) struct RustcDumpPredicatesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicates {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicatesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_predicates];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
|
|
@ -49,9 +49,9 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicates {
|
|||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDumpVtable;
|
||||
pub(crate) struct RustcDumpVtableParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVtable {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVtableParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_dump_vtable];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
|
||||
use rustc_hir::attrs::RustcLayoutType;
|
||||
use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcLayoutType, RustcMirKind};
|
||||
use rustc_session::errors;
|
||||
|
||||
use super::prelude::*;
|
||||
|
|
@ -307,6 +309,14 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcHasIncoherentInherentImplsParse
|
|||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcHiddenTypeOfOpaquesParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcHiddenTypeOfOpaquesParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_hidden_type_of_opaques];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHiddenTypeOfOpaques;
|
||||
}
|
||||
pub(crate) struct RustcNounwindParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNounwindParser {
|
||||
|
|
@ -349,7 +359,6 @@ impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser {
|
|||
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]);
|
||||
|
||||
fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
|
|
@ -389,6 +398,94 @@ impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcMirParser;
|
||||
|
||||
impl<S: Stage> CombineAttributeParser<S> for RustcMirParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_mir];
|
||||
|
||||
type Item = RustcMirKind;
|
||||
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items);
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
]);
|
||||
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["arg1, arg2, ..."]);
|
||||
|
||||
fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
return ThinVec::new();
|
||||
};
|
||||
|
||||
list.mixed()
|
||||
.filter_map(|arg| arg.meta_item())
|
||||
.filter_map(|mi| {
|
||||
if let Some(ident) = mi.ident() {
|
||||
match ident.name {
|
||||
sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit),
|
||||
sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit),
|
||||
sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness),
|
||||
sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow),
|
||||
sym::borrowck_graphviz_postflow => {
|
||||
let Some(nv) = mi.args().name_value() else {
|
||||
cx.expected_name_value(
|
||||
mi.span(),
|
||||
Some(sym::borrowck_graphviz_postflow),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
let Some(path) = nv.value_as_str() else {
|
||||
cx.expected_string_literal(nv.value_span, None);
|
||||
return None;
|
||||
};
|
||||
let path = PathBuf::from(path.to_string());
|
||||
if path.file_name().is_some() {
|
||||
Some(RustcMirKind::BorrowckGraphvizPostflow { path })
|
||||
} else {
|
||||
cx.expected_filename_literal(nv.value_span);
|
||||
None
|
||||
}
|
||||
}
|
||||
sym::borrowck_graphviz_format => {
|
||||
let Some(nv) = mi.args().name_value() else {
|
||||
cx.expected_name_value(
|
||||
mi.span(),
|
||||
Some(sym::borrowck_graphviz_format),
|
||||
);
|
||||
return None;
|
||||
};
|
||||
let Some(format) = nv.value_as_ident() else {
|
||||
cx.expected_identifier(nv.value_span);
|
||||
return None;
|
||||
};
|
||||
match format.name {
|
||||
sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat {
|
||||
format: BorrowckGraphvizFormatKind::TwoPhase,
|
||||
}),
|
||||
_ => {
|
||||
cx.expected_specific_argument(format.span, &[sym::two_phase]);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
pub(crate) struct RustcNonConstTraitMethodParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNonConstTraitMethodParser {
|
||||
|
|
|
|||
|
|
@ -10,93 +10,48 @@ use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
|
|||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrPath, HirId};
|
||||
use rustc_parse::parser::Recovery;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{Lint, LintId};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
|
||||
use crate::AttributeParser;
|
||||
use crate::attributes::allow_unstable::{
|
||||
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
|
||||
};
|
||||
use crate::attributes::body::CoroutineParser;
|
||||
use crate::attributes::cfi_encoding::CfiEncodingParser;
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, CoverageParser, EiiForeignItemParser, ExportNameParser, ForceTargetFeatureParser,
|
||||
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
|
||||
PatchableFunctionEntryParser, RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser,
|
||||
TargetFeatureParser, ThreadLocalParser, TrackCallerParser, UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::crate_level::{
|
||||
CrateNameParser, CrateTypeParser, MoveSizeLimitParser, NeedsPanicRuntimeParser,
|
||||
NoBuiltinsParser, NoCoreParser, NoMainParser, NoStdParser, PanicRuntimeParser,
|
||||
PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser,
|
||||
RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser,
|
||||
};
|
||||
use crate::attributes::debugger::DebuggerViualizerParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::do_not_recommend::DoNotRecommendParser;
|
||||
use crate::attributes::doc::DocParser;
|
||||
use crate::attributes::dummy::DummyParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::instruction_set::InstructionSetParser;
|
||||
use crate::attributes::link_attrs::{
|
||||
CompilerBuiltinsParser, ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser,
|
||||
LinkOrdinalParser, LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser,
|
||||
StdInternalSymbolParser,
|
||||
};
|
||||
use crate::attributes::lint_helpers::{
|
||||
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
|
||||
RustcShouldNotBeCalledOnConstItems,
|
||||
};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::macro_attrs::{
|
||||
AllowInternalUnsafeParser, CollapseDebugInfoParser, MacroEscapeParser, MacroExportParser,
|
||||
MacroUseParser,
|
||||
};
|
||||
use crate::attributes::must_not_suspend::MustNotSuspendParser;
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
use crate::attributes::no_link::NoLinkParser;
|
||||
use crate::attributes::non_exhaustive::NonExhaustiveParser;
|
||||
// Glob imports to avoid big, bitrotty import lists
|
||||
use crate::attributes::allow_unstable::*;
|
||||
use crate::attributes::body::*;
|
||||
use crate::attributes::cfi_encoding::*;
|
||||
use crate::attributes::codegen_attrs::*;
|
||||
use crate::attributes::confusables::*;
|
||||
use crate::attributes::crate_level::*;
|
||||
use crate::attributes::debugger::*;
|
||||
use crate::attributes::deprecation::*;
|
||||
use crate::attributes::do_not_recommend::*;
|
||||
use crate::attributes::doc::*;
|
||||
use crate::attributes::dummy::*;
|
||||
use crate::attributes::inline::*;
|
||||
use crate::attributes::instruction_set::*;
|
||||
use crate::attributes::link_attrs::*;
|
||||
use crate::attributes::lint_helpers::*;
|
||||
use crate::attributes::loop_match::*;
|
||||
use crate::attributes::macro_attrs::*;
|
||||
use crate::attributes::must_not_suspend::*;
|
||||
use crate::attributes::must_use::*;
|
||||
use crate::attributes::no_implicit_prelude::*;
|
||||
use crate::attributes::no_link::*;
|
||||
use crate::attributes::non_exhaustive::*;
|
||||
use crate::attributes::path::PathParser as PathAttributeParser;
|
||||
use crate::attributes::pin_v2::PinV2Parser;
|
||||
use crate::attributes::proc_macro_attrs::{
|
||||
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
|
||||
};
|
||||
use crate::attributes::prototype::CustomMirParser;
|
||||
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
|
||||
use crate::attributes::rustc_allocator::{
|
||||
RustcAllocatorParser, RustcAllocatorZeroedParser, RustcAllocatorZeroedVariantParser,
|
||||
RustcDeallocatorParser, RustcReallocatorParser,
|
||||
};
|
||||
use crate::attributes::rustc_dump::{
|
||||
RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs,
|
||||
RustcDumpVtable,
|
||||
};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser,
|
||||
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
|
||||
RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
|
||||
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
|
||||
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser,
|
||||
RustcNonConstTraitMethodParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser,
|
||||
RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
use crate::attributes::stability::{
|
||||
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
|
||||
};
|
||||
use crate::attributes::test_attrs::{
|
||||
IgnoreParser, RustcVarianceOfOpaquesParser, RustcVarianceParser, ShouldPanicParser,
|
||||
};
|
||||
use crate::attributes::traits::{
|
||||
AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser,
|
||||
DynIncompatibleTraitParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser,
|
||||
SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
|
||||
UnsafeSpecializationMarkerParser,
|
||||
};
|
||||
use crate::attributes::transparency::TransparencyParser;
|
||||
use crate::attributes::pin_v2::*;
|
||||
use crate::attributes::proc_macro_attrs::*;
|
||||
use crate::attributes::prototype::*;
|
||||
use crate::attributes::repr::*;
|
||||
use crate::attributes::rustc_allocator::*;
|
||||
use crate::attributes::rustc_dump::*;
|
||||
use crate::attributes::rustc_internal::*;
|
||||
use crate::attributes::semantics::*;
|
||||
use crate::attributes::stability::*;
|
||||
use crate::attributes::test_attrs::*;
|
||||
use crate::attributes::traits::*;
|
||||
use crate::attributes::transparency::*;
|
||||
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
|
||||
use crate::parser::{ArgParser, RefPathParser};
|
||||
use crate::session_diagnostics::{
|
||||
|
|
@ -199,6 +154,7 @@ attribute_parsers!(
|
|||
Combine<LinkParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<RustcLayoutParser>,
|
||||
Combine<RustcMirParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
// tidy-alphabetical-end
|
||||
|
|
@ -293,12 +249,13 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<RustcAllocatorZeroedParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<RustcDeallocatorParser>>,
|
||||
Single<WithoutArgs<RustcDumpDefParents>>,
|
||||
Single<WithoutArgs<RustcDumpItemBounds>>,
|
||||
Single<WithoutArgs<RustcDumpPredicates>>,
|
||||
Single<WithoutArgs<RustcDumpUserArgs>>,
|
||||
Single<WithoutArgs<RustcDumpVtable>>,
|
||||
Single<WithoutArgs<RustcDumpDefParentsParser>>,
|
||||
Single<WithoutArgs<RustcDumpItemBoundsParser>>,
|
||||
Single<WithoutArgs<RustcDumpPredicatesParser>>,
|
||||
Single<WithoutArgs<RustcDumpUserArgsParser>>,
|
||||
Single<WithoutArgs<RustcDumpVtableParser>>,
|
||||
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
|
||||
Single<WithoutArgs<RustcHiddenTypeOfOpaquesParser>>,
|
||||
Single<WithoutArgs<RustcLintOptTyParser>>,
|
||||
Single<WithoutArgs<RustcLintQueryInstabilityParser>>,
|
||||
Single<WithoutArgs<RustcLintUntrackedQueryInformationParser>>,
|
||||
|
|
@ -309,6 +266,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<RustcNounwindParser>>,
|
||||
Single<WithoutArgs<RustcOffloadKernelParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
Single<WithoutArgs<RustcPreserveUbChecksParser>>,
|
||||
Single<WithoutArgs<RustcReallocatorParser>>,
|
||||
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
|
||||
Single<WithoutArgs<RustcVarianceOfOpaquesParser>>,
|
||||
|
|
@ -383,7 +341,7 @@ impl Stage for Late {
|
|||
}
|
||||
|
||||
fn should_emit(&self) -> ShouldEmit {
|
||||
ShouldEmit::ErrorsAndLints { recover: true }
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -512,6 +470,11 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Error that a filename string literal was expected.
|
||||
pub(crate) fn expected_filename_literal(&self, span: Span) {
|
||||
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedFilenameLiteral);
|
||||
}
|
||||
|
||||
pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
|
||||
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIntegerLiteral)
|
||||
}
|
||||
|
|
@ -770,10 +733,10 @@ pub enum ShouldEmit {
|
|||
ErrorsAndLints {
|
||||
/// Whether [`ArgParser`] will attempt to recover from errors.
|
||||
///
|
||||
/// If true, it will attempt to recover from bad input (like an invalid literal). Setting
|
||||
/// this to false will instead return early, and not raise errors except at the top level
|
||||
/// (in [`ArgParser::from_attr_args`]).
|
||||
recover: bool,
|
||||
/// Whether it is allowed to recover from bad input (like an invalid literal). Setting
|
||||
/// this to `Forbidden` will instead return early, and not raise errors except at the top
|
||||
/// level (in [`ArgParser::from_attr_args`]).
|
||||
recovery: Recovery,
|
||||
},
|
||||
/// The operation will *not* emit errors and lints.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -113,5 +113,3 @@ pub use attributes::util::{is_builtin_attr, parse_version};
|
|||
pub use context::{Early, Late, OmitDoc, ShouldEmit};
|
||||
pub use interface::AttributeParser;
|
||||
pub use session_diagnostics::ParsedDescription;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust;
|
|||
use rustc_errors::{Diag, PResult};
|
||||
use rustc_hir::{self as hir, AttrPath};
|
||||
use rustc_parse::exp;
|
||||
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr};
|
||||
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, Recovery, token_descr};
|
||||
use rustc_session::errors::create_lit_error;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
|
|
@ -121,7 +121,7 @@ impl ArgParser {
|
|||
&args.tokens,
|
||||
args.dspan.entire(),
|
||||
psess,
|
||||
ShouldEmit::ErrorsAndLints { recover: false },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden },
|
||||
) {
|
||||
Ok(p) => return Some(ArgParser::List(p)),
|
||||
Err(e) => {
|
||||
|
|
@ -373,7 +373,10 @@ fn expr_to_lit<'sess>(
|
|||
}
|
||||
Err(err) => {
|
||||
let err = create_lit_error(psess, err, token_lit, expr.span);
|
||||
if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) {
|
||||
if matches!(
|
||||
should_emit,
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }
|
||||
) {
|
||||
Err(err)
|
||||
} else {
|
||||
let lit = MetaItemLit {
|
||||
|
|
@ -431,7 +434,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
|
|||
if !lit.kind.is_unsuffixed() {
|
||||
// Emit error and continue, we can still parse the attribute as if the suffix isn't there
|
||||
let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span });
|
||||
if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) {
|
||||
if matches!(
|
||||
self.should_emit,
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }
|
||||
) {
|
||||
return Err(err);
|
||||
} else {
|
||||
self.should_emit.emit_err(err)
|
||||
|
|
@ -569,6 +575,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
|
|||
should_emit: ShouldEmit,
|
||||
) -> PResult<'sess, MetaItemListParser> {
|
||||
let mut parser = Parser::new(psess, tokens, None);
|
||||
if let ShouldEmit::ErrorsAndLints { recovery } = should_emit {
|
||||
parser = parser.recovery(recovery);
|
||||
}
|
||||
|
||||
let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };
|
||||
|
||||
// Presumably, the majority of the time there will only be one attr.
|
||||
|
|
|
|||
|
|
@ -11,10 +11,8 @@ use rustc_macros::{Diagnostic, Subdiagnostic};
|
|||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::spec::TargetTuple;
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_predicate, code = E0537)]
|
||||
#[diag("invalid predicate `{$predicate}`", code = E0537)]
|
||||
pub(crate) struct InvalidPredicate {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -23,7 +21,7 @@ pub(crate) struct InvalidPredicate {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_alias_empty)]
|
||||
#[diag("{$attr_str} attribute cannot have empty value")]
|
||||
pub(crate) struct DocAliasEmpty<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -31,7 +29,7 @@ pub(crate) struct DocAliasEmpty<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_alias_bad_char)]
|
||||
#[diag("{$char_} character isn't allowed in {$attr_str}")]
|
||||
pub(crate) struct DocAliasBadChar<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -40,7 +38,7 @@ pub(crate) struct DocAliasBadChar<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_alias_start_end)]
|
||||
#[diag("{$attr_str} cannot start or end with ' '")]
|
||||
pub(crate) struct DocAliasStartEnd<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -48,7 +46,7 @@ pub(crate) struct DocAliasStartEnd<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_attr_not_crate_level)]
|
||||
#[diag("`#![doc({$attr_name} = \"...\")]` isn't allowed as a crate-level attribute")]
|
||||
pub(crate) struct DocAttrNotCrateLevel {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -56,8 +54,8 @@ pub(crate) struct DocAttrNotCrateLevel {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_keyword_not_keyword)]
|
||||
#[help]
|
||||
#[diag("nonexistent keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`")]
|
||||
#[help("only existing keywords are allowed in core/std")]
|
||||
pub(crate) struct DocKeywordNotKeyword {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -65,8 +63,8 @@ pub(crate) struct DocKeywordNotKeyword {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_attribute_not_attribute)]
|
||||
#[help]
|
||||
#[diag("nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = \"...\")]`")]
|
||||
#[help("only existing builtin attributes are allowed in core/std")]
|
||||
pub(crate) struct DocAttributeNotAttribute {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -74,28 +72,28 @@ pub(crate) struct DocAttributeNotAttribute {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_missing_since, code = E0542)]
|
||||
#[diag("missing 'since'", code = E0542)]
|
||||
pub(crate) struct MissingSince {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_missing_note, code = E0543)]
|
||||
#[diag("missing 'note'", code = E0543)]
|
||||
pub(crate) struct MissingNote {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_multiple_stability_levels, code = E0544)]
|
||||
#[diag("multiple stability levels", code = E0544)]
|
||||
pub(crate) struct MultipleStabilityLevels {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_issue_string, code = E0545)]
|
||||
#[diag("`issue` must be a non-zero numeric string or \"none\"", code = E0545)]
|
||||
pub(crate) struct InvalidIssueString {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -108,31 +106,31 @@ pub(crate) struct InvalidIssueString {
|
|||
// translatable.
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum InvalidIssueStringCause {
|
||||
#[label(attr_parsing_must_not_be_zero)]
|
||||
#[label("`issue` must not be \"0\", use \"none\" instead")]
|
||||
MustNotBeZero {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_parsing_empty)]
|
||||
#[label("cannot parse integer from empty string")]
|
||||
Empty {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_parsing_invalid_digit)]
|
||||
#[label("invalid digit found in string")]
|
||||
InvalidDigit {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_parsing_pos_overflow)]
|
||||
#[label("number too large to fit in target type")]
|
||||
PosOverflow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_parsing_neg_overflow)]
|
||||
#[label("number too small to fit in target type")]
|
||||
NegOverflow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -153,21 +151,21 @@ impl InvalidIssueStringCause {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_missing_feature, code = E0546)]
|
||||
#[diag("missing 'feature'", code = E0546)]
|
||||
pub(crate) struct MissingFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_non_ident_feature, code = E0546)]
|
||||
#[diag("'feature' is not an identifier", code = E0546)]
|
||||
pub(crate) struct NonIdentFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_missing_issue, code = E0547)]
|
||||
#[diag("missing 'issue'", code = E0547)]
|
||||
pub(crate) struct MissingIssue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -176,20 +174,20 @@ pub(crate) struct MissingIssue {
|
|||
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
|
||||
// It is more similar to `IncorrectReprFormatGeneric`.
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
|
||||
#[diag("incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all", code = E0552)]
|
||||
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_packed_expect_integer, code = E0552)]
|
||||
#[diag("incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument", code = E0552)]
|
||||
pub(crate) struct IncorrectReprFormatPackedExpectInteger {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_repr_hint_no_paren, code = E0552)]
|
||||
#[diag("invalid representation hint: `{$name}` does not take a parenthesized argument list", code = E0552)]
|
||||
pub(crate) struct InvalidReprHintNoParen {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -198,7 +196,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_repr_hint_no_value, code = E0552)]
|
||||
#[diag("invalid representation hint: `{$name}` does not take a value", code = E0552)]
|
||||
pub(crate) struct InvalidReprHintNoValue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -207,15 +205,19 @@ pub(crate) struct InvalidReprHintNoValue {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)]
|
||||
#[diag("invalid `repr(align)` attribute: `align` needs an argument", code = E0589)]
|
||||
pub(crate) struct InvalidReprAlignNeedArg {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
|
||||
#[suggestion(
|
||||
"supply an argument here",
|
||||
code = "align(...)",
|
||||
applicability = "has-placeholders"
|
||||
)]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_repr_generic, code = E0589)]
|
||||
#[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)]
|
||||
pub(crate) struct InvalidReprGeneric<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -225,21 +227,21 @@ pub(crate) struct InvalidReprGeneric<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_align_one_arg, code = E0693)]
|
||||
#[diag("incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses", code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatAlignOneArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_expect_literal_integer, code = E0693)]
|
||||
#[diag("incorrect `repr(align)` attribute format: `align` expects a literal integer as argument", code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatExpectInteger {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)]
|
||||
#[diag("incorrect `repr({$repr_arg})` attribute format", code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -253,7 +255,7 @@ pub(crate) struct IncorrectReprFormatGeneric {
|
|||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum IncorrectReprFormatGenericCause {
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
"use parentheses instead",
|
||||
code = "{name}({value})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
|
|
@ -269,7 +271,7 @@ pub(crate) enum IncorrectReprFormatGenericCause {
|
|||
},
|
||||
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
"use parentheses instead",
|
||||
code = "{name}({value})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
|
|
@ -298,48 +300,48 @@ impl IncorrectReprFormatGenericCause {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_rustc_promotable_pairing, code = E0717)]
|
||||
#[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)]
|
||||
pub(crate) struct RustcPromotablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_rustc_allowed_unstable_pairing, code = E0789)]
|
||||
#[diag("`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute", code = E0789)]
|
||||
pub(crate) struct RustcAllowedUnstablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_deprecated_item_suggestion)]
|
||||
#[diag("suggestions on deprecated items are unstable")]
|
||||
pub(crate) struct DeprecatedItemSuggestion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
#[help]
|
||||
#[help("add `#![feature(deprecated_suggestion)]` to the crate root")]
|
||||
pub is_nightly: bool,
|
||||
|
||||
#[note]
|
||||
#[note("see #94785 for more details")]
|
||||
pub details: (),
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_expected_single_version_literal)]
|
||||
#[diag("expected single version literal")]
|
||||
pub(crate) struct ExpectedSingleVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_expected_version_literal)]
|
||||
#[diag("expected a version literal")]
|
||||
pub(crate) struct ExpectedVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_expects_feature_list)]
|
||||
#[diag("`{$name}` expects a list of feature names")]
|
||||
pub(crate) struct ExpectsFeatureList {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -348,7 +350,7 @@ pub(crate) struct ExpectsFeatureList {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_expects_features)]
|
||||
#[diag("`{$name}` expects feature names")]
|
||||
pub(crate) struct ExpectsFeatures {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -357,21 +359,21 @@ pub(crate) struct ExpectsFeatures {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_since)]
|
||||
#[diag("'since' must be a Rust version number, such as \"1.31.0\"")]
|
||||
pub(crate) struct InvalidSince {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_soft_no_args)]
|
||||
#[diag("`soft` should not have any arguments")]
|
||||
pub(crate) struct SoftNoArgs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unknown_version_literal)]
|
||||
#[diag("unknown version literal format, assuming it refers to a future version")]
|
||||
pub(crate) struct UnknownVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -379,78 +381,83 @@ pub(crate) struct UnknownVersionLiteral {
|
|||
|
||||
// FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated.
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unused_multiple)]
|
||||
#[diag("multiple `{$name}` attributes")]
|
||||
pub(crate) struct UnusedMultiple {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||
#[suggestion("remove this attribute", code = "", applicability = "machine-applicable")]
|
||||
pub this: Span,
|
||||
#[note]
|
||||
#[note("attribute also specified here")]
|
||||
pub other: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_null_on_export, code = E0648)]
|
||||
#[diag("`export_name` may not contain null characters", code = E0648)]
|
||||
pub(crate) struct NullOnExport {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_null_on_link_section, code = E0648)]
|
||||
#[diag("`link_section` may not contain null characters", code = E0648)]
|
||||
pub(crate) struct NullOnLinkSection {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_null_on_objc_class)]
|
||||
#[diag("`objc::class!` may not contain null characters")]
|
||||
pub(crate) struct NullOnObjcClass {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_null_on_objc_selector)]
|
||||
#[diag("`objc::selector!` may not contain null characters")]
|
||||
pub(crate) struct NullOnObjcSelector {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_objc_class_expected_string_literal)]
|
||||
#[diag("`objc::class!` expected a string literal")]
|
||||
pub(crate) struct ObjcClassExpectedStringLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_objc_selector_expected_string_literal)]
|
||||
#[diag("`objc::selector!` expected a string literal")]
|
||||
pub(crate) struct ObjcSelectorExpectedStringLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_stability_outside_std, code = E0734)]
|
||||
#[diag("stability attributes may not be used outside of the standard library", code = E0734)]
|
||||
pub(crate) struct StabilityOutsideStd {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_empty_confusables)]
|
||||
#[diag("expected at least one confusable name")]
|
||||
pub(crate) struct EmptyConfusables {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[help]
|
||||
#[diag(attr_parsing_invalid_target)]
|
||||
#[help("`#[{$name}]` can {$only}be applied to {$applied}")]
|
||||
#[diag("`#[{$name}]` attribute cannot be used on {$target}")]
|
||||
pub(crate) struct InvalidTarget {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
|
||||
#[suggestion(
|
||||
"remove the attribute",
|
||||
code = "",
|
||||
applicability = "machine-applicable",
|
||||
style = "tool-only"
|
||||
)]
|
||||
pub span: Span,
|
||||
pub name: AttrPath,
|
||||
pub target: &'static str,
|
||||
|
|
@ -459,7 +466,7 @@ pub(crate) struct InvalidTarget {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_alignment_value, code = E0589)]
|
||||
#[diag("invalid alignment value: {$error_part}", code = E0589)]
|
||||
pub(crate) struct InvalidAlignmentValue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -467,43 +474,49 @@ pub(crate) struct InvalidAlignmentValue {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_repr_ident, code = E0565)]
|
||||
#[diag("meta item in `repr` must be an identifier", code = E0565)]
|
||||
pub(crate) struct ReprIdent {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unrecognized_repr_hint, code = E0552)]
|
||||
#[help]
|
||||
#[note]
|
||||
#[diag("unrecognized representation hint", code = E0552)]
|
||||
#[help(
|
||||
"valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`"
|
||||
)]
|
||||
#[note(
|
||||
"for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>"
|
||||
)]
|
||||
pub(crate) struct UnrecognizedReprHint {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)]
|
||||
#[help]
|
||||
#[diag("item annotated with `#[unstable_feature_bound]` should not be stable")]
|
||||
#[help(
|
||||
"if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`"
|
||||
)]
|
||||
pub(crate) struct UnstableFeatureBoundIncompatibleStability {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)]
|
||||
#[diag("attribute incompatible with `#[unsafe(naked)]`", code = E0736)]
|
||||
pub(crate) struct NakedFunctionIncompatibleAttribute {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("the `{$attr}` attribute is incompatible with `#[unsafe(naked)]`")]
|
||||
pub span: Span,
|
||||
#[label(attr_parsing_naked_attribute)]
|
||||
#[label("function marked with `#[unsafe(naked)]` here")]
|
||||
pub naked_span: Span,
|
||||
pub attr: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_link_ordinal_out_of_range)]
|
||||
#[note]
|
||||
#[diag("ordinal value in `link_ordinal` is too large: `{$ordinal}`")]
|
||||
#[note("the value may not exceed `u16::MAX`")]
|
||||
pub(crate) struct LinkOrdinalOutOfRange {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -511,8 +524,8 @@ pub(crate) struct LinkOrdinalOutOfRange {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_rustc_scalable_vector_count_out_of_range)]
|
||||
#[note]
|
||||
#[diag("element count in `rustc_scalable_vector` is too large: `{$n}`")]
|
||||
#[note("the value may not exceed `u16::MAX`")]
|
||||
pub(crate) struct RustcScalableVectorCountOutOfRange {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -524,6 +537,7 @@ pub(crate) enum AttributeParseErrorReason<'a> {
|
|||
ExpectedStringLiteral {
|
||||
byte_string: Option<Span>,
|
||||
},
|
||||
ExpectedFilenameLiteral,
|
||||
ExpectedIntegerLiteral,
|
||||
ExpectedIntegerLiteralInRange {
|
||||
lower_bound: isize,
|
||||
|
|
@ -586,7 +600,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
|||
if let Some(start_point_span) = byte_string {
|
||||
diag.span_suggestion(
|
||||
start_point_span,
|
||||
fluent::attr_parsing_unsupported_literal_suggestion,
|
||||
"consider removing the prefix",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
@ -597,6 +611,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
|||
diag.span_label(self.span, "expected a string literal here");
|
||||
}
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedFilenameLiteral => {
|
||||
diag.span_label(self.span, "expected a filename string literal here");
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedIntegerLiteral => {
|
||||
diag.span_label(self.span, "expected an integer literal here");
|
||||
}
|
||||
|
|
@ -751,30 +768,27 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_attr_unsafe)]
|
||||
#[note]
|
||||
#[diag("`{$name}` is not an unsafe attribute")]
|
||||
#[note("extraneous unsafe is not allowed in attributes")]
|
||||
pub(crate) struct InvalidAttrUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("this is not an unsafe attribute")]
|
||||
pub span: Span,
|
||||
pub name: AttrPath,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unsafe_attr_outside_unsafe)]
|
||||
#[diag("unsafe attribute used without unsafe")]
|
||||
pub(crate) struct UnsafeAttrOutsideUnsafe {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("usage of unsafe attribute")]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: Option<UnsafeAttrOutsideUnsafeSuggestion>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
attr_parsing_unsafe_attr_outside_unsafe_suggestion,
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")]
|
||||
pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
|
||||
#[suggestion_part(code = "unsafe(")]
|
||||
pub left: Span,
|
||||
|
|
@ -783,7 +797,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_meta_bad_delim)]
|
||||
#[diag("wrong meta list delimiters")]
|
||||
pub(crate) struct MetaBadDelim {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -793,7 +807,7 @@ pub(crate) struct MetaBadDelim {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
attr_parsing_meta_bad_delim_suggestion,
|
||||
"the delimiters should be `(` and `)`",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
pub(crate) struct MetaBadDelimSugg {
|
||||
|
|
@ -804,7 +818,7 @@ pub(crate) struct MetaBadDelimSugg {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_meta_item)]
|
||||
#[diag("expected a literal (`1u8`, `1.0f32`, `\"string\"`, etc.) here, found {$descr}")]
|
||||
pub(crate) struct InvalidMetaItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -813,12 +827,15 @@ pub(crate) struct InvalidMetaItem {
|
|||
pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>,
|
||||
#[subdiagnostic]
|
||||
pub remove_neg_sugg: Option<InvalidMetaItemRemoveNegSugg>,
|
||||
#[label]
|
||||
#[label("{$descr}s are not allowed here")]
|
||||
pub label: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(attr_parsing_quote_ident_sugg, applicability = "machine-applicable")]
|
||||
#[multipart_suggestion(
|
||||
"surround the identifier with quotation marks to make it into a string literal",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
pub(crate) struct InvalidMetaItemQuoteIdentSugg {
|
||||
#[suggestion_part(code = "\"")]
|
||||
pub before: Span,
|
||||
|
|
@ -827,73 +844,80 @@ pub(crate) struct InvalidMetaItemQuoteIdentSugg {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(attr_parsing_remove_neg_sugg, applicability = "machine-applicable")]
|
||||
#[multipart_suggestion(
|
||||
"negative numbers are not literals, try removing the `-` sign",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
pub(crate) struct InvalidMetaItemRemoveNegSugg {
|
||||
#[suggestion_part(code = "")]
|
||||
pub negative_sign: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_suffixed_literal_in_attribute)]
|
||||
#[help]
|
||||
#[diag("suffixed literals are not allowed in attributes")]
|
||||
#[help(
|
||||
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)"
|
||||
)]
|
||||
pub(crate) struct SuffixedLiteralInAttribute {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_empty_link_name, code = E0454)]
|
||||
#[diag("link name must not be empty", code = E0454)]
|
||||
pub(crate) struct EmptyLinkName {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("empty link name")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_link_framework_apple, code = E0455)]
|
||||
#[diag("link kind `framework` is only supported on Apple targets", code = E0455)]
|
||||
pub(crate) struct LinkFrameworkApple {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incompatible_wasm_link)]
|
||||
#[diag("`wasm_import_module` is incompatible with other arguments in `#[link]` attributes")]
|
||||
pub(crate) struct IncompatibleWasmLink {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_link_requires_name, code = E0459)]
|
||||
#[diag("`#[link]` attribute requires a `name = \"string\"` argument", code = E0459)]
|
||||
pub(crate) struct LinkRequiresName {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("missing `name` argument")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_raw_dylib_no_nul)]
|
||||
#[diag("link name must not contain NUL characters if link kind is `raw-dylib`")]
|
||||
pub(crate) struct RawDylibNoNul {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)]
|
||||
#[diag("link kind `raw-dylib` is only supported on Windows targets", code = E0455)]
|
||||
pub(crate) struct RawDylibOnlyWindows {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_link_modifier)]
|
||||
#[diag(
|
||||
"invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols"
|
||||
)]
|
||||
pub(crate) struct InvalidLinkModifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_multiple_modifiers)]
|
||||
#[diag("multiple `{$modifier}` modifiers in a single `modifiers` argument")]
|
||||
pub(crate) struct MultipleModifiers {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -901,52 +925,61 @@ pub(crate) struct MultipleModifiers {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_import_name_type_x86)]
|
||||
#[diag("import name type is only supported on x86")]
|
||||
pub(crate) struct ImportNameTypeX86 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_bundle_needs_static)]
|
||||
#[diag("linking modifier `bundle` is only compatible with `static` linking kind")]
|
||||
pub(crate) struct BundleNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_whole_archive_needs_static)]
|
||||
#[diag("linking modifier `export-symbols` is only compatible with `static` linking kind")]
|
||||
pub(crate) struct ExportSymbolsNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("linking modifier `whole-archive` is only compatible with `static` linking kind")]
|
||||
pub(crate) struct WholeArchiveNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_as_needed_compatibility)]
|
||||
#[diag(
|
||||
"linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds"
|
||||
)]
|
||||
pub(crate) struct AsNeededCompatibility {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_import_name_type_raw)]
|
||||
#[diag("import name type can only be used with link kind `raw-dylib`")]
|
||||
pub(crate) struct ImportNameTypeRaw {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_limit_invalid)]
|
||||
#[diag("`limit` must be a non-negative integer")]
|
||||
pub(crate) struct LimitInvalid<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
#[label("{$error_str}")]
|
||||
pub value_span: Span,
|
||||
pub error_str: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_cfg_attr_bad_delim)]
|
||||
#[diag("wrong `cfg_attr` delimiters")]
|
||||
pub(crate) struct CfgAttrBadDelim {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -955,14 +988,16 @@ pub(crate) struct CfgAttrBadDelim {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_doc_alias_malformed)]
|
||||
#[diag(
|
||||
"doc alias attribute expects a string `#[doc(alias = \"a\")]` or a list of strings `#[doc(alias(\"a\", \"b\"))]`"
|
||||
)]
|
||||
pub(crate) struct DocAliasMalformed {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unsupported_instruction_set)]
|
||||
#[diag("target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`")]
|
||||
pub(crate) struct UnsupportedInstructionSet<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
|
|||
|
|
@ -2309,12 +2309,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
tcx: TyCtxt<'hir>,
|
||||
issue_span: Span,
|
||||
expr_span: Span,
|
||||
body_expr: Option<&'hir hir::Expr<'hir>>,
|
||||
loop_bind: Option<&'hir Ident>,
|
||||
loop_span: Option<Span>,
|
||||
head_span: Option<Span>,
|
||||
pat_span: Option<Span>,
|
||||
head: Option<&'hir hir::Expr<'hir>>,
|
||||
body_expr: Option<&'hir hir::Expr<'hir>> = None,
|
||||
loop_bind: Option<&'hir Ident> = None,
|
||||
loop_span: Option<Span> = None,
|
||||
head_span: Option<Span> = None,
|
||||
pat_span: Option<Span> = None,
|
||||
head: Option<&'hir hir::Expr<'hir>> = None,
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
|
||||
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||
|
|
@ -2380,17 +2380,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
hir::intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
let mut finder = ExprFinder {
|
||||
tcx,
|
||||
expr_span: span,
|
||||
issue_span,
|
||||
loop_bind: None,
|
||||
body_expr: None,
|
||||
head_span: None,
|
||||
loop_span: None,
|
||||
pat_span: None,
|
||||
head: None,
|
||||
};
|
||||
let mut finder = ExprFinder { tcx, expr_span: span, issue_span, .. };
|
||||
finder.visit_expr(tcx.hir_body(body_id).value);
|
||||
|
||||
if let Some(body_expr) = finder.body_expr
|
||||
|
|
@ -2625,13 +2615,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
|
||||
struct ExpressionFinder<'tcx> {
|
||||
capture_span: Span,
|
||||
closure_change_spans: Vec<Span>,
|
||||
closure_arg_span: Option<Span>,
|
||||
in_closure: bool,
|
||||
suggest_arg: String,
|
||||
closure_change_spans: Vec<Span> = vec![],
|
||||
closure_arg_span: Option<Span> = None,
|
||||
in_closure: bool = false,
|
||||
suggest_arg: String = String::new(),
|
||||
tcx: TyCtxt<'tcx>,
|
||||
closure_local_id: Option<hir::HirId>,
|
||||
closure_call_changes: Vec<(Span, String)>,
|
||||
closure_local_id: Option<hir::HirId> = None,
|
||||
closure_call_changes: Vec<(Span, String)> = vec![],
|
||||
}
|
||||
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
|
||||
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||
|
|
@ -2712,16 +2702,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}) = self.infcx.tcx.hir_node(self.mir_hir_id())
|
||||
&& let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id)
|
||||
{
|
||||
let mut finder = ExpressionFinder {
|
||||
capture_span: *capture_kind_span,
|
||||
closure_change_spans: vec![],
|
||||
closure_arg_span: None,
|
||||
in_closure: false,
|
||||
suggest_arg: String::new(),
|
||||
closure_local_id: None,
|
||||
closure_call_changes: vec![],
|
||||
tcx: self.infcx.tcx,
|
||||
};
|
||||
let mut finder =
|
||||
ExpressionFinder { capture_span: *capture_kind_span, tcx: self.infcx.tcx, .. };
|
||||
finder.visit_expr(expr);
|
||||
|
||||
if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(default_field_values)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(negative_impls)]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpa
|
|||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::{AttrPath, Target};
|
||||
use rustc_parse::exp;
|
||||
use rustc_parse::parser::Recovery;
|
||||
use rustc_span::{ErrorGuaranteed, Span, sym};
|
||||
|
||||
use crate::errors;
|
||||
|
|
@ -42,7 +43,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
|
|||
|
||||
let meta = MetaItemOrLitParser::parse_single(
|
||||
&mut parser,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
)
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let cfg = AttributeParser::parse_single_args(
|
||||
|
|
@ -58,7 +59,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
|
|||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
Some(cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&CFG_TEMPLATE,
|
||||
|
|
|
|||
|
|
@ -125,11 +125,6 @@ pub struct CraneliftCodegenBackend {
|
|||
}
|
||||
|
||||
impl CodegenBackend for CraneliftCodegenBackend {
|
||||
fn locale_resource(&self) -> &'static str {
|
||||
// FIXME(rust-lang/rust#100717) - cranelift codegen backend is not yet translated
|
||||
""
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"cranelift"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
codegen_gcc_unwinding_inline_asm =
|
||||
GCC backend does not support unwinding from inline asm
|
||||
|
||||
codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err}
|
||||
|
||||
codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err})
|
||||
|
||||
codegen_gcc_explicit_tail_calls_unsupported = explicit tail calls with the 'become' keyword are not implemented in the GCC backend
|
||||
|
|
@ -2,24 +2,24 @@ use rustc_macros::Diagnostic;
|
|||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_unwinding_inline_asm)]
|
||||
#[diag("GCC backend does not support unwinding from inline asm")]
|
||||
pub(crate) struct UnwindingInlineAsm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_copy_bitcode)]
|
||||
#[diag("failed to copy bitcode to object file: {$err}")]
|
||||
pub(crate) struct CopyBitcode {
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_lto_bitcode_from_rlib)]
|
||||
#[diag("failed to get bitcode from object file for LTO ({$gcc_err})")]
|
||||
pub(crate) struct LtoBitcodeFromRlib {
|
||||
pub gcc_err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_explicit_tail_calls_unsupported)]
|
||||
#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")]
|
||||
pub(crate) struct ExplicitTailCallsUnsupported;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ extern crate rustc_ast;
|
|||
extern crate rustc_codegen_ssa;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_fluent_macro;
|
||||
extern crate rustc_fs_util;
|
||||
extern crate rustc_hir;
|
||||
extern crate rustc_index;
|
||||
|
|
@ -105,8 +104,6 @@ use tempfile::TempDir;
|
|||
use crate::back::lto::ModuleBuffer;
|
||||
use crate::gcc_util::{target_cpu, to_gcc_features};
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
|
||||
|
||||
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
|
||||
|
|
@ -197,10 +194,6 @@ fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) {
|
|||
}
|
||||
|
||||
impl CodegenBackend for GccCodegenBackend {
|
||||
fn locale_resource(&self) -> &'static str {
|
||||
crate::DEFAULT_LOCALE_RESOURCE
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"gcc"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ rustc_ast = { path = "../rustc_ast" }
|
|||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_fs_util = { path = "../rustc_fs_util" }
|
||||
rustc_hashes = { path = "../rustc_hashes" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
codegen_llvm_autodiff_component_missing = autodiff backend not found in the sysroot: {$err}
|
||||
.note = it will be distributed via rustup in the future
|
||||
|
||||
codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend: {$err}
|
||||
|
||||
codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable
|
||||
codegen_llvm_autodiff_without_lto = using the autodiff feature requires setting `lto="fat"` in your Cargo.toml
|
||||
|
||||
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
|
||||
|
||||
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
|
||||
|
||||
codegen_llvm_from_llvm_diag = {$message}
|
||||
|
||||
codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
|
||||
|
||||
codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
|
||||
codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
|
||||
|
||||
codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$err})
|
||||
|
||||
codegen_llvm_mismatch_data_layout =
|
||||
data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
|
||||
|
||||
codegen_llvm_offload_bundleimages_failed = call to BundleImages failed, `host.out` was not created
|
||||
codegen_llvm_offload_embed_failed = call to EmbedBufferInModule failed, `host.o` was not created
|
||||
codegen_llvm_offload_no_abs_path = using the `-Z offload=Host=/absolute/path/to/host.out` flag requires an absolute path
|
||||
codegen_llvm_offload_no_host_out = using the `-Z offload=Host=/absolute/path/to/host.out` flag must point to a `host.out` file
|
||||
codegen_llvm_offload_nonexisting = the given path/file to `host.out` does not exist. Did you forget to run the device compilation first?
|
||||
codegen_llvm_offload_without_enable = using the offload feature requires -Z offload=<Device or Host=/absolute/path/to/host.out>
|
||||
codegen_llvm_offload_without_fat_lto = using the offload feature requires -C lto=fat
|
||||
|
||||
codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
|
||||
codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
|
||||
|
||||
codegen_llvm_parse_target_machine_config =
|
||||
failed to parse target machine config to target machine: {$error}
|
||||
|
||||
codegen_llvm_prepare_autodiff = failed to prepare autodiff: src: {$src}, target: {$target}, {$error}
|
||||
codegen_llvm_prepare_autodiff_with_llvm_err = failed to prepare autodiff: {$llvm_err}, src: {$src}, target: {$target}, {$error}
|
||||
codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
|
||||
codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
|
||||
|
||||
codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
|
||||
codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
|
||||
|
||||
codegen_llvm_run_passes = failed to run LLVM passes
|
||||
codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
|
||||
|
||||
codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0 = `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.
|
||||
|
||||
codegen_llvm_sanitizer_memtag_requires_mte =
|
||||
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
|
||||
|
||||
codegen_llvm_serialize_module = failed to serialize module {$name}
|
||||
codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
|
||||
|
||||
codegen_llvm_symbol_already_defined =
|
||||
symbol `{$symbol_name}` is already defined
|
||||
|
||||
codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
|
||||
codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
|
||||
|
||||
codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo
|
||||
|
||||
codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
|
||||
|
||||
codegen_llvm_write_ir = failed to write LLVM IR to {$path}
|
||||
codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
|
||||
|
||||
codegen_llvm_write_output = could not write output to {$path}
|
||||
codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
|
||||
|
||||
codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
|
||||
codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
|
||||
|
|
@ -2,14 +2,12 @@ use std::ffi::CString;
|
|||
use std::path::Path;
|
||||
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, inline_fluent};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_symbol_already_defined)]
|
||||
#[diag("symbol `{$symbol_name}` is already defined")]
|
||||
pub(crate) struct SymbolAlreadyDefined<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -17,7 +15,7 @@ pub(crate) struct SymbolAlreadyDefined<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||
#[diag("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`")]
|
||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
||||
|
||||
pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
|
||||
|
|
@ -27,89 +25,97 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
|
|||
let diag: Diag<'_, G> = self.0.into_diag(dcx, level);
|
||||
let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
|
||||
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter());
|
||||
Diag::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
|
||||
.with_arg("error", message)
|
||||
Diag::new(
|
||||
dcx,
|
||||
level,
|
||||
inline_fluent!("failed to parse target machine config to target machine: {$error}"),
|
||||
)
|
||||
.with_arg("error", message)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_autodiff_component_unavailable)]
|
||||
#[diag("failed to load our autodiff backend: {$err}")]
|
||||
pub(crate) struct AutoDiffComponentUnavailable {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_autodiff_component_missing)]
|
||||
#[note]
|
||||
#[diag("autodiff backend not found in the sysroot: {$err}")]
|
||||
#[note("it will be distributed via rustup in the future")]
|
||||
pub(crate) struct AutoDiffComponentMissing {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_autodiff_without_lto)]
|
||||
#[diag("using the autodiff feature requires setting `lto=\"fat\"` in your Cargo.toml")]
|
||||
pub(crate) struct AutoDiffWithoutLto;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_autodiff_without_enable)]
|
||||
#[diag("using the autodiff feature requires -Z autodiff=Enable")]
|
||||
pub(crate) struct AutoDiffWithoutEnable;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_without_enable)]
|
||||
#[diag("using the offload feature requires -Z offload=<Device or Host=/absolute/path/to/host.out>")]
|
||||
pub(crate) struct OffloadWithoutEnable;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_without_fat_lto)]
|
||||
#[diag("using the offload feature requires -C lto=fat")]
|
||||
pub(crate) struct OffloadWithoutFatLTO;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_no_abs_path)]
|
||||
#[diag("using the `-Z offload=Host=/absolute/path/to/host.out` flag requires an absolute path")]
|
||||
pub(crate) struct OffloadWithoutAbsPath;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_no_host_out)]
|
||||
#[diag(
|
||||
"using the `-Z offload=Host=/absolute/path/to/host.out` flag must point to a `host.out` file"
|
||||
)]
|
||||
pub(crate) struct OffloadWrongFileName;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_nonexisting)]
|
||||
#[diag(
|
||||
"the given path/file to `host.out` does not exist. Did you forget to run the device compilation first?"
|
||||
)]
|
||||
pub(crate) struct OffloadNonexistingPath;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_bundleimages_failed)]
|
||||
#[diag("call to BundleImages failed, `host.out` was not created")]
|
||||
pub(crate) struct OffloadBundleImagesFailed;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_offload_embed_failed)]
|
||||
#[diag("call to EmbedBufferInModule failed, `host.o` was not created")]
|
||||
pub(crate) struct OffloadEmbedFailed;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_lto_bitcode_from_rlib)]
|
||||
#[diag("failed to get bitcode from object file for LTO ({$err})")]
|
||||
pub(crate) struct LtoBitcodeFromRlib {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum LlvmError<'a> {
|
||||
#[diag(codegen_llvm_write_output)]
|
||||
#[diag("could not write output to {$path}")]
|
||||
WriteOutput { path: &'a Path },
|
||||
#[diag(codegen_llvm_target_machine)]
|
||||
#[diag("could not create LLVM TargetMachine for triple: {$triple}")]
|
||||
CreateTargetMachine { triple: SmallCStr },
|
||||
#[diag(codegen_llvm_run_passes)]
|
||||
#[diag("failed to run LLVM passes")]
|
||||
RunLlvmPasses,
|
||||
#[diag(codegen_llvm_serialize_module)]
|
||||
#[diag("failed to serialize module {$name}")]
|
||||
SerializeModule { name: &'a str },
|
||||
#[diag(codegen_llvm_write_ir)]
|
||||
#[diag("failed to write LLVM IR to {$path}")]
|
||||
WriteIr { path: &'a Path },
|
||||
#[diag(codegen_llvm_prepare_thin_lto_context)]
|
||||
#[diag("failed to prepare thin LTO context")]
|
||||
PrepareThinLtoContext,
|
||||
#[diag(codegen_llvm_load_bitcode)]
|
||||
#[diag("failed to load bitcode of module \"{$name}\"")]
|
||||
LoadBitcode { name: CString },
|
||||
#[diag(codegen_llvm_write_thinlto_key)]
|
||||
#[diag("error while writing ThinLTO key data: {$err}")]
|
||||
WriteThinLtoKey { err: std::io::Error },
|
||||
#[diag(codegen_llvm_prepare_thin_lto_module)]
|
||||
#[diag("failed to prepare thin LTO module")]
|
||||
PrepareThinLtoModule,
|
||||
#[diag(codegen_llvm_parse_bitcode)]
|
||||
#[diag("failed to parse bitcode for LTO module")]
|
||||
ParseBitcode,
|
||||
#[diag(codegen_llvm_prepare_autodiff)]
|
||||
#[diag("failed to prepare autodiff: src: {$src}, target: {$target}, {$error}")]
|
||||
PrepareAutoDiff { src: String, target: String, error: String },
|
||||
}
|
||||
|
||||
|
|
@ -119,17 +125,31 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for WithLlvmError<'_> {
|
|||
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
|
||||
use LlvmError::*;
|
||||
let msg_with_llvm_err = match &self.0 {
|
||||
WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err,
|
||||
CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err,
|
||||
RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err,
|
||||
SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err,
|
||||
WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err,
|
||||
PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err,
|
||||
LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err,
|
||||
WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err,
|
||||
PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
|
||||
ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
|
||||
PrepareAutoDiff { .. } => fluent::codegen_llvm_prepare_autodiff_with_llvm_err,
|
||||
WriteOutput { .. } => inline_fluent!("could not write output to {$path}: {$llvm_err}"),
|
||||
CreateTargetMachine { .. } => inline_fluent!(
|
||||
"could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}"
|
||||
),
|
||||
RunLlvmPasses => inline_fluent!("failed to run LLVM passes: {$llvm_err}"),
|
||||
SerializeModule { .. } => {
|
||||
inline_fluent!("failed to serialize module {$name}: {$llvm_err}")
|
||||
}
|
||||
WriteIr { .. } => inline_fluent!("failed to write LLVM IR to {$path}: {$llvm_err}"),
|
||||
PrepareThinLtoContext => {
|
||||
inline_fluent!("failed to prepare thin LTO context: {$llvm_err}")
|
||||
}
|
||||
LoadBitcode { .. } => {
|
||||
inline_fluent!("failed to load bitcode of module \"{$name}\": {$llvm_err}")
|
||||
}
|
||||
WriteThinLtoKey { .. } => {
|
||||
inline_fluent!("error while writing ThinLTO key data: {$err}: {$llvm_err}")
|
||||
}
|
||||
PrepareThinLtoModule => {
|
||||
inline_fluent!("failed to prepare thin LTO module: {$llvm_err}")
|
||||
}
|
||||
ParseBitcode => inline_fluent!("failed to parse bitcode for LTO module: {$llvm_err}"),
|
||||
PrepareAutoDiff { .. } => inline_fluent!(
|
||||
"failed to prepare autodiff: {$llvm_err}, src: {$src}, target: {$target}, {$error}"
|
||||
),
|
||||
};
|
||||
self.0
|
||||
.into_diag(dcx, level)
|
||||
|
|
@ -139,7 +159,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for WithLlvmError<'_> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_from_llvm_optimization_diag)]
|
||||
#[diag("{$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}")]
|
||||
pub(crate) struct FromLlvmOptimizationDiag<'a> {
|
||||
pub filename: &'a str,
|
||||
pub line: std::ffi::c_uint,
|
||||
|
|
@ -150,32 +170,36 @@ pub(crate) struct FromLlvmOptimizationDiag<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_from_llvm_diag)]
|
||||
#[diag("{$message}")]
|
||||
pub(crate) struct FromLlvmDiag {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_write_bytecode)]
|
||||
#[diag("failed to write bytecode to {$path}: {$err}")]
|
||||
pub(crate) struct WriteBytecode<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_copy_bitcode)]
|
||||
#[diag("failed to copy bitcode to object file: {$err}")]
|
||||
pub(crate) struct CopyBitcode {
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_debuginfo_compression)]
|
||||
#[diag(
|
||||
"unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo"
|
||||
)]
|
||||
pub(crate) struct UnknownCompression {
|
||||
pub algorithm: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_mismatch_data_layout)]
|
||||
#[diag(
|
||||
"data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`"
|
||||
)]
|
||||
pub(crate) struct MismatchedDataLayout<'a> {
|
||||
pub rustc_target: &'a str,
|
||||
pub rustc_layout: &'a str,
|
||||
|
|
@ -184,11 +208,11 @@ pub(crate) struct MismatchedDataLayout<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_fixed_x18_invalid_arch)]
|
||||
#[diag("the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture")]
|
||||
pub(crate) struct FixedX18InvalidArch<'a> {
|
||||
pub arch: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0)]
|
||||
#[diag("`-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.")]
|
||||
pub(crate) struct SanitizerKcfiArityRequiresLLVM2100;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_middle::util::Providers;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_target::spec::{RelocModel, TlsModel};
|
||||
|
||||
use crate::llvm::ToLlvmBool;
|
||||
|
|
@ -74,8 +74,6 @@ mod typetree;
|
|||
mod va_arg;
|
||||
mod value;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub(crate) use macros::TryFromU32;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -241,10 +239,6 @@ impl LlvmCodegenBackend {
|
|||
}
|
||||
|
||||
impl CodegenBackend for LlvmCodegenBackend {
|
||||
fn locale_resource(&self) -> &'static str {
|
||||
crate::DEFAULT_LOCALE_RESOURCE
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"llvm"
|
||||
}
|
||||
|
|
@ -350,6 +344,10 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
target_config(sess)
|
||||
}
|
||||
|
||||
fn replaced_intrinsics(&self) -> Vec<Symbol> {
|
||||
vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add]
|
||||
}
|
||||
|
||||
fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any> {
|
||||
Box::new(rustc_codegen_ssa::base::codegen_crate(
|
||||
LlvmCodegenBackend(()),
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ rustc_lint_defs = { path = "../rustc_lint_defs" }
|
|||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_metadata = { path = "../rustc_metadata" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ use std::{env, fmt, fs, io, mem, str};
|
|||
|
||||
use find_msvc_tools;
|
||||
use itertools::Itertools;
|
||||
use object::{Object, ObjectSection, ObjectSymbol};
|
||||
use regex::Regex;
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_attr_parsing::eval_config_entry;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
|
||||
|
|
@ -2185,6 +2186,71 @@ fn add_rpath_args(
|
|||
}
|
||||
}
|
||||
|
||||
fn add_c_staticlib_symbols(
|
||||
sess: &Session,
|
||||
lib: &NativeLib,
|
||||
out: &mut Vec<(String, SymbolExportKind)>,
|
||||
) -> io::Result<()> {
|
||||
let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);
|
||||
|
||||
let archive_map = unsafe { Mmap::map(File::open(&file_path)?)? };
|
||||
|
||||
let archive = object::read::archive::ArchiveFile::parse(&*archive_map)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
for member in archive.members() {
|
||||
let member = member.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
let data = member
|
||||
.data(&*archive_map)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
// clang LTO: raw LLVM bitcode
|
||||
if data.starts_with(b"BC\xc0\xde") {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"LLVM bitcode object in C static library (LTO not supported)",
|
||||
));
|
||||
}
|
||||
|
||||
let object = object::File::parse(&*data)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
// gcc / clang ELF / Mach-O LTO
|
||||
if object.sections().any(|s| {
|
||||
s.name().map(|n| n.starts_with(".gnu.lto_") || n == ".llvm.lto").unwrap_or(false)
|
||||
}) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"LTO object in C static library is not supported",
|
||||
));
|
||||
}
|
||||
|
||||
for symbol in object.symbols() {
|
||||
if symbol.scope() != object::SymbolScope::Dynamic {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = match symbol.name() {
|
||||
Ok(n) => n,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let export_kind = match symbol.kind() {
|
||||
object::SymbolKind::Text => SymbolExportKind::Text,
|
||||
object::SymbolKind::Data => SymbolExportKind::Data,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
// FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple.
|
||||
// Need to be resolved.
|
||||
out.push((name.to_string(), export_kind));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Produce the linker command line containing linker path and arguments.
|
||||
///
|
||||
/// When comments in the function say "order-(in)dependent" they mean order-dependence between
|
||||
|
|
@ -2217,6 +2283,25 @@ fn linker_with_args(
|
|||
);
|
||||
let link_output_kind = link_output_kind(sess, crate_type);
|
||||
|
||||
let mut export_symbols = codegen_results.crate_info.exported_symbols[&crate_type].clone();
|
||||
|
||||
if crate_type == CrateType::Cdylib {
|
||||
let mut seen = FxHashSet::default();
|
||||
|
||||
for lib in &codegen_results.crate_info.used_libraries {
|
||||
if let NativeLibKind::Static { export_symbols: Some(true), .. } = lib.kind
|
||||
&& seen.insert((lib.name, lib.verbatim))
|
||||
{
|
||||
if let Err(err) = add_c_staticlib_symbols(&sess, lib, &mut export_symbols) {
|
||||
sess.dcx().fatal(format!(
|
||||
"failed to process C static library `{}`: {}",
|
||||
lib.name, err
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------ Early order-dependent options ------------
|
||||
|
||||
// If we're building something like a dynamic library then some platforms
|
||||
|
|
@ -2224,11 +2309,7 @@ fn linker_with_args(
|
|||
// dynamic library.
|
||||
// Must be passed before any libraries to prevent the symbols to export from being thrown away,
|
||||
// at least on some platforms (e.g. windows-gnu).
|
||||
cmd.export_symbols(
|
||||
tmpdir,
|
||||
crate_type,
|
||||
&codegen_results.crate_info.exported_symbols[&crate_type],
|
||||
);
|
||||
cmd.export_symbols(tmpdir, crate_type, &export_symbols);
|
||||
|
||||
// Can be used for adding custom CRT objects or overriding order-dependent options above.
|
||||
// FIXME: In practice built-in target specs use this for arbitrary order-independent options,
|
||||
|
|
@ -2678,7 +2759,7 @@ fn add_native_libs_from_crate(
|
|||
let name = lib.name.as_str();
|
||||
let verbatim = lib.verbatim;
|
||||
match lib.kind {
|
||||
NativeLibKind::Static { bundle, whole_archive } => {
|
||||
NativeLibKind::Static { bundle, whole_archive, .. } => {
|
||||
if link_static {
|
||||
let bundle = bundle.unwrap_or(true);
|
||||
let whole_archive = whole_archive == Some(true);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use rustc_data_structures::unord::UnordMap;
|
|||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_hir::attrs::{CfgEntry, NativeLibKind, WindowsSubsystemKind};
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::WorkProduct;
|
||||
use rustc_middle::lint::LevelAndSource;
|
||||
|
|
@ -175,7 +175,12 @@ bitflags::bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
|
||||
// This is the same as `rustc_session::cstore::NativeLib`, except:
|
||||
// - (important) the `foreign_module` field is missing, because it contains a `DefId`, which can't
|
||||
// be encoded with `FileEncoder`.
|
||||
// - (less important) the `verbatim` field is a `bool` rather than an `Option<bool>`, because here
|
||||
// we can treat `false` and `absent` the same.
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
pub struct NativeLib {
|
||||
pub kind: NativeLibKind,
|
||||
pub name: Symbol,
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ pub trait BackendTypes {
|
|||
}
|
||||
|
||||
pub trait CodegenBackend {
|
||||
/// Locale resources for diagnostic messages - a string the content of the Fluent resource.
|
||||
/// Called before `init` so that all other functions are able to emit translatable diagnostics.
|
||||
fn locale_resource(&self) -> &'static str;
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
fn init(&self, _sess: &Session) {}
|
||||
|
|
@ -78,6 +74,12 @@ pub trait CodegenBackend {
|
|||
|
||||
fn print_version(&self) {}
|
||||
|
||||
/// Returns a list of all intrinsics that this backend definitely
|
||||
/// replaces, which means their fallback bodies do not need to be monomorphized.
|
||||
fn replaced_intrinsics(&self) -> Vec<Symbol> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
/// Value printed by `--print=backend-has-zstd`.
|
||||
///
|
||||
/// Used by compiletest to determine whether tests involving zstd compression
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
use either::{Either, Left, Right};
|
||||
use rustc_abi::{BackendRepr, HasDataLayout, Size};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::{bug, mir, span_bug};
|
||||
use tracing::field::Empty;
|
||||
use tracing::{instrument, trace};
|
||||
|
|
@ -884,10 +884,38 @@ where
|
|||
dest.layout().ty,
|
||||
);
|
||||
}
|
||||
// If the source has padding, we want to always do a mem-to-mem copy to ensure consistent
|
||||
// padding in the target independent of layout choices.
|
||||
let src_has_padding = match src.layout().backend_repr {
|
||||
BackendRepr::Scalar(_) => false,
|
||||
BackendRepr::ScalarPair(left, right)
|
||||
if matches!(src.layout().ty.kind(), ty::Ref(..) | ty::RawPtr(..)) =>
|
||||
{
|
||||
// Wide pointers never have padding, so we can avoid calling `size()`.
|
||||
debug_assert_eq!(left.size(self) + right.size(self), src.layout().size);
|
||||
false
|
||||
}
|
||||
BackendRepr::ScalarPair(left, right) => {
|
||||
let left_size = left.size(self);
|
||||
let right_size = right.size(self);
|
||||
// We have padding if the sizes don't add up to the total.
|
||||
left_size + right_size != src.layout().size
|
||||
}
|
||||
// Everything else can only exist in memory anyway, so it doesn't matter.
|
||||
BackendRepr::SimdVector { .. }
|
||||
| BackendRepr::ScalableVector { .. }
|
||||
| BackendRepr::Memory { .. } => true,
|
||||
};
|
||||
|
||||
// Let us see if the layout is simple so we take a shortcut,
|
||||
// avoid force_allocation.
|
||||
let src = match self.read_immediate_raw(src)? {
|
||||
let src_val = if src_has_padding {
|
||||
// Do our best to get an mplace. If there's no mplace, then this is stored as an
|
||||
// "optimized" local, so its padding is definitely uninitialized and we are fine.
|
||||
src.to_op(self)?.as_mplace_or_imm()
|
||||
} else {
|
||||
// Do our best to get an immediate, to avoid having to force_allocate the destination.
|
||||
self.read_immediate_raw(src)?
|
||||
};
|
||||
let src = match src_val {
|
||||
Right(src_val) => {
|
||||
assert!(!src.layout().is_unsized());
|
||||
assert!(!dest.layout().is_unsized());
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug {
|
|||
}
|
||||
|
||||
/// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for
|
||||
/// reading from this thing.
|
||||
/// reading from this thing. This will never actually do a read from memory!
|
||||
fn to_op<M: Machine<'tcx, Provenance = Prov>>(
|
||||
&self,
|
||||
ecx: &InterpCx<'tcx, M>,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ pub use std::{assert_matches, debug_assert_matches};
|
|||
|
||||
pub use atomic_ref::AtomicRef;
|
||||
pub use ena::{snapshot_vec, undo_log, unify};
|
||||
// Re-export `hashbrown::hash_table`, because it's part of our API
|
||||
// (via `ShardedHashMap`), and because it lets other compiler crates use the
|
||||
// lower-level `HashTable` API without a tricky `hashbrown` dependency.
|
||||
pub use hashbrown::hash_table;
|
||||
pub use rustc_index::static_assert_size;
|
||||
// Re-export some data-structure crates which are part of our public API.
|
||||
pub use {either, indexmap, smallvec, thin_vec};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher};
|
|||
use std::{iter, mem};
|
||||
|
||||
use either::Either;
|
||||
use hashbrown::hash_table::{Entry, HashTable};
|
||||
use hashbrown::hash_table::{self, Entry, HashTable};
|
||||
|
||||
use crate::fx::FxHasher;
|
||||
use crate::sync::{CacheAligned, Lock, LockGuard, Mode, is_dyn_thread_safe};
|
||||
|
|
@ -140,7 +140,7 @@ pub fn shards() -> usize {
|
|||
1
|
||||
}
|
||||
|
||||
pub type ShardedHashMap<K, V> = Sharded<HashTable<(K, V)>>;
|
||||
pub type ShardedHashMap<K, V> = Sharded<hash_table::HashTable<(K, V)>>;
|
||||
|
||||
impl<K: Eq, V> ShardedHashMap<K, V> {
|
||||
pub fn with_capacity(cap: usize) -> Self {
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ struct Slot<V> {
|
|||
struct SlotIndex {
|
||||
// the index of the bucket in VecCache (0 to 20)
|
||||
bucket_idx: usize,
|
||||
// number of entries in that bucket
|
||||
entries: usize,
|
||||
// the index of the slot within the bucket
|
||||
index_in_bucket: usize,
|
||||
}
|
||||
|
|
@ -39,12 +37,12 @@ struct SlotIndex {
|
|||
// compile-time. Visiting all powers of two is enough to hit all the buckets.
|
||||
//
|
||||
// We confirm counts are accurate in the slot_index_exhaustive test.
|
||||
const ENTRIES_BY_BUCKET: [usize; 21] = {
|
||||
let mut entries = [0; 21];
|
||||
const ENTRIES_BY_BUCKET: [usize; BUCKETS] = {
|
||||
let mut entries = [0; BUCKETS];
|
||||
let mut key = 0;
|
||||
loop {
|
||||
let si = SlotIndex::from_index(key);
|
||||
entries[si.bucket_idx] = si.entries;
|
||||
entries[si.bucket_idx] = si.entries();
|
||||
if key == 0 {
|
||||
key = 1;
|
||||
} else if key == (1 << 31) {
|
||||
|
|
@ -56,7 +54,14 @@ const ENTRIES_BY_BUCKET: [usize; 21] = {
|
|||
entries
|
||||
};
|
||||
|
||||
const BUCKETS: usize = 21;
|
||||
|
||||
impl SlotIndex {
|
||||
/// The total possible number of entries in the bucket
|
||||
const fn entries(&self) -> usize {
|
||||
if self.bucket_idx == 0 { 1 << 12 } else { 1 << (self.bucket_idx + 11) }
|
||||
}
|
||||
|
||||
// This unpacks a flat u32 index into identifying which bucket it belongs to and the offset
|
||||
// within that bucket. As noted in the VecCache docs, buckets double in size with each index.
|
||||
// Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce
|
||||
|
|
@ -70,18 +75,13 @@ impl SlotIndex {
|
|||
const fn from_index(idx: u32) -> Self {
|
||||
const FIRST_BUCKET_SHIFT: usize = 12;
|
||||
if idx < (1 << FIRST_BUCKET_SHIFT) {
|
||||
return SlotIndex {
|
||||
bucket_idx: 0,
|
||||
entries: 1 << FIRST_BUCKET_SHIFT,
|
||||
index_in_bucket: idx as usize,
|
||||
};
|
||||
return SlotIndex { bucket_idx: 0, index_in_bucket: idx as usize };
|
||||
}
|
||||
// We already ruled out idx 0, so this `ilog2` never panics (and the check optimizes away)
|
||||
let bucket = idx.ilog2() as usize;
|
||||
let entries = 1 << bucket;
|
||||
SlotIndex {
|
||||
bucket_idx: bucket - FIRST_BUCKET_SHIFT + 1,
|
||||
entries,
|
||||
index_in_bucket: idx as usize - entries,
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ impl SlotIndex {
|
|||
if ptr.is_null() {
|
||||
return None;
|
||||
}
|
||||
assert!(self.index_in_bucket < self.entries);
|
||||
debug_assert!(self.index_in_bucket < self.entries());
|
||||
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
|
||||
// must be inbounds.
|
||||
let slot = unsafe { ptr.add(self.index_in_bucket) };
|
||||
|
|
@ -126,11 +126,12 @@ impl SlotIndex {
|
|||
|
||||
fn bucket_ptr<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
|
||||
let ptr = bucket.load(Ordering::Acquire);
|
||||
if ptr.is_null() { self.initialize_bucket(bucket) } else { ptr }
|
||||
if ptr.is_null() { Self::initialize_bucket(bucket, self.bucket_idx) } else { ptr }
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn initialize_bucket<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
|
||||
#[inline(never)]
|
||||
fn initialize_bucket<V>(bucket: &AtomicPtr<Slot<V>>, bucket_idx: usize) -> *mut Slot<V> {
|
||||
static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
||||
|
||||
// If we are initializing the bucket, then acquire a global lock.
|
||||
|
|
@ -144,8 +145,8 @@ impl SlotIndex {
|
|||
// OK, now under the allocator lock, if we're still null then it's definitely us that will
|
||||
// initialize this bucket.
|
||||
if ptr.is_null() {
|
||||
let bucket_layout =
|
||||
std::alloc::Layout::array::<Slot<V>>(self.entries as usize).unwrap();
|
||||
let bucket_len = SlotIndex { bucket_idx, index_in_bucket: 0 }.entries();
|
||||
let bucket_layout = std::alloc::Layout::array::<Slot<V>>(bucket_len).unwrap();
|
||||
// This is more of a sanity check -- this code is very cold, so it's safe to pay a
|
||||
// little extra cost here.
|
||||
assert!(bucket_layout.size() > 0);
|
||||
|
|
@ -171,7 +172,7 @@ impl SlotIndex {
|
|||
let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
|
||||
let ptr = self.bucket_ptr(bucket);
|
||||
|
||||
assert!(self.index_in_bucket < self.entries);
|
||||
debug_assert!(self.index_in_bucket < self.entries());
|
||||
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
|
||||
// must be inbounds.
|
||||
let slot = unsafe { ptr.add(self.index_in_bucket) };
|
||||
|
|
@ -204,6 +205,31 @@ impl SlotIndex {
|
|||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts into the map, given that the slot is unique, so it won't race with other threads.
|
||||
#[inline]
|
||||
unsafe fn put_unique<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21], value: V, extra: u32) {
|
||||
// SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
|
||||
// in-bounds of buckets.
|
||||
let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
|
||||
let ptr = self.bucket_ptr(bucket);
|
||||
|
||||
debug_assert!(self.index_in_bucket < self.entries());
|
||||
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
|
||||
// must be inbounds.
|
||||
let slot = unsafe { ptr.add(self.index_in_bucket) };
|
||||
|
||||
// SAFETY: We known our slot is unique as a precondition of this function, so this can't race.
|
||||
unsafe {
|
||||
(&raw mut (*slot).value).write(value);
|
||||
}
|
||||
|
||||
// SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
|
||||
// AtomicU32 access.
|
||||
let index_and_lock = unsafe { &(*slot).index_and_lock };
|
||||
|
||||
index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
/// In-memory cache for queries whose keys are densely-numbered IDs
|
||||
|
|
@ -229,11 +255,11 @@ pub struct VecCache<K: Idx, V, I> {
|
|||
// Bucket 19: 1073741824
|
||||
// Bucket 20: 2147483648
|
||||
// The total number of entries if all buckets are initialized is u32::MAX-1.
|
||||
buckets: [AtomicPtr<Slot<V>>; 21],
|
||||
buckets: [AtomicPtr<Slot<V>>; BUCKETS],
|
||||
|
||||
// In the compiler's current usage these are only *read* during incremental and self-profiling.
|
||||
// They are an optimization over iterating the full buckets array.
|
||||
present: [AtomicPtr<Slot<()>>; 21],
|
||||
present: [AtomicPtr<Slot<()>>; BUCKETS],
|
||||
len: AtomicUsize,
|
||||
|
||||
key: PhantomData<(K, I)>,
|
||||
|
|
@ -307,9 +333,11 @@ where
|
|||
let slot_idx = SlotIndex::from_index(key);
|
||||
if slot_idx.put(&self.buckets, value, index.index() as u32) {
|
||||
let present_idx = self.len.fetch_add(1, Ordering::Relaxed);
|
||||
let slot = SlotIndex::from_index(present_idx as u32);
|
||||
// We should always be uniquely putting due to `len` fetch_add returning unique values.
|
||||
assert!(slot.put(&self.present, (), key));
|
||||
let slot = SlotIndex::from_index(u32::try_from(present_idx).unwrap());
|
||||
// SAFETY: We should always be uniquely putting due to `len` fetch_add returning unique values.
|
||||
// We can't get here if `len` overflows because `put` will not succeed u32::MAX + 1 times
|
||||
// as it will run out of slots.
|
||||
unsafe { slot.put_unique(&self.present, (), key) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,6 +359,10 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.len.load(Ordering::Acquire)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -68,6 +68,13 @@ fn slot_entries_table() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bucket_entries_matches() {
|
||||
for i in 0..BUCKETS {
|
||||
assert_eq!(SlotIndex { bucket_idx: i, index_in_bucket: 0 }.entries(), ENTRIES_BY_BUCKET[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
fn slot_index_exhaustive() {
|
||||
|
|
@ -81,14 +88,18 @@ fn slot_index_exhaustive() {
|
|||
let mut prev = slot_idx;
|
||||
for idx in 1..=u32::MAX {
|
||||
let slot_idx = SlotIndex::from_index(idx);
|
||||
|
||||
// SAFETY: Ensure indices don't go out of bounds of buckets.
|
||||
assert!(slot_idx.index_in_bucket < slot_idx.entries());
|
||||
|
||||
if prev.bucket_idx == slot_idx.bucket_idx {
|
||||
assert_eq!(prev.index_in_bucket + 1, slot_idx.index_in_bucket);
|
||||
} else {
|
||||
assert_eq!(slot_idx.index_in_bucket, 0);
|
||||
}
|
||||
|
||||
assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries as u32);
|
||||
assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries, "{}", idx);
|
||||
assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries() as u32);
|
||||
assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries(), "{}", idx);
|
||||
|
||||
prev = slot_idx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ rustc_ast = { path = "../rustc_ast" }
|
|||
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
|
||||
rustc_ast_passes = { path = "../rustc_ast_passes" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_borrowck = { path = "../rustc_borrowck" }
|
||||
rustc_builtin_macros = { path = "../rustc_builtin_macros" }
|
||||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
|
|
@ -21,13 +20,10 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
|||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
|
||||
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||
rustc_hir_typeck = { path = "../rustc_hir_typeck" }
|
||||
rustc_incremental = { path = "../rustc_incremental" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_interface = { path = "../rustc_interface" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_lint = { path = "../rustc_lint" }
|
||||
|
|
@ -36,21 +32,16 @@ rustc_macros = { path = "../rustc_macros" }
|
|||
rustc_metadata = { path = "../rustc_metadata" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_mir_build = { path = "../rustc_mir_build" }
|
||||
rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
|
||||
rustc_mir_transform = { path = "../rustc_mir_transform" }
|
||||
rustc_monomorphize = { path = "../rustc_monomorphize" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_passes = { path = "../rustc_passes" }
|
||||
rustc_pattern_analysis = { path = "../rustc_pattern_analysis" }
|
||||
rustc_privacy = { path = "../rustc_privacy" }
|
||||
rustc_public = { path = "../rustc_public", features = ["rustc_internal"] }
|
||||
rustc_query_system = { path = "../rustc_query_system" }
|
||||
rustc_resolve = { path = "../rustc_resolve" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||
serde_json = "1.0.59"
|
||||
shlex = "1.0"
|
||||
tracing = { version = "0.1.35" }
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
driver_impl_cant_emit_mir = could not emit MIR: {$error}
|
||||
|
||||
driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
|
||||
driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
||||
driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
|
||||
driver_impl_ice_bug_report_update_note = please make sure that you have updated to the latest nightly
|
||||
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||
|
||||
driver_impl_ice_flags = compiler flags: {$flags}
|
||||
driver_impl_ice_path = please attach the file at `{$path}` to your bug report
|
||||
driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error}
|
||||
driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}`
|
||||
driver_impl_ice_version = rustc {$version} running on {$triple}
|
||||
|
||||
driver_impl_rlink_corrupt_file = corrupt metadata encountered in `{$file}`
|
||||
|
||||
driver_impl_rlink_empty_version_number = the input does not contain version number
|
||||
|
||||
driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
|
||||
|
||||
driver_impl_rlink_no_a_file = rlink must be a file
|
||||
|
||||
driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
|
||||
|
||||
driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
|
||||
|
||||
driver_impl_rlink_wrong_file_type = the input does not look like a .rlink file
|
||||
|
||||
driver_impl_unstable_feature_usage = cannot dump feature usage metrics: {$error}
|
||||
|
|
@ -108,18 +108,14 @@ use crate::session_diagnostics::{
|
|||
RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage,
|
||||
};
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub fn default_translator() -> Translator {
|
||||
Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false)
|
||||
}
|
||||
|
||||
pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
||||
// tidy-alphabetical-start
|
||||
crate::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_ast_passes::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_attr_parsing::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_borrowck::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE,
|
||||
|
|
@ -128,25 +124,16 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
|||
rustc_expand::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_incremental::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_infer::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_interface::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_lint::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_metadata::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_middle::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_mir_build::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_mir_dataflow::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_mir_transform::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_monomorphize::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_parse::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_passes::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_privacy::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_query_system::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_resolve::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_session::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_trait_selection::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_ty_utils::DEFAULT_LOCALE_RESOURCE,
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
||||
|
|
@ -491,10 +478,18 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col
|
|||
}
|
||||
text.push('\n');
|
||||
}
|
||||
|
||||
// If output is a terminal, use a pager to display the content.
|
||||
if io::stdout().is_terminal() {
|
||||
show_md_content_with_pager(&text, color);
|
||||
} else {
|
||||
safe_print!("{text}");
|
||||
// Otherwise, if the user has requested colored output
|
||||
// print the content in color, else print the md content.
|
||||
if color == ColorConfig::Always {
|
||||
show_colored_md_content(&text);
|
||||
} else {
|
||||
safe_print!("{text}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
early_dcx.early_fatal(format!("{code} is not a valid error code"));
|
||||
|
|
@ -564,6 +559,33 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
|
|||
safe_print!("{content}");
|
||||
}
|
||||
|
||||
/// Prints the markdown content with colored output.
|
||||
///
|
||||
/// This function is used when the output is not a terminal,
|
||||
/// but the user has requested colored output with `--color=always`.
|
||||
fn show_colored_md_content(content: &str) {
|
||||
// Try to prettify the raw markdown text.
|
||||
let mut pretty_data = {
|
||||
let mdstream = markdown::MdStream::parse_str(content);
|
||||
let bufwtr = markdown::create_stdout_bufwtr();
|
||||
let mut mdbuf = Vec::new();
|
||||
if mdstream.write_anstream_buf(&mut mdbuf, Some(&highlighter::highlight)).is_ok() {
|
||||
Some((bufwtr, mdbuf))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((bufwtr, mdbuf)) = &mut pretty_data
|
||||
&& bufwtr.write_all(&mdbuf).is_ok()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Everything failed. Print the raw markdown text.
|
||||
safe_print!("{content}");
|
||||
}
|
||||
|
||||
fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
|
||||
assert!(sess.opts.unstable_opts.link_only);
|
||||
let dcx = sess.dcx();
|
||||
|
|
|
|||
|
|
@ -3,82 +3,88 @@ use std::error::Error;
|
|||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_cant_emit_mir)]
|
||||
#[diag("could not emit MIR: {$error}")]
|
||||
pub struct CantEmitMIR {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_unable_to_read)]
|
||||
#[diag("failed to read rlink file: `{$err}`")]
|
||||
pub(crate) struct RlinkUnableToRead {
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_wrong_file_type)]
|
||||
#[diag("the input does not look like a .rlink file")]
|
||||
pub(crate) struct RLinkWrongFileType;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_empty_version_number)]
|
||||
#[diag("the input does not contain version number")]
|
||||
pub(crate) struct RLinkEmptyVersionNumber;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_encoding_version_mismatch)]
|
||||
#[diag(
|
||||
".rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`"
|
||||
)]
|
||||
pub(crate) struct RLinkEncodingVersionMismatch {
|
||||
pub version_array: String,
|
||||
pub rlink_version: u32,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_rustc_version_mismatch)]
|
||||
#[diag(
|
||||
".rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`"
|
||||
)]
|
||||
pub(crate) struct RLinkRustcVersionMismatch<'a> {
|
||||
pub rustc_version: String,
|
||||
pub current_version: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_no_a_file)]
|
||||
#[diag("rlink must be a file")]
|
||||
pub(crate) struct RlinkNotAFile;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_rlink_corrupt_file)]
|
||||
#[diag("corrupt metadata encountered in `{$file}`")]
|
||||
pub(crate) struct RlinkCorruptFile<'a> {
|
||||
pub file: &'a std::path::Path,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice)]
|
||||
#[diag("the compiler unexpectedly panicked. this is a bug.")]
|
||||
pub(crate) struct Ice;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_bug_report)]
|
||||
#[diag("we would appreciate a bug report: {$bug_report_url}")]
|
||||
pub(crate) struct IceBugReport<'a> {
|
||||
pub bug_report_url: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_bug_report_update_note)]
|
||||
#[diag("please make sure that you have updated to the latest nightly")]
|
||||
pub(crate) struct UpdateNightlyNote;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_bug_report_internal_feature)]
|
||||
#[diag(
|
||||
"using internal features is not supported and expected to cause internal compiler errors when used incorrectly"
|
||||
)]
|
||||
pub(crate) struct IceBugReportInternalFeature;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_version)]
|
||||
#[diag("rustc {$version} running on {$triple}")]
|
||||
pub(crate) struct IceVersion<'a> {
|
||||
pub version: &'a str,
|
||||
pub triple: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_path)]
|
||||
#[diag("please attach the file at `{$path}` to your bug report")]
|
||||
pub(crate) struct IcePath {
|
||||
pub path: std::path::PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_path_error)]
|
||||
#[diag("the ICE couldn't be written to `{$path}`: {$error}")]
|
||||
pub(crate) struct IcePathError {
|
||||
pub path: std::path::PathBuf,
|
||||
pub error: String,
|
||||
|
|
@ -87,23 +93,23 @@ pub(crate) struct IcePathError {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(driver_impl_ice_path_error_env)]
|
||||
#[note("the environment variable `RUSTC_ICE` is set to `{$env_var}`")]
|
||||
pub(crate) struct IcePathErrorEnv {
|
||||
pub env_var: std::path::PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_flags)]
|
||||
#[diag("compiler flags: {$flags}")]
|
||||
pub(crate) struct IceFlags {
|
||||
pub flags: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_ice_exclude_cargo_defaults)]
|
||||
#[diag("some of the compiler flags provided by cargo are hidden")]
|
||||
pub(crate) struct IceExcludeCargoDefaults;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver_impl_unstable_feature_usage)]
|
||||
#[diag("cannot dump feature usage metrics: {$error}")]
|
||||
pub(crate) struct UnstableFeatureUsage {
|
||||
pub error: Box<dyn Error>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,6 +247,9 @@ pub enum SubdiagMessage {
|
|||
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
||||
/// `Subdiagnostic` derive.
|
||||
FluentIdentifier(FluentId),
|
||||
/// An inline Fluent message. Instances of this variant are generated by the
|
||||
/// `Subdiagnostic` derive.
|
||||
Inline(Cow<'static, str>),
|
||||
/// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an
|
||||
/// actual translated message. Instances of this variant are generated by the `fluent_messages`
|
||||
/// macro.
|
||||
|
|
@ -291,6 +294,8 @@ pub enum DiagMessage {
|
|||
/// <https://projectfluent.org/fluent/guide/hello.html>
|
||||
/// <https://projectfluent.org/fluent/guide/attributes.html>
|
||||
FluentIdentifier(FluentId, Option<FluentId>),
|
||||
/// An inline Fluent message, containing the to be translated diagnostic message.
|
||||
Inline(Cow<'static, str>),
|
||||
}
|
||||
|
||||
impl DiagMessage {
|
||||
|
|
@ -305,21 +310,22 @@ impl DiagMessage {
|
|||
SubdiagMessage::FluentIdentifier(id) => {
|
||||
return DiagMessage::FluentIdentifier(id, None);
|
||||
}
|
||||
SubdiagMessage::Inline(s) => return DiagMessage::Inline(s),
|
||||
SubdiagMessage::FluentAttr(attr) => attr,
|
||||
};
|
||||
|
||||
match self {
|
||||
DiagMessage::Str(s) => DiagMessage::Str(s.clone()),
|
||||
DiagMessage::FluentIdentifier(id, _) => {
|
||||
DiagMessage::FluentIdentifier(id.clone(), Some(attr))
|
||||
}
|
||||
_ => panic!("Tried to add a subdiagnostic to a message without a fluent identifier"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match self {
|
||||
DiagMessage::Str(s) => Some(s),
|
||||
DiagMessage::FluentIdentifier(_, _) => None,
|
||||
DiagMessage::FluentIdentifier(_, _) | DiagMessage::Inline(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -353,6 +359,7 @@ impl From<DiagMessage> for SubdiagMessage {
|
|||
// There isn't really a sensible behaviour for this because it loses information but
|
||||
// this is the most sensible of the behaviours.
|
||||
DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr),
|
||||
DiagMessage::Inline(s) => SubdiagMessage::Inline(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@ use std::env;
|
|||
use std::error::Report;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_error_messages::langid;
|
||||
pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle};
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::error::{TranslateError, TranslateErrorKind};
|
||||
use crate::{DiagArg, DiagMessage, FluentBundle, Style};
|
||||
use crate::fluent_bundle::FluentResource;
|
||||
use crate::{DiagArg, DiagMessage, FluentBundle, Style, fluent_bundle};
|
||||
|
||||
/// Convert diagnostic arguments (a rustc internal type that exists to implement
|
||||
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
|
||||
|
|
@ -79,6 +81,28 @@ impl Translator {
|
|||
return Ok(Cow::Borrowed(msg));
|
||||
}
|
||||
DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||
// This translates an inline fluent diagnostic message
|
||||
// It does this by creating a new `FluentBundle` with only one message,
|
||||
// and then translating using this bundle.
|
||||
DiagMessage::Inline(msg) => {
|
||||
const GENERATED_MSG_ID: &str = "generated_msg";
|
||||
let resource =
|
||||
FluentResource::try_new(format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap();
|
||||
let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]);
|
||||
bundle.set_use_isolating(false);
|
||||
bundle.add_resource(resource).unwrap();
|
||||
let message = bundle.get_message(GENERATED_MSG_ID).unwrap();
|
||||
let value = message.value().unwrap();
|
||||
|
||||
let mut errs = vec![];
|
||||
let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string();
|
||||
debug!(?translated, ?errs);
|
||||
return if errs.is_empty() {
|
||||
Ok(Cow::Owned(translated))
|
||||
} else {
|
||||
Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs))
|
||||
};
|
||||
}
|
||||
};
|
||||
let translate_with_bundle =
|
||||
|bundle: &'a FluentBundle| -> Result<Cow<'_, str>, TranslateError<'_>> {
|
||||
|
|
@ -142,3 +166,14 @@ impl Translator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This macro creates a translatable `DiagMessage` from a literal string.
|
||||
/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired.
|
||||
///
|
||||
/// This is a macro because in the future we may want to globally register these messages.
|
||||
#[macro_export]
|
||||
macro_rules! inline_fluent {
|
||||
($inline: literal) => {
|
||||
rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed($inline))
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use rustc_feature::{
|
|||
UNSTABLE_LANG_FEATURES,
|
||||
};
|
||||
use rustc_hir::Target;
|
||||
use rustc_parse::parser::Recovery;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
|
||||
|
|
@ -395,7 +396,9 @@ impl<'a> StripUnconfigured<'a> {
|
|||
fn in_cfg(&self, attrs: &[Attribute]) -> bool {
|
||||
attrs.iter().all(|attr| {
|
||||
!is_cfg(attr)
|
||||
|| self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool()
|
||||
|| self
|
||||
.cfg_true(attr, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed })
|
||||
.as_bool()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use rustc_hir::def::MacroKinds;
|
|||
use rustc_hir::limit::Limit;
|
||||
use rustc_parse::parser::{
|
||||
AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser,
|
||||
RecoverColon, RecoverComma, token_descr,
|
||||
RecoverColon, RecoverComma, Recovery, token_descr,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
|
||||
|
|
@ -508,6 +508,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
// Unresolved macros produce dummy outputs as a recovery measure.
|
||||
invocations.reverse();
|
||||
let mut expanded_fragments = Vec::new();
|
||||
let mut expanded_fragments_len = 0;
|
||||
let mut undetermined_invocations = Vec::new();
|
||||
let (mut progress, mut force) = (false, !self.monotonic);
|
||||
loop {
|
||||
|
|
@ -602,6 +603,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
expanded_fragments.push(Vec::new());
|
||||
}
|
||||
expanded_fragments[depth - 1].push((expn_id, expanded_fragment));
|
||||
expanded_fragments_len += 1;
|
||||
invocations.extend(derive_invocations.into_iter().rev());
|
||||
}
|
||||
ExpandResult::Retry(invoc) => {
|
||||
|
|
@ -622,7 +624,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
self.cx.force_mode = orig_force_mode;
|
||||
|
||||
// Finally incorporate all the expanded macros into the input AST fragment.
|
||||
let mut placeholder_expander = PlaceholderExpander::default();
|
||||
let mut placeholder_expander = PlaceholderExpander::with_capacity(expanded_fragments_len);
|
||||
while let Some(expanded_fragments) = expanded_fragments.pop() {
|
||||
for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
|
||||
placeholder_expander
|
||||
|
|
@ -2170,7 +2172,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
call.span(),
|
||||
self.cx.current_expansion.lint_node_id,
|
||||
Some(self.cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
);
|
||||
|
||||
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
||||
|
|
@ -2220,7 +2222,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
// Target doesn't matter for `cfg` parsing.
|
||||
Target::Crate,
|
||||
self.cfg().features,
|
||||
ShouldEmit::ErrorsAndLints { recover: true },
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
parse_cfg,
|
||||
&CFG_TEMPLATE,
|
||||
) else {
|
||||
|
|
|
|||
|
|
@ -218,12 +218,17 @@ pub(crate) fn placeholder(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct PlaceholderExpander {
|
||||
expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
|
||||
}
|
||||
|
||||
impl PlaceholderExpander {
|
||||
pub(crate) fn with_capacity(capacity: usize) -> Self {
|
||||
PlaceholderExpander {
|
||||
expanded_fragments: FxHashMap::with_capacity_and_hasher(capacity, Default::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
|
||||
fragment.mut_visit_with(self);
|
||||
self.expanded_fragments.insert(id, fragment);
|
||||
|
|
|
|||
|
|
@ -331,6 +331,8 @@ pub enum NativeLibKind {
|
|||
bundle: Option<bool>,
|
||||
/// Whether to link static library without throwing any object files away
|
||||
whole_archive: Option<bool>,
|
||||
/// Whether to export c static library symbols
|
||||
export_symbols: Option<bool>,
|
||||
},
|
||||
/// Dynamic library (e.g. `libfoo.so` on Linux)
|
||||
/// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
|
||||
|
|
@ -363,8 +365,8 @@ pub enum NativeLibKind {
|
|||
impl NativeLibKind {
|
||||
pub fn has_modifiers(&self) -> bool {
|
||||
match self {
|
||||
NativeLibKind::Static { bundle, whole_archive } => {
|
||||
bundle.is_some() || whole_archive.is_some()
|
||||
NativeLibKind::Static { bundle, whole_archive, export_symbols } => {
|
||||
bundle.is_some() || whole_archive.is_some() || export_symbols.is_some()
|
||||
}
|
||||
NativeLibKind::Dylib { as_needed }
|
||||
| NativeLibKind::Framework { as_needed }
|
||||
|
|
@ -699,6 +701,21 @@ pub enum RustcLayoutType {
|
|||
Debug,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq, Eq)]
|
||||
pub enum RustcMirKind {
|
||||
PeekMaybeInit,
|
||||
PeekMaybeUninit,
|
||||
PeekLiveness,
|
||||
StopAfterDataflow,
|
||||
BorrowckGraphvizPostflow { path: PathBuf },
|
||||
BorrowckGraphvizFormat { format: BorrowckGraphvizFormatKind },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq, Eq)]
|
||||
pub enum BorrowckGraphvizFormatKind {
|
||||
TwoPhase,
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
|
|
@ -1057,6 +1074,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_has_incoherent_inherent_impls]`
|
||||
RustcHasIncoherentInherentImpls,
|
||||
|
||||
/// Represents `#[rustc_hidden_type_of_opaques]`
|
||||
RustcHiddenTypeOfOpaques,
|
||||
|
||||
/// Represents `#[rustc_layout]`
|
||||
RustcLayout(ThinVec<RustcLayoutType>),
|
||||
|
||||
|
|
@ -1087,6 +1107,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_main]`.
|
||||
RustcMain,
|
||||
|
||||
/// Represents `#[rustc_mir]`.
|
||||
RustcMir(ThinVec<RustcMirKind>),
|
||||
|
||||
/// Represents `#[rustc_must_implement_one_of]`
|
||||
RustcMustImplementOneOf { attr_span: Span, fn_names: ThinVec<Ident> },
|
||||
|
||||
|
|
@ -1123,6 +1146,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]`
|
||||
RustcPassIndirectlyInNonRusticAbis(Span),
|
||||
|
||||
/// Represents `#[rustc_preserve_ub_checks]`
|
||||
RustcPreserveUbChecks,
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
RustcPubTransparent(Span),
|
||||
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ impl AttributeKind {
|
|||
RustcDumpVtable(..) => No,
|
||||
RustcDynIncompatibleTrait(..) => No,
|
||||
RustcHasIncoherentInherentImpls => Yes,
|
||||
RustcHiddenTypeOfOpaques => No,
|
||||
RustcLayout(..) => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
|
|
@ -121,6 +122,7 @@ impl AttributeKind {
|
|||
RustcLintUntrackedQueryInformation => Yes,
|
||||
RustcMacroTransparency(..) => Yes,
|
||||
RustcMain => No,
|
||||
RustcMir(..) => Yes,
|
||||
RustcMustImplementOneOf { .. } => No,
|
||||
RustcNeverReturnsNullPointer => Yes,
|
||||
RustcNoImplicitAutorefs => Yes,
|
||||
|
|
@ -133,6 +135,7 @@ impl AttributeKind {
|
|||
RustcParenSugar(..) => No,
|
||||
RustcPassByValue(..) => Yes,
|
||||
RustcPassIndirectlyInNonRusticAbis(..) => No,
|
||||
RustcPreserveUbChecks => No,
|
||||
RustcPubTransparent(..) => Yes,
|
||||
RustcReallocator => No,
|
||||
RustcScalableVector { .. } => Yes,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::num::NonZero;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_abi::Align;
|
||||
use rustc_ast::attr::data_structures::CfgEntry;
|
||||
|
|
@ -96,7 +97,15 @@ impl<T: PrintAttribute> PrintAttribute for FxIndexMap<T, Span> {
|
|||
p.word("]");
|
||||
}
|
||||
}
|
||||
impl PrintAttribute for PathBuf {
|
||||
fn should_render(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn print_attribute(&self, p: &mut Printer) {
|
||||
p.word(self.display().to_string());
|
||||
}
|
||||
}
|
||||
macro_rules! print_skip {
|
||||
($($t: ty),* $(,)?) => {$(
|
||||
impl PrintAttribute for $t {
|
||||
|
|
|
|||
|
|
@ -224,6 +224,10 @@ hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a par
|
|||
hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
|
||||
.note = parent implementation is in crate `{$cname}`
|
||||
|
||||
hir_analysis_impl_unpin_for_pin_projected_type = explicit impls for the `Unpin` trait are not permitted for structurally pinned types
|
||||
.label = impl of `Unpin` not allowed
|
||||
.help = `{$adt_name}` is structurally pinned because it is marked as `#[pin_v2]`
|
||||
|
||||
hir_analysis_inherent_dyn = cannot define inherent `impl` for a dyn auto trait
|
||||
.label = impl requires at least one non-auto trait
|
||||
.note = define and implement a new trait or type instead
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ pub(super) fn check_trait<'tcx>(
|
|||
checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
|
||||
checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
|
||||
checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
|
||||
checker.check(lang_items.unpin_trait(), visit_implementation_of_unpin)?;
|
||||
checker.check(lang_items.const_param_ty_trait(), |checker| {
|
||||
visit_implementation_of_const_param_ty(checker)
|
||||
})?;
|
||||
|
|
@ -134,6 +135,41 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = checker.tcx;
|
||||
let impl_header = checker.impl_header;
|
||||
let impl_did = checker.impl_def_id;
|
||||
debug!("visit_implementation_of_unpin: impl_did={:?}", impl_did);
|
||||
|
||||
let self_type = impl_header.trait_ref.instantiate_identity().self_ty();
|
||||
debug!("visit_implementation_of_unpin: self_type={:?}", self_type);
|
||||
|
||||
let span = tcx.def_span(impl_did);
|
||||
|
||||
if tcx.features().pin_ergonomics() {
|
||||
match self_type.kind() {
|
||||
// Soundness concerns: a type `T` annotated with `#[pin_v2]` is allowed to project
|
||||
// `Pin<&mut T>` to its field `Pin<&mut U>` safely (even if `U: !Unpin`).
|
||||
// If `T` is allowed to impl `Unpin` manually (note that `Unpin` is a safe trait,
|
||||
// which cannot carry safety properties), then `&mut U` could be obtained from
|
||||
// `&mut T` that dereferenced by `Pin<&mut T>`, which breaks the safety contract of
|
||||
// `Pin<&mut U>` for `U: !Unpin`.
|
||||
ty::Adt(adt, _) if adt.is_pin_project() => {
|
||||
return Err(tcx.dcx().emit_err(crate::errors::ImplUnpinForPinProjectedType {
|
||||
span,
|
||||
adt_span: tcx.def_span(adt.did()),
|
||||
adt_name: tcx.item_name(adt.did()),
|
||||
}));
|
||||
}
|
||||
ty::Adt(_, _) => {}
|
||||
_ => {
|
||||
return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type"));
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = checker.tcx;
|
||||
let header = checker.impl_header;
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
|||
use rustc_span::sym;
|
||||
|
||||
pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
|
||||
if !tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) {
|
||||
if !find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcHiddenTypeOfOpaques) {
|
||||
return;
|
||||
}
|
||||
|
||||
for id in tcx.hir_crate_items(()).opaques() {
|
||||
if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
|
||||
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } =
|
||||
|
|
|
|||
|
|
@ -1690,3 +1690,14 @@ pub(crate) struct EiiWithGenerics {
|
|||
pub eii_name: Symbol,
|
||||
pub impl_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_impl_unpin_for_pin_projected_type)]
|
||||
pub(crate) struct ImplUnpinForPinProjectedType {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[help]
|
||||
pub adt_span: Span,
|
||||
pub adt_name: Symbol,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
|
|||
struct HirWfCheck<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
cause: Option<ObligationCause<'tcx>>,
|
||||
cause_depth: usize,
|
||||
cause: Option<ObligationCause<'tcx>> = None,
|
||||
cause_depth: usize = 0,
|
||||
icx: ItemCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
depth: usize,
|
||||
depth: usize = 0,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
|
||||
|
|
@ -124,16 +124,8 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
let mut visitor = HirWfCheck {
|
||||
tcx,
|
||||
predicate,
|
||||
cause: None,
|
||||
cause_depth: 0,
|
||||
icx,
|
||||
def_id,
|
||||
param_env: tcx.param_env(def_id.to_def_id()),
|
||||
depth: 0,
|
||||
};
|
||||
let param_env = tcx.param_env(def_id.to_def_id());
|
||||
let mut visitor = HirWfCheck { tcx, predicate, icx, def_id, param_env, .. };
|
||||
|
||||
// Get the starting `hir::Ty` using our `WellFormedLoc`.
|
||||
// We will walk 'into' this type to try to find
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ This API is completely unstable and subject to change.
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![feature(assert_matches)]
|
||||
#![feature(default_field_values)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use itertools::Itertools;
|
|||
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::traits::PredicateObligations;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
|
@ -45,22 +45,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty()));
|
||||
let steps: Vec<_> = steps
|
||||
.iter()
|
||||
.map(|&(source, kind)| {
|
||||
if let AutoderefKind::Overloaded = kind {
|
||||
self.try_overloaded_deref(autoderef.span(), source).and_then(
|
||||
|InferOk { value: method, obligations: o }| {
|
||||
.map(|&(source, kind)| match kind {
|
||||
AutoderefKind::Overloaded => {
|
||||
self.try_overloaded_deref(autoderef.span(), source)
|
||||
.and_then(|InferOk { value: method, obligations: o }| {
|
||||
obligations.extend(o);
|
||||
// FIXME: we should assert the sig is &T here... there's no reason for this to be fallible.
|
||||
if let ty::Ref(_, _, mutbl) = *method.sig.output().kind() {
|
||||
Some(OverloadedDeref { mutbl, span: autoderef.span() })
|
||||
Some(DerefAdjustKind::Overloaded(OverloadedDeref {
|
||||
mutbl,
|
||||
span: autoderef.span(),
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.unwrap_or(DerefAdjustKind::Builtin)
|
||||
}
|
||||
AutoderefKind::Builtin => DerefAdjustKind::Builtin,
|
||||
})
|
||||
.zip_eq(targets)
|
||||
.map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ use rustc_infer::traits::{
|
|||
};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind,
|
||||
PointerCoercion,
|
||||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
|
|
@ -595,7 +596,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
|
||||
|
||||
Some((
|
||||
Adjustment { kind: Adjust::Deref(None), target: ty_a },
|
||||
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
|
||||
target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b),
|
||||
|
|
@ -606,7 +607,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
coerce_mutbls(mt_a, mt_b)?;
|
||||
|
||||
Some((
|
||||
Adjustment { kind: Adjust::Deref(None), target: ty_a },
|
||||
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
|
||||
target: Ty::new_ptr(self.tcx, ty_a, mt_b),
|
||||
|
|
@ -936,7 +937,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
self.unify_and(
|
||||
a_raw,
|
||||
b,
|
||||
[Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }],
|
||||
[Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: mt_a.ty }],
|
||||
Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
|
||||
ForceLeakCheck::No,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use rustc_middle::hir::place::ProjectionKind;
|
|||
pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_middle::thir::DerefPatBorrowMode;
|
||||
use rustc_middle::ty::adjustment::DerefAdjustKind;
|
||||
use rustc_middle::ty::{
|
||||
self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
|
||||
};
|
||||
|
|
@ -733,14 +734,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
|
||||
}
|
||||
|
||||
adjustment::Adjust::Deref(None) => {}
|
||||
adjustment::Adjust::Deref(DerefAdjustKind::Builtin) => {}
|
||||
|
||||
// Autoderefs for overloaded Deref calls in fact reference
|
||||
// their receiver. That is, if we have `(*x)` where `x`
|
||||
// is of type `Rc<T>`, then this in fact is equivalent to
|
||||
// `x.deref()`. Since `deref()` is declared with `&self`,
|
||||
// this is an autoref of `x`.
|
||||
adjustment::Adjust::Deref(Some(ref deref)) => {
|
||||
adjustment::Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
|
||||
let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
|
||||
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
|
||||
}
|
||||
|
|
@ -1272,9 +1273,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
{
|
||||
let target = self.cx.resolve_vars_if_possible(adjustment.target);
|
||||
match adjustment.kind {
|
||||
adjustment::Adjust::Deref(overloaded) => {
|
||||
adjustment::Adjust::Deref(deref_kind) => {
|
||||
// Equivalent to *expr or something similar.
|
||||
let base = if let Some(deref) = overloaded {
|
||||
let base = if let DerefAdjustKind::Overloaded(deref) = deref_kind {
|
||||
let ref_ty = Ty::new_ref(
|
||||
self.cx.tcx(),
|
||||
self.cx.tcx().lifetimes.re_erased,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ use rustc_hir_analysis::hir_ty_lowering::{
|
|||
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
|
||||
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind,
|
||||
};
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity,
|
||||
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs,
|
||||
|
|
@ -266,7 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
|
||||
}
|
||||
}
|
||||
Adjust::Deref(Some(overloaded_deref)) => {
|
||||
Adjust::Deref(DerefAdjustKind::Overloaded(overloaded_deref)) => {
|
||||
self.enforce_context_effects(
|
||||
None,
|
||||
expr.span,
|
||||
|
|
@ -274,7 +276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx.mk_args(&[expr_ty.into()]),
|
||||
);
|
||||
}
|
||||
Adjust::Deref(None) => {
|
||||
Adjust::Deref(DerefAdjustKind::Builtin) => {
|
||||
// FIXME(const_trait_impl): We *could* enforce `&T: [const] Deref` here.
|
||||
}
|
||||
Adjust::Pointer(_pointer_coercion) => {
|
||||
|
|
|
|||
|
|
@ -2647,7 +2647,15 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> {
|
|||
// To suggest a multipart suggestion when encountering `foo(1, "")` where the def
|
||||
// was `fn foo(())`.
|
||||
let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx];
|
||||
suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
|
||||
// Check if the new suggestion would overlap with any existing suggestion.
|
||||
// This can happen when we have both removal suggestions (which may include
|
||||
// adjacent commas) and type replacement suggestions for the same span.
|
||||
let dominated = suggestions
|
||||
.iter()
|
||||
.any(|(span, _)| span.contains(*arg_span) || arg_span.overlaps(*span));
|
||||
if !dominated {
|
||||
suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,6 +200,14 @@ fn typeck_with_inspect<'tcx>(
|
|||
let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
|
||||
fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
|
||||
|
||||
if let hir::Node::AnonConst(_) = node {
|
||||
fcx.require_type_is_sized(
|
||||
expected_type,
|
||||
body.value.span,
|
||||
ObligationCauseCode::SizedConstOrStatic,
|
||||
);
|
||||
}
|
||||
|
||||
fcx.check_expr_coercible_to_type(body.value, expected_type, None);
|
||||
|
||||
fcx.write_ty(id, expected_type);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use rustc_infer::infer::InferOk;
|
|||
use rustc_infer::traits::{Obligation, ObligationCauseCode};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref,
|
||||
PointerCoercion,
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind,
|
||||
OverloadedDeref, PointerCoercion,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{Span, sym};
|
||||
|
|
@ -298,7 +298,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.typeck_results.borrow_mut().adjustments_mut().remove(expr.hir_id);
|
||||
if let Some(mut adjustments) = previous_adjustments {
|
||||
for adjustment in &mut adjustments {
|
||||
if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind
|
||||
if let Adjust::Deref(DerefAdjustKind::Overloaded(ref mut deref)) =
|
||||
adjustment.kind
|
||||
&& let Some(ok) = self.try_mutable_overloaded_place_op(
|
||||
expr.span,
|
||||
source,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ rand = "0.9.0"
|
|||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_fs_util = { path = "../rustc_fs_util" }
|
||||
rustc_graphviz = { path = "../rustc_graphviz" }
|
||||
rustc_hashes = { path = "../rustc_hashes" }
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
incremental_assert_loaded =
|
||||
we asserted that an existing incremental cache directory should be successfully loaded, but it was not
|
||||
|
||||
incremental_assert_not_loaded =
|
||||
we asserted that the incremental cache should not be loaded, but it was loaded
|
||||
|
||||
incremental_assertion_auto =
|
||||
`except` specified DepNodes that can not be affected for "{$name}": "{$e}"
|
||||
|
||||
incremental_associated_value_expected = expected an associated value
|
||||
|
||||
incremental_associated_value_expected_for = associated value expected for `{$ident}`
|
||||
|
||||
incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
|
||||
|
||||
incremental_cargo_help_1 =
|
||||
incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
|
||||
incremental_cargo_help_2 =
|
||||
the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
|
||||
|
||||
incremental_copy_workproduct_to_cache =
|
||||
error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
|
||||
|
||||
incremental_corrupt_file = corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant.
|
||||
|
||||
incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
|
||||
|
||||
incremental_create_incr_comp_dir =
|
||||
could not create incremental compilation {$tag} directory `{$path}`: {$err}
|
||||
|
||||
incremental_create_lock =
|
||||
incremental compilation: could not create session directory lock file: {$lock_err}
|
||||
incremental_create_new = failed to create {$name} at `{$path}`: {$err}
|
||||
|
||||
incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_delete_incompatible =
|
||||
failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
|
||||
|
||||
incremental_delete_lock =
|
||||
error deleting lock file for incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
|
||||
|
||||
incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
|
||||
|
||||
incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
|
||||
|
||||
incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_finalized_gc_failed =
|
||||
failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_hard_link_failed =
|
||||
hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
|
||||
|
||||
incremental_invalid_gc_failed =
|
||||
failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
|
||||
|
||||
incremental_lock_unsupported =
|
||||
the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
|
||||
|
||||
incremental_missing_depnode = missing `DepNode` variant
|
||||
|
||||
incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
|
||||
|
||||
incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
|
||||
|
||||
incremental_no_cfg = no cfg attribute
|
||||
|
||||
incremental_no_path = no path from `{$source}` to `{$target}`
|
||||
|
||||
incremental_not_clean = `{$dep_node_str}` should be clean but is not
|
||||
|
||||
incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
|
||||
|
||||
incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
|
||||
|
||||
incremental_ok = OK
|
||||
|
||||
incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
|
||||
|
||||
incremental_session_gc_failed =
|
||||
failed to garbage collect incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
|
||||
|
||||
incremental_undefined_clean_dirty_assertions =
|
||||
clean/dirty auto-assertions not yet defined for {$kind}
|
||||
|
||||
incremental_undefined_clean_dirty_assertions_item =
|
||||
clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
|
||||
|
||||
incremental_unknown_rustc_clean_argument = unknown `rustc_clean` argument
|
||||
|
||||
incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
|
||||
|
||||
incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
|
||||
|
||||
incremental_write_new = failed to write {$name} to `{$path}`: {$err}
|
||||
|
|
@ -4,7 +4,7 @@ use rustc_macros::Diagnostic;
|
|||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unrecognized_depnode)]
|
||||
#[diag("unrecognized `DepNode` variant: {$name}")]
|
||||
pub(crate) struct UnrecognizedDepNode {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -12,28 +12,28 @@ pub(crate) struct UnrecognizedDepNode {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_missing_depnode)]
|
||||
#[diag("missing `DepNode` variant")]
|
||||
pub(crate) struct MissingDepNode {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_missing_if_this_changed)]
|
||||
#[diag("no `#[rustc_if_this_changed]` annotation detected")]
|
||||
pub(crate) struct MissingIfThisChanged {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_ok)]
|
||||
#[diag("OK")]
|
||||
pub(crate) struct Ok {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_path)]
|
||||
#[diag("no path from `{$source}` to `{$target}`")]
|
||||
pub(crate) struct NoPath {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -42,7 +42,7 @@ pub(crate) struct NoPath {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assertion_auto)]
|
||||
#[diag("`except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\"")]
|
||||
pub(crate) struct AssertionAuto<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -51,7 +51,7 @@ pub(crate) struct AssertionAuto<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_undefined_clean_dirty_assertions_item)]
|
||||
#[diag("clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}")]
|
||||
pub(crate) struct UndefinedCleanDirtyItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -59,7 +59,7 @@ pub(crate) struct UndefinedCleanDirtyItem {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_undefined_clean_dirty_assertions)]
|
||||
#[diag("clean/dirty auto-assertions not yet defined for {$kind}")]
|
||||
pub(crate) struct UndefinedCleanDirty {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -67,7 +67,7 @@ pub(crate) struct UndefinedCleanDirty {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_repeated_depnode_label)]
|
||||
#[diag("dep-node label `{$label}` is repeated")]
|
||||
pub(crate) struct RepeatedDepNodeLabel<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -75,7 +75,7 @@ pub(crate) struct RepeatedDepNodeLabel<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unrecognized_depnode_label)]
|
||||
#[diag("dep-node label `{$label}` not recognized")]
|
||||
pub(crate) struct UnrecognizedDepNodeLabel<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -83,7 +83,7 @@ pub(crate) struct UnrecognizedDepNodeLabel<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_not_dirty)]
|
||||
#[diag("`{$dep_node_str}` should be dirty but is not")]
|
||||
pub(crate) struct NotDirty<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -91,7 +91,7 @@ pub(crate) struct NotDirty<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_not_clean)]
|
||||
#[diag("`{$dep_node_str}` should be clean but is not")]
|
||||
pub(crate) struct NotClean<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -99,7 +99,7 @@ pub(crate) struct NotClean<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_not_loaded)]
|
||||
#[diag("`{$dep_node_str}` should have been loaded from disk but it was not")]
|
||||
pub(crate) struct NotLoaded<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -107,21 +107,21 @@ pub(crate) struct NotLoaded<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unknown_rustc_clean_argument)]
|
||||
#[diag("unknown `rustc_clean` argument")]
|
||||
pub(crate) struct UnknownRustcCleanArgument {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_cfg)]
|
||||
#[diag("no cfg attribute")]
|
||||
pub(crate) struct NoCfg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_associated_value_expected_for)]
|
||||
#[diag("associated value expected for `{$ident}`")]
|
||||
pub(crate) struct AssociatedValueExpectedFor {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -129,21 +129,21 @@ pub(crate) struct AssociatedValueExpectedFor {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_associated_value_expected)]
|
||||
#[diag("expected an associated value")]
|
||||
pub(crate) struct AssociatedValueExpected {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unchecked_clean)]
|
||||
#[diag("found unchecked `#[rustc_clean]` attribute")]
|
||||
pub(crate) struct UncheckedClean {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_old)]
|
||||
#[diag("unable to delete old {$name} at `{$path}`: {$err}")]
|
||||
pub(crate) struct DeleteOld<'a> {
|
||||
pub name: &'a str,
|
||||
pub path: PathBuf,
|
||||
|
|
@ -151,7 +151,7 @@ pub(crate) struct DeleteOld<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_new)]
|
||||
#[diag("failed to create {$name} at `{$path}`: {$err}")]
|
||||
pub(crate) struct CreateNew<'a> {
|
||||
pub name: &'a str,
|
||||
pub path: PathBuf,
|
||||
|
|
@ -159,7 +159,7 @@ pub(crate) struct CreateNew<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_write_new)]
|
||||
#[diag("failed to write {$name} to `{$path}`: {$err}")]
|
||||
pub(crate) struct WriteNew<'a> {
|
||||
pub name: &'a str,
|
||||
pub path: PathBuf,
|
||||
|
|
@ -167,14 +167,14 @@ pub(crate) struct WriteNew<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_canonicalize_path)]
|
||||
#[diag("incremental compilation: error canonicalizing path `{$path}`: {$err}")]
|
||||
pub(crate) struct CanonicalizePath {
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_incr_comp_dir)]
|
||||
#[diag("could not create incremental compilation {$tag} directory `{$path}`: {$err}")]
|
||||
pub(crate) struct CreateIncrCompDir<'a> {
|
||||
pub tag: &'a str,
|
||||
pub path: &'a Path,
|
||||
|
|
@ -182,96 +182,112 @@ pub(crate) struct CreateIncrCompDir<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_lock)]
|
||||
#[diag("incremental compilation: could not create session directory lock file: {$lock_err}")]
|
||||
pub(crate) struct CreateLock<'a> {
|
||||
pub lock_err: std::io::Error,
|
||||
pub session_dir: &'a Path,
|
||||
#[note(incremental_lock_unsupported)]
|
||||
#[note(
|
||||
"the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation"
|
||||
)]
|
||||
pub is_unsupported_lock: bool,
|
||||
#[help(incremental_cargo_help_1)]
|
||||
#[help(incremental_cargo_help_2)]
|
||||
#[help(
|
||||
"incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)"
|
||||
)]
|
||||
#[help(
|
||||
"the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)"
|
||||
)]
|
||||
pub is_cargo: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_lock)]
|
||||
#[diag("error deleting lock file for incremental compilation session directory `{$path}`: {$err}")]
|
||||
pub(crate) struct DeleteLock<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_hard_link_failed)]
|
||||
#[diag(
|
||||
"hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`"
|
||||
)]
|
||||
pub(crate) struct HardLinkFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_partial)]
|
||||
#[diag("failed to delete partly initialized session dir `{$path}`: {$err}")]
|
||||
pub(crate) struct DeletePartial<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_full)]
|
||||
#[diag("error deleting incremental compilation session directory `{$path}`: {$err}")]
|
||||
pub(crate) struct DeleteFull<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_finalize)]
|
||||
#[diag("error finalizing incremental compilation session directory `{$path}`: {$err}")]
|
||||
pub(crate) struct Finalize<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_invalid_gc_failed)]
|
||||
#[diag(
|
||||
"failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}"
|
||||
)]
|
||||
pub(crate) struct InvalidGcFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_finalized_gc_failed)]
|
||||
#[diag(
|
||||
"failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}"
|
||||
)]
|
||||
pub(crate) struct FinalizedGcFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_session_gc_failed)]
|
||||
#[diag("failed to garbage collect incremental compilation session directory `{$path}`: {$err}")]
|
||||
pub(crate) struct SessionGcFailed<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assert_not_loaded)]
|
||||
#[diag("we asserted that the incremental cache should not be loaded, but it was loaded")]
|
||||
pub(crate) struct AssertNotLoaded;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assert_loaded)]
|
||||
#[diag(
|
||||
"we asserted that an existing incremental cache directory should be successfully loaded, but it was not"
|
||||
)]
|
||||
pub(crate) struct AssertLoaded;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_incompatible)]
|
||||
#[diag(
|
||||
"failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}"
|
||||
)]
|
||||
pub(crate) struct DeleteIncompatible {
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_load_dep_graph)]
|
||||
#[diag("could not load dep-graph from `{$path}`: {$err}")]
|
||||
pub(crate) struct LoadDepGraph {
|
||||
pub path: PathBuf,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_move_dep_graph)]
|
||||
#[diag("failed to move dependency graph from `{$from}` to `{$to}`: {$err}")]
|
||||
pub(crate) struct MoveDepGraph<'a> {
|
||||
pub from: &'a Path,
|
||||
pub to: &'a Path,
|
||||
|
|
@ -279,14 +295,14 @@ pub(crate) struct MoveDepGraph<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_create_dep_graph)]
|
||||
#[diag("failed to create dependency graph at `{$path}`: {$err}")]
|
||||
pub(crate) struct CreateDepGraph<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_copy_workproduct_to_cache)]
|
||||
#[diag("error copying object file `{$from}` to incremental directory as `{$to}`: {$err}")]
|
||||
pub(crate) struct CopyWorkProductToCache<'a> {
|
||||
pub from: &'a Path,
|
||||
pub to: &'a Path,
|
||||
|
|
@ -294,14 +310,16 @@ pub(crate) struct CopyWorkProductToCache<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_delete_workproduct)]
|
||||
#[diag("file-system error deleting outdated file `{$path}`: {$err}")]
|
||||
pub(crate) struct DeleteWorkProduct<'a> {
|
||||
pub path: &'a Path,
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_corrupt_file)]
|
||||
#[diag(
|
||||
"corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant."
|
||||
)]
|
||||
pub(crate) struct CorruptFile<'a> {
|
||||
pub path: &'a Path,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,5 +21,3 @@ pub fn provide(providers: &mut Providers) {
|
|||
providers.hooks.save_dep_graph =
|
||||
|tcx| tcx.sess.time("serialize_dep_graph", || persist::save_dep_graph(tcx));
|
||||
}
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ doctest = false
|
|||
# tidy-alphabetical-start
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
infer_opaque_hidden_type =
|
||||
opaque type's hidden type cannot be another opaque type from the same scope
|
||||
.label = one of the two opaque types used here has to be outside its defining scope
|
||||
.opaque_type = opaque type whose hidden type is being assigned
|
||||
.hidden_type = opaque type being used as hidden type
|
||||
|
|
@ -2,13 +2,13 @@ use rustc_macros::Diagnostic;
|
|||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_opaque_hidden_type)]
|
||||
#[diag("opaque type's hidden type cannot be another opaque type from the same scope")]
|
||||
pub(crate) struct OpaqueHiddenTypeDiag {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("one of the two opaque types used here has to be outside its defining scope")]
|
||||
pub span: Span,
|
||||
#[note(infer_opaque_type)]
|
||||
#[note("opaque type whose hidden type is being assigned")]
|
||||
pub opaque_type: Span,
|
||||
#[note(infer_hidden_type)]
|
||||
#[note("opaque type being used as hidden type")]
|
||||
pub hidden_type: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,3 @@
|
|||
mod errors;
|
||||
pub mod infer;
|
||||
pub mod traits;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
|||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_fs_util = { path = "../rustc_fs_util" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
interface_abi_required_feature =
|
||||
target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly
|
||||
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
interface_abi_required_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`
|
||||
|
||||
interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen
|
||||
|
||||
interface_emoji_identifier =
|
||||
identifiers cannot contain emoji: `{$ident}`
|
||||
|
||||
interface_error_writing_dependencies =
|
||||
error writing dependencies to `{$path}`: {$error}
|
||||
|
||||
interface_failed_writing_file =
|
||||
failed to write file {$path}: {$error}"
|
||||
|
||||
interface_ferris_identifier =
|
||||
Ferris cannot be used as an identifier
|
||||
.suggestion = try using their name instead
|
||||
|
||||
interface_generated_file_conflicts_with_directory =
|
||||
the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}"
|
||||
|
||||
interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
|
||||
|
||||
interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
|
||||
|
||||
interface_input_file_would_be_overwritten =
|
||||
the input file "{$path}" would be overwritten by the generated executable
|
||||
|
||||
interface_mixed_bin_crate =
|
||||
cannot mix `bin` crate type with others
|
||||
|
||||
interface_mixed_proc_macro_crate =
|
||||
cannot mix `proc-macro` crate type with others
|
||||
|
||||
interface_multiple_output_types_adaption =
|
||||
due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
|
||||
|
||||
interface_multiple_output_types_to_stdout = can't use option `-o` or `--emit` to write multiple output types to stdout
|
||||
interface_out_dir_error =
|
||||
failed to find or create the directory specified by `--out-dir`
|
||||
|
||||
interface_proc_macro_crate_panic_abort =
|
||||
building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
|
||||
|
||||
interface_temps_dir_error =
|
||||
failed to find or create the directory specified by `--temps-dir`
|
||||
|
||||
interface_unsupported_crate_type_for_codegen_backend =
|
||||
dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}`
|
||||
|
||||
interface_unsupported_crate_type_for_target =
|
||||
dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
|
||||
|
|
@ -7,7 +7,9 @@ use rustc_span::{Span, Symbol};
|
|||
use rustc_target::spec::TargetTuple;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_crate_name_does_not_match)]
|
||||
#[diag(
|
||||
"`--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`"
|
||||
)]
|
||||
pub(crate) struct CrateNameDoesNotMatch {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
|
|
@ -16,23 +18,27 @@ pub(crate) struct CrateNameDoesNotMatch {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_crate_name_invalid)]
|
||||
#[diag("crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen")]
|
||||
pub(crate) struct CrateNameInvalid<'a> {
|
||||
pub(crate) crate_name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_ferris_identifier)]
|
||||
#[diag("Ferris cannot be used as an identifier")]
|
||||
pub struct FerrisIdentifier {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
#[suggestion(code = "{ferris_fix}", applicability = "maybe-incorrect")]
|
||||
#[suggestion(
|
||||
"try using their name instead",
|
||||
code = "{ferris_fix}",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub first_span: Span,
|
||||
pub ferris_fix: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_emoji_identifier)]
|
||||
#[diag("identifiers cannot contain emoji: `{$ident}`")]
|
||||
pub struct EmojiIdentifier {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
|
|
@ -40,86 +46,96 @@ pub struct EmojiIdentifier {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_mixed_bin_crate)]
|
||||
#[diag("cannot mix `bin` crate type with others")]
|
||||
pub struct MixedBinCrate;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_mixed_proc_macro_crate)]
|
||||
#[diag("cannot mix `proc-macro` crate type with others")]
|
||||
pub struct MixedProcMacroCrate;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_error_writing_dependencies)]
|
||||
#[diag("error writing dependencies to `{$path}`: {$error}")]
|
||||
pub struct ErrorWritingDependencies<'a> {
|
||||
pub path: &'a Path,
|
||||
pub error: io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_input_file_would_be_overwritten)]
|
||||
#[diag("the input file \"{$path}\" would be overwritten by the generated executable")]
|
||||
pub struct InputFileWouldBeOverWritten<'a> {
|
||||
pub path: &'a Path,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_generated_file_conflicts_with_directory)]
|
||||
#[diag(
|
||||
"the generated executable for the input file \"{$input_path}\" conflicts with the existing directory \"{$dir_path}\""
|
||||
)]
|
||||
pub struct GeneratedFileConflictsWithDirectory<'a> {
|
||||
pub input_path: &'a Path,
|
||||
pub dir_path: &'a Path,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_temps_dir_error)]
|
||||
#[diag("failed to find or create the directory specified by `--temps-dir`")]
|
||||
pub struct TempsDirError;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_out_dir_error)]
|
||||
#[diag("failed to find or create the directory specified by `--out-dir`")]
|
||||
pub struct OutDirError;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_failed_writing_file)]
|
||||
#[diag("failed to write file {$path}: {$error}\"")]
|
||||
pub struct FailedWritingFile<'a> {
|
||||
pub path: &'a Path,
|
||||
pub error: io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_proc_macro_crate_panic_abort)]
|
||||
#[diag(
|
||||
"building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic"
|
||||
)]
|
||||
pub struct ProcMacroCratePanicAbort;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_multiple_output_types_adaption)]
|
||||
#[diag(
|
||||
"due to multiple output types requested, the explicitly specified output file name will be adapted for each output type"
|
||||
)]
|
||||
pub struct MultipleOutputTypesAdaption;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_ignoring_extra_filename)]
|
||||
#[diag("ignoring -C extra-filename flag due to -o flag")]
|
||||
pub struct IgnoringExtraFilename;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_ignoring_out_dir)]
|
||||
#[diag("ignoring --out-dir flag due to -o flag")]
|
||||
pub struct IgnoringOutDir;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_multiple_output_types_to_stdout)]
|
||||
#[diag("can't use option `-o` or `--emit` to write multiple output types to stdout")]
|
||||
pub struct MultipleOutputTypesToStdout;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_abi_required_feature)]
|
||||
#[note]
|
||||
#[note(interface_abi_required_feature_issue)]
|
||||
#[diag(
|
||||
"target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly"
|
||||
)]
|
||||
#[note(
|
||||
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
|
||||
)]
|
||||
#[note("for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>")]
|
||||
pub(crate) struct AbiRequiredTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
pub enabled: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_unsupported_crate_type_for_codegen_backend)]
|
||||
#[diag("dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}`")]
|
||||
pub(crate) struct UnsupportedCrateTypeForCodegenBackend {
|
||||
pub(crate) crate_type: CrateType,
|
||||
pub(crate) codegen_backend: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(interface_unsupported_crate_type_for_target)]
|
||||
#[diag("dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`")]
|
||||
pub(crate) struct UnsupportedCrateTypeForTarget<'a> {
|
||||
pub(crate) crate_type: CrateType,
|
||||
pub(crate) target_triple: &'a TargetTuple,
|
||||
|
|
|
|||
|
|
@ -55,11 +55,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
|
|||
cfgs.into_iter()
|
||||
.map(|s| {
|
||||
let psess = ParseSess::emitter_with_note(
|
||||
vec![
|
||||
crate::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_parse::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_session::DEFAULT_LOCALE_RESOURCE,
|
||||
],
|
||||
vec![rustc_parse::DEFAULT_LOCALE_RESOURCE],
|
||||
format!("this occurred on the command line: `--cfg={s}`"),
|
||||
);
|
||||
let filename = FileName::cfg_spec_source_code(&s);
|
||||
|
|
@ -131,11 +127,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
|
|||
|
||||
for s in specs {
|
||||
let psess = ParseSess::emitter_with_note(
|
||||
vec![
|
||||
crate::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_parse::DEFAULT_LOCALE_RESOURCE,
|
||||
rustc_session::DEFAULT_LOCALE_RESOURCE,
|
||||
],
|
||||
vec![rustc_parse::DEFAULT_LOCALE_RESOURCE],
|
||||
format!("this occurred on the command line: `--check-cfg={s}`"),
|
||||
);
|
||||
let filename = FileName::cfg_spec_source_code(&s);
|
||||
|
|
@ -463,9 +455,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
|
||||
};
|
||||
|
||||
let mut locale_resources = config.locale_resources;
|
||||
locale_resources.push(codegen_backend.locale_resource());
|
||||
|
||||
let mut sess = rustc_session::build_session(
|
||||
config.opts,
|
||||
CompilerIO {
|
||||
|
|
@ -476,7 +465,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
},
|
||||
bundle,
|
||||
config.registry,
|
||||
locale_resources,
|
||||
config.locale_resources,
|
||||
config.lint_caps,
|
||||
target,
|
||||
util::rustc_version_str().unwrap_or("unknown"),
|
||||
|
|
@ -485,6 +474,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
);
|
||||
|
||||
codegen_backend.init(&sess);
|
||||
sess.replaced_intrinsics = FxHashSet::from_iter(codegen_backend.replaced_intrinsics());
|
||||
|
||||
let cfg = parse_cfg(sess.dcx(), config.crate_cfg);
|
||||
let mut cfg = config::build_configuration(&sess, cfg);
|
||||
|
|
|
|||
|
|
@ -21,5 +21,3 @@ pub use queries::Linker;
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ fn test_native_libs_tracking_hash_different_values() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -401,7 +401,7 @@ fn test_native_libs_tracking_hash_different_values() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -423,13 +423,13 @@ fn test_native_libs_tracking_hash_different_values() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
name: String::from("b"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -445,7 +445,7 @@ fn test_native_libs_tracking_hash_different_values() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -467,7 +467,7 @@ fn test_native_libs_tracking_hash_different_values() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -501,7 +501,7 @@ fn test_native_libs_tracking_hash_different_order() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -528,7 +528,7 @@ fn test_native_libs_tracking_hash_different_order() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
@ -549,7 +549,7 @@ fn test_native_libs_tracking_hash_different_order() {
|
|||
NativeLib {
|
||||
name: String::from("a"),
|
||||
new_name: None,
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None },
|
||||
verbatim: None,
|
||||
},
|
||||
NativeLib {
|
||||
|
|
|
|||
|
|
@ -231,7 +231,12 @@ pub(crate) fn run_in_thread_pool_with_globals<
|
|||
.name("rustc query cycle handler".to_string())
|
||||
.spawn(move || {
|
||||
let on_panic = defer(|| {
|
||||
eprintln!("internal compiler error: query cycle handler thread panicked, aborting process");
|
||||
// Split this long string so that it doesn't cause rustfmt to
|
||||
// give up on the entire builder expression.
|
||||
// <https://github.com/rust-lang/rustfmt/issues/3863>
|
||||
const MESSAGE: &str = "\
|
||||
internal compiler error: query cycle handler thread panicked, aborting process";
|
||||
eprintln!("{MESSAGE}");
|
||||
// We need to abort here as we failed to resolve the deadlock,
|
||||
// otherwise the compiler could just hang,
|
||||
process::abort();
|
||||
|
|
@ -244,11 +249,16 @@ pub(crate) fn run_in_thread_pool_with_globals<
|
|||
tls::with(|tcx| {
|
||||
// Accessing session globals is sound as they outlive `GlobalCtxt`.
|
||||
// They are needed to hash query keys containing spans or symbols.
|
||||
let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || {
|
||||
// Ensure there was no errors collecting all active jobs.
|
||||
// We need the complete map to ensure we find a cycle to break.
|
||||
QueryCtxt::new(tcx).collect_active_jobs(false).expect("failed to collect active queries in deadlock handler")
|
||||
});
|
||||
let query_map = rustc_span::set_session_globals_then(
|
||||
unsafe { &*(session_globals as *const SessionGlobals) },
|
||||
|| {
|
||||
// Ensure there were no errors collecting all active jobs.
|
||||
// We need the complete map to ensure we find a cycle to break.
|
||||
QueryCtxt::new(tcx).collect_active_jobs_from_all_queries(false).expect(
|
||||
"failed to collect active queries in deadlock handler",
|
||||
)
|
||||
},
|
||||
);
|
||||
break_query_cycles(query_map, ®istry);
|
||||
})
|
||||
})
|
||||
|
|
@ -351,10 +361,6 @@ pub struct DummyCodegenBackend {
|
|||
}
|
||||
|
||||
impl CodegenBackend for DummyCodegenBackend {
|
||||
fn locale_resource(&self) -> &'static str {
|
||||
""
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"dummy"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,6 +326,14 @@ lint_expectation = this lint expectation is unfulfilled
|
|||
.note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
.rationale = {$rationale}
|
||||
|
||||
lint_expected_name_value =
|
||||
expected this to be of the form `... = "..."`
|
||||
.warn = {-lint_previously_accepted}
|
||||
|
||||
lint_expected_no_args =
|
||||
didn't expect any arguments here
|
||||
.warn = {-lint_previously_accepted}
|
||||
|
||||
lint_for_loops_over_fallibles =
|
||||
for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement
|
||||
.suggestion = consider using `if let` to clear intent
|
||||
|
|
@ -558,6 +566,10 @@ lint_macro_expr_fragment_specifier_2024_migration =
|
|||
|
||||
lint_malformed_attribute = malformed lint attribute input
|
||||
|
||||
lint_malformed_doc =
|
||||
malformed `doc` attribute input
|
||||
.warn = {-lint_previously_accepted}
|
||||
|
||||
lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
|
||||
.note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
|
||||
.function_label = this function returns `()`, which is likely not what you wanted
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use rustc_ast::{BorrowKind, UnOp};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::{Expr, ExprKind, Mutability, find_attr};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref};
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AutoBorrow, DerefAdjustKind, OverloadedDeref,
|
||||
};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
|
||||
use crate::lints::{
|
||||
|
|
@ -165,12 +167,14 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
|
|||
/// an implicit borrow (or has an implicit borrow via an overloaded deref).
|
||||
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> {
|
||||
match kind {
|
||||
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)),
|
||||
&Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { mutbl, .. })) => {
|
||||
Some((mutbl, true))
|
||||
}
|
||||
&Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some((mutbl.into(), false)),
|
||||
Adjust::NeverToAny
|
||||
| Adjust::Pointer(..)
|
||||
| Adjust::ReborrowPin(..)
|
||||
| Adjust::Deref(None)
|
||||
| Adjust::Deref(DerefAdjustKind::Builtin)
|
||||
| Adjust::Borrow(AutoBorrow::RawPtr(..)) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -428,5 +428,11 @@ pub fn decorate_attribute_lint(
|
|||
sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }),
|
||||
}
|
||||
.decorate_lint(diag),
|
||||
|
||||
&AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag),
|
||||
|
||||
&AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.decorate_lint(diag),
|
||||
|
||||
&AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.decorate_lint(diag),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3185,6 +3185,21 @@ pub(crate) struct UnusedDuplicate {
|
|||
pub warning: bool,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_malformed_doc)]
|
||||
#[warning]
|
||||
pub(crate) struct MalformedDoc;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_expected_no_args)]
|
||||
#[warning]
|
||||
pub(crate) struct ExpectedNoArgs;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_expected_name_value)]
|
||||
#[warning]
|
||||
pub(crate) struct ExpectedNameValue;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_unsafe_attr_outside_unsafe)]
|
||||
pub(crate) struct UnsafeAttrOutsideUnsafeLint {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::sym;
|
||||
|
||||
|
|
@ -114,7 +114,10 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
|||
|
||||
// If there is any user defined auto-deref step, then we don't want to warn.
|
||||
// https://github.com/rust-lang/rust-clippy/issues/9272
|
||||
if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) {
|
||||
if arg_adjustments
|
||||
.iter()
|
||||
.any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_))))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1785,7 +1785,7 @@ declare_lint! {
|
|||
declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &hir::Expr<'_>) {
|
||||
match e.kind {
|
||||
hir::ExprKind::Call(path_expr, [_])
|
||||
if let hir::ExprKind::Path(qpath) = &path_expr.kind
|
||||
|
|
@ -1796,6 +1796,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
|
|||
|
||||
for adj in cx.typeck_results().expr_adjustments(e) {
|
||||
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind {
|
||||
if let ty::Ref(_, inner_ty, _) = adj.target.kind()
|
||||
&& inner_ty.is_box()
|
||||
{
|
||||
// If the target type is `&Box<T>` or `&mut Box<T>`, the allocation is necessary
|
||||
continue;
|
||||
}
|
||||
match m {
|
||||
adjustment::AutoBorrowMutability::Not => {
|
||||
cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ declare_lint_pass! {
|
|||
AMBIGUOUS_GLOB_IMPORTED_TRAITS,
|
||||
AMBIGUOUS_GLOB_IMPORTS,
|
||||
AMBIGUOUS_GLOB_REEXPORTS,
|
||||
AMBIGUOUS_IMPORT_VISIBILITIES,
|
||||
AMBIGUOUS_PANIC_IMPORTS,
|
||||
ARITHMETIC_OVERFLOW,
|
||||
ASM_SUB_REGISTER,
|
||||
|
|
@ -3457,7 +3458,7 @@ declare_lint! {
|
|||
/// but this lint was introduced to avoid breaking any existing
|
||||
/// crates which included them.
|
||||
pub INVALID_DOC_ATTRIBUTES,
|
||||
Deny,
|
||||
Warn,
|
||||
"detects invalid `#[doc(...)]` attributes",
|
||||
}
|
||||
|
||||
|
|
@ -4564,6 +4565,55 @@ declare_lint! {
|
|||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ambiguous_import_visibilities` lint detects imports that should report ambiguity
|
||||
/// errors, but previously didn't do that due to rustc bugs.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(unknown_lints)]
|
||||
/// #![deny(ambiguous_import_visibilities)]
|
||||
/// mod reexport {
|
||||
/// mod m {
|
||||
/// pub struct S {}
|
||||
/// }
|
||||
///
|
||||
/// macro_rules! mac {
|
||||
/// () => { use m::S; }
|
||||
/// }
|
||||
///
|
||||
/// pub use m::*;
|
||||
/// mac!();
|
||||
///
|
||||
/// pub use S as Z; // ambiguous visibility
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// reexport::Z {};
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Previous versions of Rust compile it successfully because it
|
||||
/// fetched the glob import's visibility for `pub use S as Z` import, and ignored the private
|
||||
/// `use m::S` import that appeared later.
|
||||
///
|
||||
/// This is a [future-incompatible] lint to transition this to a
|
||||
/// hard error in the future.
|
||||
///
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub AMBIGUOUS_IMPORT_VISIBILITIES,
|
||||
Warn,
|
||||
"detects certain glob imports that require reporting an ambiguity error",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: fcw!(FutureReleaseError #149145),
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `refining_impl_trait_reachable` lint detects `impl Trait` return
|
||||
/// types in method signatures that are refined by a publically reachable
|
||||
|
|
|
|||
|
|
@ -826,6 +826,9 @@ pub enum AttributeLintKind {
|
|||
span: Span,
|
||||
suggested: Option<Symbol>,
|
||||
},
|
||||
MalformedDoc,
|
||||
ExpectedNoArgs,
|
||||
ExpectedNameValue,
|
||||
}
|
||||
|
||||
pub type RegisteredTools = FxIndexSet<Ident>;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ proc-macro = true
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
fluent-bundle = "0.16"
|
||||
fluent-syntax = "0.12"
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2.0.9", features = ["full"] }
|
||||
|
|
|
|||
|
|
@ -22,20 +22,22 @@ impl<'a> DiagnosticDerive<'a> {
|
|||
pub(crate) fn into_tokens(self) -> TokenStream {
|
||||
let DiagnosticDerive { mut structure } = self;
|
||||
let kind = DiagnosticDeriveKind::Diagnostic;
|
||||
let slugs = RefCell::new(Vec::new());
|
||||
let messages = RefCell::new(Vec::new());
|
||||
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
|
||||
let preamble = builder.preamble(variant);
|
||||
let body = builder.body(variant);
|
||||
|
||||
let Some(slug) = builder.primary_message() else {
|
||||
let Some(message) = builder.primary_message() else {
|
||||
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||
};
|
||||
slugs.borrow_mut().push(slug.clone());
|
||||
messages.borrow_mut().push(message.clone());
|
||||
let message = message.diag_message(Some(variant));
|
||||
|
||||
let init = quote! {
|
||||
let mut diag = rustc_errors::Diag::new(
|
||||
dcx,
|
||||
level,
|
||||
crate::fluent_generated::#slug
|
||||
#message
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -66,7 +68,7 @@ impl<'a> DiagnosticDerive<'a> {
|
|||
}
|
||||
}
|
||||
});
|
||||
for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) {
|
||||
for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) {
|
||||
imp.extend(test);
|
||||
}
|
||||
imp
|
||||
|
|
@ -86,17 +88,18 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||
pub(crate) fn into_tokens(self) -> TokenStream {
|
||||
let LintDiagnosticDerive { mut structure } = self;
|
||||
let kind = DiagnosticDeriveKind::LintDiagnostic;
|
||||
let slugs = RefCell::new(Vec::new());
|
||||
let messages = RefCell::new(Vec::new());
|
||||
let implementation = kind.each_variant(&mut structure, |mut builder, variant| {
|
||||
let preamble = builder.preamble(variant);
|
||||
let body = builder.body(variant);
|
||||
|
||||
let Some(slug) = builder.primary_message() else {
|
||||
let Some(message) = builder.primary_message() else {
|
||||
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||
};
|
||||
slugs.borrow_mut().push(slug.clone());
|
||||
messages.borrow_mut().push(message.clone());
|
||||
let message = message.diag_message(Some(variant));
|
||||
let primary_message = quote! {
|
||||
diag.primary_message(crate::fluent_generated::#slug);
|
||||
diag.primary_message(#message);
|
||||
};
|
||||
|
||||
let formatting_init = &builder.formatting_init;
|
||||
|
|
@ -122,47 +125,10 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||
}
|
||||
}
|
||||
});
|
||||
for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) {
|
||||
for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) {
|
||||
imp.extend(test);
|
||||
}
|
||||
|
||||
imp
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a `#[test]` that verifies that all referenced variables
|
||||
/// exist on this structure.
|
||||
fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream {
|
||||
// FIXME: We can't identify variables in a subdiagnostic
|
||||
for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) {
|
||||
for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) {
|
||||
if attr_name == "subdiagnostic" {
|
||||
return quote!();
|
||||
}
|
||||
}
|
||||
}
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
// We need to make sure that the same diagnostic slug can be used multiple times without
|
||||
// causing an error, so just have a global counter here.
|
||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
let slug = slug.get_ident().unwrap();
|
||||
let ident = quote::format_ident!("verify_{slug}_{}", COUNTER.fetch_add(1, Ordering::Relaxed));
|
||||
let ref_slug = quote::format_ident!("{slug}_refs");
|
||||
let struct_name = &structure.ast().ident;
|
||||
let variables: Vec<_> = structure
|
||||
.variants()
|
||||
.iter()
|
||||
.flat_map(|v| v.ast().fields.iter().filter_map(|f| f.ident.as_ref().map(|i| i.to_string())))
|
||||
.collect();
|
||||
// tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this
|
||||
quote! {
|
||||
#[cfg(test)]
|
||||
#[test ]
|
||||
fn #ident() {
|
||||
let variables = [#(#variables),*];
|
||||
for vref in crate::fluent_generated::#ref_slug {
|
||||
assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ use proc_macro2::{Ident, Span, TokenStream};
|
|||
use quote::{format_ident, quote, quote_spanned};
|
||||
use syn::parse::ParseStream;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{Attribute, Meta, Path, Token, Type, parse_quote};
|
||||
use syn::{Attribute, LitStr, Meta, Path, Token, Type, parse_quote};
|
||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||
|
||||
use super::utils::SubdiagnosticVariant;
|
||||
use crate::diagnostics::error::{
|
||||
DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err,
|
||||
};
|
||||
use crate::diagnostics::message::Message;
|
||||
use crate::diagnostics::utils::{
|
||||
FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
|
||||
|
|
@ -41,9 +42,9 @@ pub(crate) struct DiagnosticDeriveVariantBuilder {
|
|||
/// derive builder.
|
||||
pub field_map: FieldMap,
|
||||
|
||||
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
||||
/// Message is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
||||
/// has the actual diagnostic message.
|
||||
pub slug: Option<Path>,
|
||||
pub message: Option<Message>,
|
||||
|
||||
/// Error codes are a optional part of the struct attribute - this is only set to detect
|
||||
/// multiple specifications.
|
||||
|
|
@ -90,7 +91,7 @@ impl DiagnosticDeriveKind {
|
|||
span,
|
||||
field_map: build_field_mapping(variant),
|
||||
formatting_init: TokenStream::new(),
|
||||
slug: None,
|
||||
message: None,
|
||||
code: None,
|
||||
};
|
||||
f(builder, variant)
|
||||
|
|
@ -105,8 +106,8 @@ impl DiagnosticDeriveKind {
|
|||
}
|
||||
|
||||
impl DiagnosticDeriveVariantBuilder {
|
||||
pub(crate) fn primary_message(&self) -> Option<&Path> {
|
||||
match self.slug.as_ref() {
|
||||
pub(crate) fn primary_message(&self) -> Option<&Message> {
|
||||
match self.message.as_ref() {
|
||||
None => {
|
||||
span_err(self.span, "diagnostic slug not specified")
|
||||
.help(
|
||||
|
|
@ -116,7 +117,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
.emit();
|
||||
None
|
||||
}
|
||||
Some(slug)
|
||||
Some(Message::Slug(slug))
|
||||
if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
|
||||
Mismatch::check(slug) =>
|
||||
{
|
||||
|
|
@ -126,7 +127,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
.emit();
|
||||
None
|
||||
}
|
||||
Some(slug) => Some(slug),
|
||||
Some(msg) => Some(msg),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +137,8 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
let ast = variant.ast();
|
||||
let attrs = &ast.attrs;
|
||||
let preamble = attrs.iter().map(|attr| {
|
||||
self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error())
|
||||
self.generate_structure_code_for_attr(attr, variant)
|
||||
.unwrap_or_else(|v| v.to_compile_error())
|
||||
});
|
||||
|
||||
quote! {
|
||||
|
|
@ -154,7 +156,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
}
|
||||
// ..and then subdiagnostic additions.
|
||||
for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) {
|
||||
body.extend(self.generate_field_attrs_code(binding));
|
||||
body.extend(self.generate_field_attrs_code(binding, variant));
|
||||
}
|
||||
body
|
||||
}
|
||||
|
|
@ -163,7 +165,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
fn parse_subdiag_attribute(
|
||||
&self,
|
||||
attr: &Attribute,
|
||||
) -> Result<Option<(SubdiagnosticKind, Path, bool)>, DiagnosticDeriveError> {
|
||||
) -> Result<Option<(SubdiagnosticKind, Message, bool)>, DiagnosticDeriveError> {
|
||||
let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, &self.field_map)? else {
|
||||
// Some attributes aren't errors - like documentation comments - but also aren't
|
||||
// subdiagnostics.
|
||||
|
|
@ -175,15 +177,18 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
.help("consider creating a `Subdiagnostic` instead"));
|
||||
}
|
||||
|
||||
let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind {
|
||||
SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
|
||||
SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
|
||||
SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once },
|
||||
SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
|
||||
SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once },
|
||||
SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn },
|
||||
SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion },
|
||||
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
|
||||
// For subdiagnostics without a message specified, insert a placeholder slug
|
||||
let slug = subdiag.slug.unwrap_or_else(|| {
|
||||
Message::Slug(match subdiag.kind {
|
||||
SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
|
||||
SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
|
||||
SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once },
|
||||
SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
|
||||
SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once },
|
||||
SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn },
|
||||
SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion },
|
||||
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
|
||||
})
|
||||
});
|
||||
|
||||
Ok(Some((subdiag.kind, slug, false)))
|
||||
|
|
@ -195,6 +200,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
fn generate_structure_code_for_attr(
|
||||
&mut self,
|
||||
attr: &Attribute,
|
||||
variant: &VariantInfo<'_>,
|
||||
) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||
// Always allow documentation comments.
|
||||
if is_doc_comment(attr) {
|
||||
|
|
@ -210,13 +216,28 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
let mut input = &*input;
|
||||
let slug_recovery_point = input.fork();
|
||||
|
||||
let slug = input.parse::<Path>()?;
|
||||
if input.is_empty() || input.peek(Token![,]) {
|
||||
self.slug = Some(slug);
|
||||
if input.peek(LitStr) {
|
||||
// Parse an inline message
|
||||
let message = input.parse::<LitStr>()?;
|
||||
if !message.suffix().is_empty() {
|
||||
span_err(
|
||||
message.span().unwrap(),
|
||||
"Inline message is not allowed to have a suffix",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
self.message = Some(Message::Inline(message.span(), message.value()));
|
||||
} else {
|
||||
input = &slug_recovery_point;
|
||||
// Parse a slug
|
||||
let slug = input.parse::<Path>()?;
|
||||
if input.is_empty() || input.peek(Token![,]) {
|
||||
self.message = Some(Message::Slug(slug));
|
||||
} else {
|
||||
input = &slug_recovery_point;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse arguments
|
||||
while !input.is_empty() {
|
||||
input.parse::<Token![,]>()?;
|
||||
// Allow trailing comma
|
||||
|
|
@ -266,7 +287,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
| SubdiagnosticKind::NoteOnce
|
||||
| SubdiagnosticKind::Help
|
||||
| SubdiagnosticKind::HelpOnce
|
||||
| SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug)),
|
||||
| SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug, variant)),
|
||||
SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
|
||||
throw_invalid_attr!(attr, |diag| diag
|
||||
.help("`#[label]` and `#[suggestion]` can only be applied to fields"));
|
||||
|
|
@ -294,7 +315,11 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
|
||||
fn generate_field_attrs_code(
|
||||
&mut self,
|
||||
binding_info: &BindingInfo<'_>,
|
||||
variant: &VariantInfo<'_>,
|
||||
) -> TokenStream {
|
||||
let field = binding_info.ast();
|
||||
let field_binding = &binding_info.binding;
|
||||
|
||||
|
|
@ -333,6 +358,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
attr,
|
||||
FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() },
|
||||
binding,
|
||||
variant
|
||||
)
|
||||
.unwrap_or_else(|v| v.to_compile_error());
|
||||
|
||||
|
|
@ -350,6 +376,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
attr: &Attribute,
|
||||
info: FieldInfo<'_>,
|
||||
binding: TokenStream,
|
||||
variant: &VariantInfo<'_>,
|
||||
) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||
let ident = &attr.path().segments.last().unwrap().ident;
|
||||
let name = ident.to_string();
|
||||
|
|
@ -388,7 +415,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
match subdiag {
|
||||
SubdiagnosticKind::Label => {
|
||||
report_error_if_not_applied_to_span(attr, &info)?;
|
||||
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
|
||||
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant))
|
||||
}
|
||||
SubdiagnosticKind::Note
|
||||
| SubdiagnosticKind::NoteOnce
|
||||
|
|
@ -399,11 +426,11 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
if type_matches_path(inner, &["rustc_span", "Span"])
|
||||
|| type_matches_path(inner, &["rustc_span", "MultiSpan"])
|
||||
{
|
||||
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
|
||||
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant))
|
||||
} else if type_is_unit(inner)
|
||||
|| (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner))
|
||||
{
|
||||
Ok(self.add_subdiagnostic(&fn_ident, slug))
|
||||
Ok(self.add_subdiagnostic(&fn_ident, slug, variant))
|
||||
} else {
|
||||
report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")?
|
||||
}
|
||||
|
|
@ -429,6 +456,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
applicability.set_once(quote! { #static_applicability }, span);
|
||||
}
|
||||
|
||||
let message = slug.diag_message(Some(variant));
|
||||
let applicability = applicability
|
||||
.value()
|
||||
.unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
|
||||
|
|
@ -438,7 +466,7 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
Ok(quote! {
|
||||
diag.span_suggestions_with_style(
|
||||
#span_field,
|
||||
crate::fluent_generated::#slug,
|
||||
#message,
|
||||
#code_field,
|
||||
#applicability,
|
||||
#style
|
||||
|
|
@ -455,22 +483,30 @@ impl DiagnosticDeriveVariantBuilder {
|
|||
&self,
|
||||
field_binding: TokenStream,
|
||||
kind: &Ident,
|
||||
fluent_attr_identifier: Path,
|
||||
message: Message,
|
||||
variant: &VariantInfo<'_>,
|
||||
) -> TokenStream {
|
||||
let fn_name = format_ident!("span_{}", kind);
|
||||
let message = message.diag_message(Some(variant));
|
||||
quote! {
|
||||
diag.#fn_name(
|
||||
#field_binding,
|
||||
crate::fluent_generated::#fluent_attr_identifier
|
||||
#message
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug
|
||||
/// and `fluent_attr_identifier`.
|
||||
fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream {
|
||||
fn add_subdiagnostic(
|
||||
&self,
|
||||
kind: &Ident,
|
||||
message: Message,
|
||||
variant: &VariantInfo<'_>,
|
||||
) -> TokenStream {
|
||||
let message = message.diag_message(Some(variant));
|
||||
quote! {
|
||||
diag.#kind(crate::fluent_generated::#fluent_attr_identifier);
|
||||
diag.#kind(#message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
138
compiler/rustc_macros/src/diagnostics/message.rs
Normal file
138
compiler/rustc_macros/src/diagnostics/message.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
use fluent_bundle::FluentResource;
|
||||
use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::Path;
|
||||
use synstructure::{Structure, VariantInfo};
|
||||
|
||||
use crate::diagnostics::error::span_err;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum Message {
|
||||
Slug(Path),
|
||||
Inline(Span, String),
|
||||
}
|
||||
|
||||
impl Message {
|
||||
/// Get the diagnostic message for this diagnostic
|
||||
/// The passed `variant` is used to check whether all variables in the message are used.
|
||||
/// For subdiagnostics, we cannot check this.
|
||||
pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream {
|
||||
match self {
|
||||
Message::Slug(slug) => {
|
||||
quote! { crate::fluent_generated::#slug }
|
||||
}
|
||||
Message::Inline(message_span, message) => {
|
||||
if let Some(variant) = variant {
|
||||
verify_fluent_message(*message_span, &message, variant);
|
||||
}
|
||||
quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a `#[test]` that verifies that all referenced variables
|
||||
/// exist on this structure.
|
||||
pub(crate) fn generate_test(&self, structure: &Structure<'_>) -> TokenStream {
|
||||
match self {
|
||||
Message::Slug(slug) => {
|
||||
// FIXME: We can't identify variables in a subdiagnostic
|
||||
for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) {
|
||||
for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) {
|
||||
if attr_name == "subdiagnostic" {
|
||||
return quote!();
|
||||
}
|
||||
}
|
||||
}
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
// We need to make sure that the same diagnostic slug can be used multiple times without
|
||||
// causing an error, so just have a global counter here.
|
||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
let slug = slug.get_ident().unwrap();
|
||||
let ident = quote::format_ident!(
|
||||
"verify_{slug}_{}",
|
||||
COUNTER.fetch_add(1, Ordering::Relaxed)
|
||||
);
|
||||
let ref_slug = quote::format_ident!("{slug}_refs");
|
||||
let struct_name = &structure.ast().ident;
|
||||
let variables: Vec<_> = structure
|
||||
.variants()
|
||||
.iter()
|
||||
.flat_map(|v| {
|
||||
v.ast()
|
||||
.fields
|
||||
.iter()
|
||||
.filter_map(|f| f.ident.as_ref().map(|i| i.to_string()))
|
||||
})
|
||||
.collect();
|
||||
// tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this
|
||||
quote! {
|
||||
#[cfg(test)]
|
||||
#[test ]
|
||||
fn #ident() {
|
||||
let variables = [#(#variables),*];
|
||||
for vref in crate::fluent_generated::#ref_slug {
|
||||
assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Inline(..) => {
|
||||
// We don't generate a test for inline diagnostics, we can verify these at compile-time!
|
||||
// This verification is done in the `diag_message` function above
|
||||
quote! {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_fluent_message(msg_span: Span, message: &str, variant: &VariantInfo<'_>) {
|
||||
// Parse the fluent message
|
||||
const GENERATED_MSG_ID: &str = "generated_msg";
|
||||
let resource = FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message}\n")).unwrap();
|
||||
assert_eq!(resource.entries().count(), 1);
|
||||
let Some(fluent_syntax::ast::Entry::Message(message)) = resource.get_entry(0) else {
|
||||
panic!("Did not parse into a message")
|
||||
};
|
||||
|
||||
// Check if all variables are used
|
||||
let fields: Vec<String> = variant
|
||||
.bindings()
|
||||
.iter()
|
||||
.flat_map(|b| b.ast().ident.as_ref())
|
||||
.map(|id| id.to_string())
|
||||
.collect();
|
||||
for variable in variable_references(&message) {
|
||||
if !fields.iter().any(|f| f == variable) {
|
||||
span_err(msg_span.unwrap(), format!("Variable `{variable}` not found in diagnostic "))
|
||||
.help(format!("Available fields: {:?}", fields.join(", ")))
|
||||
.emit();
|
||||
}
|
||||
// assert!(, );
|
||||
}
|
||||
}
|
||||
|
||||
fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> {
|
||||
let mut refs = vec![];
|
||||
if let Some(Pattern { elements }) = &msg.value {
|
||||
for elt in elements {
|
||||
if let PatternElement::Placeable {
|
||||
expression: Expression::Inline(InlineExpression::VariableReference { id }),
|
||||
} = elt
|
||||
{
|
||||
refs.push(id.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
for attr in &msg.attributes {
|
||||
for elt in &attr.value.elements {
|
||||
if let PatternElement::Placeable {
|
||||
expression: Expression::Inline(InlineExpression::VariableReference { id }),
|
||||
} = elt
|
||||
{
|
||||
refs.push(id.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
refs
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
mod diagnostic;
|
||||
mod diagnostic_builder;
|
||||
mod error;
|
||||
mod message;
|
||||
mod subdiagnostic;
|
||||
mod utils;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use super::utils::SubdiagnosticVariant;
|
|||
use crate::diagnostics::error::{
|
||||
DiagnosticDeriveError, invalid_attr, span_err, throw_invalid_attr, throw_span_err,
|
||||
};
|
||||
use crate::diagnostics::message::Message;
|
||||
use crate::diagnostics::utils::{
|
||||
AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption,
|
||||
SubdiagnosticKind, build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident,
|
||||
|
|
@ -182,7 +183,9 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
|
|||
}
|
||||
|
||||
impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
|
||||
fn identify_kind(
|
||||
&mut self,
|
||||
) -> Result<Vec<(SubdiagnosticKind, Message)>, DiagnosticDeriveError> {
|
||||
let mut kind_slugs = vec![];
|
||||
|
||||
for attr in self.variant.ast().attrs {
|
||||
|
|
@ -532,9 +535,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
|||
let mut calls = TokenStream::new();
|
||||
for (kind, slug) in kind_slugs {
|
||||
let message = format_ident!("__message");
|
||||
calls.extend(
|
||||
quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); },
|
||||
);
|
||||
let message_stream = slug.diag_message(None);
|
||||
calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); });
|
||||
|
||||
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
|
||||
let call = match kind {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use super::error::invalid_attr;
|
|||
use crate::diagnostics::error::{
|
||||
DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err,
|
||||
};
|
||||
use crate::diagnostics::message::Message;
|
||||
|
||||
thread_local! {
|
||||
pub(crate) static CODE_IDENT_COUNT: RefCell<u32> = RefCell::new(0);
|
||||
|
|
@ -587,7 +588,7 @@ pub(super) enum SubdiagnosticKind {
|
|||
|
||||
pub(super) struct SubdiagnosticVariant {
|
||||
pub(super) kind: SubdiagnosticKind,
|
||||
pub(super) slug: Option<Path>,
|
||||
pub(super) slug: Option<Message>,
|
||||
}
|
||||
|
||||
impl SubdiagnosticVariant {
|
||||
|
|
@ -696,11 +697,31 @@ impl SubdiagnosticVariant {
|
|||
list.parse_args_with(|input: ParseStream<'_>| {
|
||||
let mut is_first = true;
|
||||
while !input.is_empty() {
|
||||
// Try to parse an inline diagnostic message
|
||||
if input.peek(LitStr) {
|
||||
let message = input.parse::<LitStr>()?;
|
||||
if !message.suffix().is_empty() {
|
||||
span_err(
|
||||
message.span().unwrap(),
|
||||
"Inline message is not allowed to have a suffix",
|
||||
).emit();
|
||||
}
|
||||
if !input.is_empty() { input.parse::<Token![,]>()?; }
|
||||
if is_first {
|
||||
slug = Some(Message::Inline(message.span(), message.value()));
|
||||
is_first = false;
|
||||
} else {
|
||||
span_err(message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit();
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Try to parse a slug instead
|
||||
let arg_name: Path = input.parse::<Path>()?;
|
||||
let arg_name_span = arg_name.span().unwrap();
|
||||
if input.is_empty() || input.parse::<Token![,]>().is_ok() {
|
||||
if is_first {
|
||||
slug = Some(arg_name);
|
||||
slug = Some(Message::Slug(arg_name));
|
||||
is_first = false;
|
||||
} else {
|
||||
span_err(arg_name_span, "a diagnostic slug must be the first argument to the attribute").emit();
|
||||
|
|
@ -709,6 +730,7 @@ impl SubdiagnosticVariant {
|
|||
}
|
||||
is_first = false;
|
||||
|
||||
// Try to parse an argument
|
||||
match (arg_name.require_ident()?.to_string().as_str(), &mut kind) {
|
||||
("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
|
||||
let code_init = build_suggestion_code(
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ fn add_query_desc_cached_impl(
|
|||
cached.extend(quote! {
|
||||
#[allow(unused_variables, unused_braces, rustc::pass_by_value)]
|
||||
#[inline]
|
||||
pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool {
|
||||
pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::queries::#name::Key<'tcx>) -> bool {
|
||||
#ra_hint
|
||||
#expr
|
||||
}
|
||||
|
|
@ -301,11 +301,9 @@ fn add_query_desc_cached_impl(
|
|||
|
||||
let desc = quote! {
|
||||
#[allow(unused_variables)]
|
||||
pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String {
|
||||
pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::queries::#name::Key<'tcx>) -> String {
|
||||
let (#tcx, #key) = (tcx, key);
|
||||
::rustc_middle::ty::print::with_no_trimmed_paths!(
|
||||
format!(#desc)
|
||||
)
|
||||
format!(#desc)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -359,6 +357,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
|
|||
no_hash,
|
||||
anon,
|
||||
eval_always,
|
||||
feedable,
|
||||
depth_limit,
|
||||
separate_provide_extern,
|
||||
return_result_from_ensure_ok,
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ fn find_bundled_library(
|
|||
tcx: TyCtxt<'_>,
|
||||
) -> Option<Symbol> {
|
||||
let sess = tcx.sess;
|
||||
if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind
|
||||
if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive, .. } = kind
|
||||
&& tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib))
|
||||
&& (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ use rustc_middle::bug;
|
|||
use rustc_middle::metadata::{AmbigModChild, ModChild};
|
||||
use rustc_middle::middle::exported_symbols::ExportedSymbol;
|
||||
use rustc_middle::middle::stability::DeprecationEntry;
|
||||
use rustc_middle::query::{ExternProviders, LocalCrate};
|
||||
use rustc_middle::queries::ExternProviders;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::util::Providers;
|
||||
|
|
@ -134,8 +135,8 @@ macro_rules! provide_one {
|
|||
($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => {
|
||||
fn $name<'tcx>(
|
||||
$tcx: TyCtxt<'tcx>,
|
||||
def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>,
|
||||
) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> {
|
||||
def_id_arg: rustc_middle::queries::$name::Key<'tcx>,
|
||||
) -> rustc_middle::queries::$name::ProvidedValue<'tcx> {
|
||||
let _prof_timer =
|
||||
$tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ mod values;
|
|||
#[macro_use]
|
||||
pub mod query;
|
||||
#[macro_use]
|
||||
pub mod queries;
|
||||
#[macro_use]
|
||||
pub mod dep_graph;
|
||||
|
||||
// Allows macros to refer to this crate as `::rustc_middle`
|
||||
|
|
|
|||
|
|
@ -441,6 +441,8 @@ impl<'tcx> Place<'tcx> {
|
|||
where
|
||||
D: ?Sized + HasLocalDecls<'tcx>,
|
||||
{
|
||||
// If there's a field projection element in `projection`, we *could* skip everything
|
||||
// before that, but on 2026-01-31 a perf experiment showed no benefit from doing so.
|
||||
PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection)
|
||||
}
|
||||
|
||||
|
|
|
|||
2775
compiler/rustc_middle/src/queries.rs
Normal file
2775
compiler/rustc_middle/src/queries.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -15,7 +15,7 @@ use rustc_span::source_map::Spanned;
|
|||
|
||||
use crate::mir::interpret::EvalToValTreeResult;
|
||||
use crate::mir::mono::{MonoItem, NormalizationErrorInMono};
|
||||
use crate::query::CyclePlaceholder;
|
||||
use crate::query::plumbing::CyclePlaceholder;
|
||||
use crate::traits::solve;
|
||||
use crate::ty::adjustment::CoerceUnsizedInfo;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue