commit
a46ccba167
802 changed files with 20840 additions and 10369 deletions
59
Cargo.lock
59
Cargo.lock
|
|
@ -1843,9 +1843,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.1"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
|
@ -1935,9 +1935,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.131"
|
||||
version = "0.2.135"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
|
||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -3569,6 +3569,32 @@ dependencies = [
|
|||
"rustc_target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_hir_typeck"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_graphviz",
|
||||
"rustc_hir",
|
||||
"rustc_hir_analysis",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_lint",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_trait_selection",
|
||||
"rustc_type_ir",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_incremental"
|
||||
version = "0.0.0"
|
||||
|
|
@ -3638,6 +3664,7 @@ dependencies = [
|
|||
"rustc_expand",
|
||||
"rustc_hir",
|
||||
"rustc_hir_analysis",
|
||||
"rustc_hir_typeck",
|
||||
"rustc_incremental",
|
||||
"rustc_lint",
|
||||
"rustc_macros",
|
||||
|
|
@ -4449,9 +4476,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.143"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
|
@ -4468,9 +4495,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.143"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -4954,16 +4981,26 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.14.3"
|
||||
name = "toml_datetime"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba98375fd631b83696f87c64e4ed8e29e6a1f3404d6aed95fa95163bad38e705"
|
||||
checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646"
|
||||
dependencies = [
|
||||
"combine",
|
||||
"indexmap",
|
||||
"itertools",
|
||||
"kstring",
|
||||
"serde",
|
||||
"toml_datetime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(unix_sigpipe)]
|
||||
|
||||
// A note about jemalloc: rustc uses jemalloc when built for CI and
|
||||
// distribution. The obvious way to do this is with the `#[global_allocator]`
|
||||
// mechanism. However, for complicated reasons (see
|
||||
|
|
@ -23,6 +25,7 @@
|
|||
// libraries. So we must reference jemalloc symbols one way or another, because
|
||||
// this file is the only object code in the rustc executable.
|
||||
|
||||
#[unix_sigpipe = "sig_dfl"]
|
||||
fn main() {
|
||||
// See the comment at the top of this file for an explanation of this.
|
||||
#[cfg(feature = "jemalloc-sys")]
|
||||
|
|
@ -58,6 +61,5 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
rustc_driver::set_sigpipe_handler();
|
||||
rustc_driver::main()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
use rustc_errors::{
|
||||
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay,
|
||||
SubdiagnosticMessage,
|
||||
};
|
||||
use rustc_errors::DiagnosticArgFromDisplay;
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
|
||||
#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
|
||||
pub struct GenericTypeWithParentheses {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -15,27 +12,17 @@ pub struct GenericTypeWithParentheses {
|
|||
pub sub: Option<UseAngleBrackets>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Subdiagnostic)]
|
||||
#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")]
|
||||
pub struct UseAngleBrackets {
|
||||
#[suggestion_part(code = "<")]
|
||||
pub open_param: Span,
|
||||
#[suggestion_part(code = ">")]
|
||||
pub close_param: Span,
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for UseAngleBrackets {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.multipart_suggestion(
|
||||
fluent::ast_lowering::use_angle_brackets,
|
||||
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering::invalid_abi, code = "E0703")]
|
||||
#[diag(ast_lowering_invalid_abi, code = "E0703")]
|
||||
#[note]
|
||||
pub struct InvalidAbi {
|
||||
#[primary_span]
|
||||
|
|
@ -49,7 +36,7 @@ pub struct InvalidAbi {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
ast_lowering::invalid_abi_suggestion,
|
||||
ast_lowering_invalid_abi_suggestion,
|
||||
code = "{suggestion}",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
|
|
@ -60,7 +47,7 @@ pub struct InvalidAbiSuggestion {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::assoc_ty_parentheses)]
|
||||
#[diag(ast_lowering_assoc_ty_parentheses)]
|
||||
pub struct AssocTyParentheses {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -68,34 +55,24 @@ pub struct AssocTyParentheses {
|
|||
pub sub: AssocTyParenthesesSub,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Subdiagnostic)]
|
||||
pub enum AssocTyParenthesesSub {
|
||||
Empty { parentheses_span: Span },
|
||||
NotEmpty { open_param: Span, close_param: Span },
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for AssocTyParenthesesSub {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
match self {
|
||||
Self::Empty { parentheses_span } => diag.multipart_suggestion(
|
||||
fluent::ast_lowering::remove_parentheses,
|
||||
vec![(parentheses_span, String::new())],
|
||||
Applicability::MaybeIncorrect,
|
||||
),
|
||||
Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion(
|
||||
fluent::ast_lowering::use_angle_brackets,
|
||||
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
|
||||
Applicability::MaybeIncorrect,
|
||||
),
|
||||
};
|
||||
}
|
||||
#[multipart_suggestion(ast_lowering_remove_parentheses)]
|
||||
Empty {
|
||||
#[suggestion_part(code = "")]
|
||||
parentheses_span: Span,
|
||||
},
|
||||
#[multipart_suggestion(ast_lowering_use_angle_brackets)]
|
||||
NotEmpty {
|
||||
#[suggestion_part(code = "<")]
|
||||
open_param: Span,
|
||||
#[suggestion_part(code = ">")]
|
||||
close_param: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")]
|
||||
#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
|
||||
pub struct MisplacedImplTrait<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -103,14 +80,14 @@ pub struct MisplacedImplTrait<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::rustc_box_attribute_error)]
|
||||
#[diag(ast_lowering_rustc_box_attribute_error)]
|
||||
pub struct RustcBoxAttributeError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::underscore_expr_lhs_assign)]
|
||||
#[diag(ast_lowering_underscore_expr_lhs_assign)]
|
||||
pub struct UnderscoreExprLhsAssign {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -118,7 +95,7 @@ pub struct UnderscoreExprLhsAssign {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::base_expression_double_dot)]
|
||||
#[diag(ast_lowering_base_expression_double_dot)]
|
||||
pub struct BaseExpressionDoubleDot {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -126,24 +103,24 @@ pub struct BaseExpressionDoubleDot {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")]
|
||||
#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
|
||||
pub struct AwaitOnlyInAsyncFnAndBlocks {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub dot_await_span: Span,
|
||||
#[label(ast_lowering::this_not_async)]
|
||||
#[label(ast_lowering_this_not_async)]
|
||||
pub item_span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")]
|
||||
#[diag(ast_lowering_generator_too_many_parameters, code = "E0628")]
|
||||
pub struct GeneratorTooManyParameters {
|
||||
#[primary_span]
|
||||
pub fn_decl_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")]
|
||||
#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
|
||||
pub struct ClosureCannotBeStatic {
|
||||
#[primary_span]
|
||||
pub fn_decl_span: Span,
|
||||
|
|
@ -151,14 +128,14 @@ pub struct ClosureCannotBeStatic {
|
|||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[help]
|
||||
#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")]
|
||||
#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
|
||||
pub struct AsyncNonMoveClosureNotSupported {
|
||||
#[primary_span]
|
||||
pub fn_decl_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::functional_record_update_destructuring_assignment)]
|
||||
#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
|
||||
pub struct FunctionalRecordUpdateDestructuringAssignemnt {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||
|
|
@ -166,28 +143,28 @@ pub struct FunctionalRecordUpdateDestructuringAssignemnt {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::async_generators_not_supported, code = "E0727")]
|
||||
#[diag(ast_lowering_async_generators_not_supported, code = "E0727")]
|
||||
pub struct AsyncGeneratorsNotSupported {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")]
|
||||
#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
|
||||
pub struct InlineAsmUnsupportedTarget {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::att_syntax_only_x86)]
|
||||
#[diag(ast_lowering_att_syntax_only_x86)]
|
||||
pub struct AttSyntaxOnlyX86 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::abi_specified_multiple_times)]
|
||||
#[diag(ast_lowering_abi_specified_multiple_times)]
|
||||
pub struct AbiSpecifiedMultipleTimes {
|
||||
#[primary_span]
|
||||
pub abi_span: Span,
|
||||
|
|
@ -199,7 +176,7 @@ pub struct AbiSpecifiedMultipleTimes {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::clobber_abi_not_supported)]
|
||||
#[diag(ast_lowering_clobber_abi_not_supported)]
|
||||
pub struct ClobberAbiNotSupported {
|
||||
#[primary_span]
|
||||
pub abi_span: Span,
|
||||
|
|
@ -207,7 +184,7 @@ pub struct ClobberAbiNotSupported {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[note]
|
||||
#[diag(ast_lowering::invalid_abi_clobber_abi)]
|
||||
#[diag(ast_lowering_invalid_abi_clobber_abi)]
|
||||
pub struct InvalidAbiClobberAbi {
|
||||
#[primary_span]
|
||||
pub abi_span: Span,
|
||||
|
|
@ -215,7 +192,7 @@ pub struct InvalidAbiClobberAbi {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_register)]
|
||||
#[diag(ast_lowering_invalid_register)]
|
||||
pub struct InvalidRegister<'a> {
|
||||
#[primary_span]
|
||||
pub op_span: Span,
|
||||
|
|
@ -224,7 +201,7 @@ pub struct InvalidRegister<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_register_class)]
|
||||
#[diag(ast_lowering_invalid_register_class)]
|
||||
pub struct InvalidRegisterClass<'a> {
|
||||
#[primary_span]
|
||||
pub op_span: Span,
|
||||
|
|
@ -233,12 +210,12 @@ pub struct InvalidRegisterClass<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)]
|
||||
#[diag(ast_lowering_invalid_asm_template_modifier_reg_class)]
|
||||
pub struct InvalidAsmTemplateModifierRegClass {
|
||||
#[primary_span]
|
||||
#[label(ast_lowering::template_modifier)]
|
||||
#[label(ast_lowering_template_modifier)]
|
||||
pub placeholder_span: Span,
|
||||
#[label(ast_lowering::argument)]
|
||||
#[label(ast_lowering_argument)]
|
||||
pub op_span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: InvalidAsmTemplateModifierRegClassSub,
|
||||
|
|
@ -246,34 +223,34 @@ pub struct InvalidAsmTemplateModifierRegClass {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum InvalidAsmTemplateModifierRegClassSub {
|
||||
#[note(ast_lowering::support_modifiers)]
|
||||
#[note(ast_lowering_support_modifiers)]
|
||||
SupportModifier { class_name: Symbol, modifiers: String },
|
||||
#[note(ast_lowering::does_not_support_modifiers)]
|
||||
#[note(ast_lowering_does_not_support_modifiers)]
|
||||
DoesNotSupportModifier { class_name: Symbol },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_asm_template_modifier_const)]
|
||||
#[diag(ast_lowering_invalid_asm_template_modifier_const)]
|
||||
pub struct InvalidAsmTemplateModifierConst {
|
||||
#[primary_span]
|
||||
#[label(ast_lowering::template_modifier)]
|
||||
#[label(ast_lowering_template_modifier)]
|
||||
pub placeholder_span: Span,
|
||||
#[label(ast_lowering::argument)]
|
||||
#[label(ast_lowering_argument)]
|
||||
pub op_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::invalid_asm_template_modifier_sym)]
|
||||
#[diag(ast_lowering_invalid_asm_template_modifier_sym)]
|
||||
pub struct InvalidAsmTemplateModifierSym {
|
||||
#[primary_span]
|
||||
#[label(ast_lowering::template_modifier)]
|
||||
#[label(ast_lowering_template_modifier)]
|
||||
pub placeholder_span: Span,
|
||||
#[label(ast_lowering::argument)]
|
||||
#[label(ast_lowering_argument)]
|
||||
pub op_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::register_class_only_clobber)]
|
||||
#[diag(ast_lowering_register_class_only_clobber)]
|
||||
pub struct RegisterClassOnlyClobber {
|
||||
#[primary_span]
|
||||
pub op_span: Span,
|
||||
|
|
@ -281,12 +258,12 @@ pub struct RegisterClassOnlyClobber {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::register_conflict)]
|
||||
#[diag(ast_lowering_register_conflict)]
|
||||
pub struct RegisterConflict<'a> {
|
||||
#[primary_span]
|
||||
#[label(ast_lowering::register1)]
|
||||
#[label(ast_lowering_register1)]
|
||||
pub op_span1: Span,
|
||||
#[label(ast_lowering::register2)]
|
||||
#[label(ast_lowering_register2)]
|
||||
pub op_span2: Span,
|
||||
pub reg1_name: &'a str,
|
||||
pub reg2_name: &'a str,
|
||||
|
|
@ -296,12 +273,12 @@ pub struct RegisterConflict<'a> {
|
|||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[help]
|
||||
#[diag(ast_lowering::sub_tuple_binding)]
|
||||
#[diag(ast_lowering_sub_tuple_binding)]
|
||||
pub struct SubTupleBinding<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[suggestion_verbose(
|
||||
ast_lowering::sub_tuple_binding_suggestion,
|
||||
ast_lowering_sub_tuple_binding_suggestion,
|
||||
code = "..",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
|
|
@ -312,56 +289,56 @@ pub struct SubTupleBinding<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::extra_double_dot)]
|
||||
#[diag(ast_lowering_extra_double_dot)]
|
||||
pub struct ExtraDoubleDot<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(ast_lowering::previously_used_here)]
|
||||
#[label(ast_lowering_previously_used_here)]
|
||||
pub prev_span: Span,
|
||||
pub ctx: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[note]
|
||||
#[diag(ast_lowering::misplaced_double_dot)]
|
||||
#[diag(ast_lowering_misplaced_double_dot)]
|
||||
pub struct MisplacedDoubleDot {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::misplaced_relax_trait_bound)]
|
||||
#[diag(ast_lowering_misplaced_relax_trait_bound)]
|
||||
pub struct MisplacedRelaxTraitBound {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)]
|
||||
#[diag(ast_lowering_not_supported_for_lifetime_binder_async_closure)]
|
||||
pub struct NotSupportedForLifetimeBinderAsyncClosure {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::arbitrary_expression_in_pattern)]
|
||||
#[diag(ast_lowering_arbitrary_expression_in_pattern)]
|
||||
pub struct ArbitraryExpressionInPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::inclusive_range_with_no_end)]
|
||||
#[diag(ast_lowering_inclusive_range_with_no_end)]
|
||||
pub struct InclusiveRangeWithNoEnd {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
#[diag(ast_lowering::trait_fn_async, code = "E0706")]
|
||||
#[diag(ast_lowering_trait_fn_async, code = "E0706")]
|
||||
#[note]
|
||||
#[note(ast_lowering::note2)]
|
||||
#[note(note2)]
|
||||
pub struct TraitFnAsync {
|
||||
#[primary_span]
|
||||
pub fn_span: Span,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_ast::*;
|
|||
use rustc_ast_pretty::pprust::{self, State};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
|
||||
use rustc_macros::Subdiagnostic;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::lint::builtin::{
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
|
|
@ -169,7 +170,7 @@ impl<'a> AstValidator<'a> {
|
|||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||
id,
|
||||
where_clauses.0.1,
|
||||
fluent::ast_passes::deprecated_where_clause_location,
|
||||
fluent::ast_passes_deprecated_where_clause_location,
|
||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
|
||||
where_clauses.1.1.shrink_to_hi(),
|
||||
suggestion,
|
||||
|
|
@ -251,20 +252,6 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
|
||||
if let Some(ident) = field.ident {
|
||||
if ident.name == kw::Underscore {
|
||||
self.visit_vis(&field.vis);
|
||||
self.visit_ident(ident);
|
||||
self.visit_ty_common(&field.ty);
|
||||
self.walk_ty(&field.ty);
|
||||
walk_list!(self, visit_attribute, &field.attrs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.visit_field_def(field);
|
||||
}
|
||||
|
||||
fn err_handler(&self) -> &rustc_errors::Handler {
|
||||
&self.session.diagnostic()
|
||||
}
|
||||
|
|
@ -1005,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
visit::walk_lifetime(self, lifetime);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'a FieldDef) {
|
||||
visit::walk_field_def(self, s)
|
||||
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
||||
visit::walk_field_def(self, field)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &'a Item) {
|
||||
|
|
@ -1194,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_mod_file_item_asciionly(item.ident);
|
||||
}
|
||||
}
|
||||
ItemKind::Struct(ref vdata, ref generics) => match vdata {
|
||||
// Duplicating the `Visitor` logic allows catching all cases
|
||||
// of `Anonymous(Struct, Union)` outside of a field struct or union.
|
||||
//
|
||||
// Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
|
||||
// encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
|
||||
// it uses `visit_ty_common`, which doesn't contain that specific check.
|
||||
VariantData::Struct(ref fields, ..) => {
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
self.visit_generics(generics);
|
||||
self.with_banned_assoc_ty_bound(|this| {
|
||||
walk_list!(this, visit_struct_field_def, fields);
|
||||
});
|
||||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
ItemKind::Union(ref vdata, ref generics) => {
|
||||
ItemKind::Union(ref vdata, ..) => {
|
||||
if vdata.fields().is_empty() {
|
||||
self.err_handler().span_err(item.span, "unions cannot have zero fields");
|
||||
}
|
||||
match vdata {
|
||||
VariantData::Struct(ref fields, ..) => {
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
self.visit_generics(generics);
|
||||
self.with_banned_assoc_ty_bound(|this| {
|
||||
walk_list!(this, visit_struct_field_def, fields);
|
||||
});
|
||||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ItemKind::Const(def, .., None) => {
|
||||
self.check_defaultness(item.span, def);
|
||||
|
|
@ -1805,15 +1760,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
|
|||
}
|
||||
|
||||
/// Used to forbid `let` expressions in certain syntactic locations.
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Subdiagnostic)]
|
||||
pub(crate) enum ForbiddenLetReason {
|
||||
/// `let` is not valid and the source environment is not important
|
||||
GenericForbidden,
|
||||
/// A let chain with the `||` operator
|
||||
NotSupportedOr(Span),
|
||||
#[note(not_supported_or)]
|
||||
NotSupportedOr(#[primary_span] Span),
|
||||
/// A let chain with invalid parentheses
|
||||
///
|
||||
/// For example, `let 1 = 1 && (expr && expr)` is allowed
|
||||
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
|
||||
NotSupportedParentheses(Span),
|
||||
#[note(not_supported_parentheses)]
|
||||
NotSupportedParentheses(#[primary_span] Span),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_span::{Span, Symbol};
|
|||
use crate::ast_validation::ForbiddenLetReason;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_let)]
|
||||
#[diag(ast_passes_forbidden_let)]
|
||||
#[note]
|
||||
pub struct ForbiddenLet {
|
||||
#[primary_span]
|
||||
|
|
@ -16,25 +16,8 @@ pub struct ForbiddenLet {
|
|||
pub(crate) reason: ForbiddenLetReason,
|
||||
}
|
||||
|
||||
impl AddToDiagnostic for ForbiddenLetReason {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
match self {
|
||||
Self::GenericForbidden => {}
|
||||
Self::NotSupportedOr(span) => {
|
||||
diag.span_note(span, fluent::ast_passes::not_supported_or);
|
||||
}
|
||||
Self::NotSupportedParentheses(span) => {
|
||||
diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_let_stable)]
|
||||
#[diag(ast_passes_forbidden_let_stable)]
|
||||
#[note]
|
||||
pub struct ForbiddenLetStable {
|
||||
#[primary_span]
|
||||
|
|
@ -42,21 +25,21 @@ pub struct ForbiddenLetStable {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_assoc_constraint)]
|
||||
#[diag(ast_passes_forbidden_assoc_constraint)]
|
||||
pub struct ForbiddenAssocConstraint {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::keyword_lifetime)]
|
||||
#[diag(ast_passes_keyword_lifetime)]
|
||||
pub struct KeywordLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::invalid_label)]
|
||||
#[diag(ast_passes_invalid_label)]
|
||||
pub struct InvalidLabel {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -64,11 +47,11 @@ pub struct InvalidLabel {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::invalid_visibility, code = "E0449")]
|
||||
#[diag(ast_passes_invalid_visibility, code = "E0449")]
|
||||
pub struct InvalidVisibility {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label(ast_passes::implied)]
|
||||
#[label(implied)]
|
||||
pub implied: Option<Span>,
|
||||
#[subdiagnostic]
|
||||
pub note: Option<InvalidVisibilityNote>,
|
||||
|
|
@ -76,14 +59,14 @@ pub struct InvalidVisibility {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum InvalidVisibilityNote {
|
||||
#[note(ast_passes::individual_impl_items)]
|
||||
#[note(individual_impl_items)]
|
||||
IndividualImplItems,
|
||||
#[note(ast_passes::individual_foreign_items)]
|
||||
#[note(individual_foreign_items)]
|
||||
IndividualForeignItems,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::trait_fn_const, code = "E0379")]
|
||||
#[diag(ast_passes_trait_fn_const, code = "E0379")]
|
||||
pub struct TraitFnConst {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -91,21 +74,21 @@ pub struct TraitFnConst {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_lifetime_bound)]
|
||||
#[diag(ast_passes_forbidden_lifetime_bound)]
|
||||
pub struct ForbiddenLifetimeBound {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_non_lifetime_param)]
|
||||
#[diag(ast_passes_forbidden_non_lifetime_param)]
|
||||
pub struct ForbiddenNonLifetimeParam {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_too_many)]
|
||||
#[diag(ast_passes_fn_param_too_many)]
|
||||
pub struct FnParamTooMany {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -113,21 +96,21 @@ pub struct FnParamTooMany {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_c_var_args_only)]
|
||||
#[diag(ast_passes_fn_param_c_var_args_only)]
|
||||
pub struct FnParamCVarArgsOnly {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_c_var_args_not_last)]
|
||||
#[diag(ast_passes_fn_param_c_var_args_not_last)]
|
||||
pub struct FnParamCVarArgsNotLast {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_doc_comment)]
|
||||
#[diag(ast_passes_fn_param_doc_comment)]
|
||||
pub struct FnParamDocComment {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -135,14 +118,14 @@ pub struct FnParamDocComment {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_forbidden_attr)]
|
||||
#[diag(ast_passes_fn_param_forbidden_attr)]
|
||||
pub struct FnParamForbiddenAttr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_param_forbidden_self)]
|
||||
#[diag(ast_passes_fn_param_forbidden_self)]
|
||||
#[note]
|
||||
pub struct FnParamForbiddenSelf {
|
||||
#[primary_span]
|
||||
|
|
@ -151,7 +134,7 @@ pub struct FnParamForbiddenSelf {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::forbidden_default)]
|
||||
#[diag(ast_passes_forbidden_default)]
|
||||
pub struct ForbiddenDefault {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -160,7 +143,7 @@ pub struct ForbiddenDefault {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::assoc_const_without_body)]
|
||||
#[diag(ast_passes_assoc_const_without_body)]
|
||||
pub struct AssocConstWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -169,7 +152,7 @@ pub struct AssocConstWithoutBody {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::assoc_fn_without_body)]
|
||||
#[diag(ast_passes_assoc_fn_without_body)]
|
||||
pub struct AssocFnWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -178,7 +161,7 @@ pub struct AssocFnWithoutBody {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::assoc_type_without_body)]
|
||||
#[diag(ast_passes_assoc_type_without_body)]
|
||||
pub struct AssocTypeWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -187,7 +170,7 @@ pub struct AssocTypeWithoutBody {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::const_without_body)]
|
||||
#[diag(ast_passes_const_without_body)]
|
||||
pub struct ConstWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -196,7 +179,7 @@ pub struct ConstWithoutBody {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::static_without_body)]
|
||||
#[diag(ast_passes_static_without_body)]
|
||||
pub struct StaticWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -205,7 +188,7 @@ pub struct StaticWithoutBody {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::ty_alias_without_body)]
|
||||
#[diag(ast_passes_ty_alias_without_body)]
|
||||
pub struct TyAliasWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -214,7 +197,7 @@ pub struct TyAliasWithoutBody {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes::fn_without_body)]
|
||||
#[diag(ast_passes_fn_without_body)]
|
||||
pub struct FnWithoutBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -243,7 +226,7 @@ impl AddToDiagnostic for ExternBlockSuggestion {
|
|||
let end_suggestion = " }".to_owned();
|
||||
|
||||
diag.multipart_suggestion(
|
||||
fluent::ast_passes::extern_block_suggestion,
|
||||
fluent::extern_block_suggestion,
|
||||
vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ use rustc_span::{Span, Symbol};
|
|||
use crate::UnsupportedLiteralReason;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expected_one_cfg_pattern, code = "E0536")]
|
||||
#[diag(attr_expected_one_cfg_pattern, code = "E0536")]
|
||||
pub(crate) struct ExpectedOneCfgPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_predicate, code = "E0537")]
|
||||
#[diag(attr_invalid_predicate, code = "E0537")]
|
||||
pub(crate) struct InvalidPredicate {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -26,7 +26,7 @@ pub(crate) struct InvalidPredicate {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::multiple_item, code = "E0538")]
|
||||
#[diag(attr_multiple_item, code = "E0538")]
|
||||
pub(crate) struct MultipleItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -35,7 +35,7 @@ pub(crate) struct MultipleItem {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_meta_item, code = "E0539")]
|
||||
#[diag(attr_incorrect_meta_item, code = "E0539")]
|
||||
pub(crate) struct IncorrectMetaItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -54,39 +54,39 @@ impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
|
|||
let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
|
||||
let mut diag = handler.struct_span_err_with_code(
|
||||
self.span,
|
||||
fluent::attr::unknown_meta_item,
|
||||
fluent::attr_unknown_meta_item,
|
||||
error_code!(E0541),
|
||||
);
|
||||
diag.set_arg("item", self.item);
|
||||
diag.set_arg("expected", expected.join(", "));
|
||||
diag.span_label(self.span, fluent::attr::label);
|
||||
diag.span_label(self.span, fluent::label);
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_since, code = "E0542")]
|
||||
#[diag(attr_missing_since, code = "E0542")]
|
||||
pub(crate) struct MissingSince {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_note, code = "E0543")]
|
||||
#[diag(attr_missing_note, code = "E0543")]
|
||||
pub(crate) struct MissingNote {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::multiple_stability_levels, code = "E0544")]
|
||||
#[diag(attr_multiple_stability_levels, code = "E0544")]
|
||||
pub(crate) struct MultipleStabilityLevels {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_issue_string, code = "E0545")]
|
||||
#[diag(attr_invalid_issue_string, code = "E0545")]
|
||||
pub(crate) struct InvalidIssueString {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -99,31 +99,31 @@ pub(crate) struct InvalidIssueString {
|
|||
// translatable.
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum InvalidIssueStringCause {
|
||||
#[label(attr::must_not_be_zero)]
|
||||
#[label(must_not_be_zero)]
|
||||
MustNotBeZero {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr::empty)]
|
||||
#[label(empty)]
|
||||
Empty {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr::invalid_digit)]
|
||||
#[label(invalid_digit)]
|
||||
InvalidDigit {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr::pos_overflow)]
|
||||
#[label(pos_overflow)]
|
||||
PosOverflow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr::neg_overflow)]
|
||||
#[label(neg_overflow)]
|
||||
NegOverflow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -144,21 +144,21 @@ impl InvalidIssueStringCause {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_feature, code = "E0546")]
|
||||
#[diag(attr_missing_feature, code = "E0546")]
|
||||
pub(crate) struct MissingFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::non_ident_feature, code = "E0546")]
|
||||
#[diag(attr_non_ident_feature, code = "E0546")]
|
||||
pub(crate) struct NonIdentFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::missing_issue, code = "E0547")]
|
||||
#[diag(attr_missing_issue, code = "E0547")]
|
||||
pub(crate) struct MissingIssue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -167,7 +167,7 @@ pub(crate) struct MissingIssue {
|
|||
// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
|
||||
// changing this to `IncorrectMetaItem`. See #51489.
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_meta_item, code = "E0551")]
|
||||
#[diag(attr_incorrect_meta_item, code = "E0551")]
|
||||
pub(crate) struct IncorrectMetaItem2 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -176,14 +176,14 @@ pub(crate) struct IncorrectMetaItem2 {
|
|||
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
|
||||
// It is more similar to `IncorrectReprFormatGeneric`.
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
|
||||
#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
|
||||
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")]
|
||||
#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
|
||||
pub(crate) struct InvalidReprHintNoParen {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -192,7 +192,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_hint_no_value, code = "E0552")]
|
||||
#[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
|
||||
pub(crate) struct InvalidReprHintNoValue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -213,13 +213,13 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
|||
let mut diag = handler.struct_span_err_with_code(
|
||||
self.span,
|
||||
match self.reason {
|
||||
UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic,
|
||||
UnsupportedLiteralReason::CfgString => fluent::attr::unsupported_literal_cfg_string,
|
||||
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
||||
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
||||
UnsupportedLiteralReason::DeprecatedString => {
|
||||
fluent::attr::unsupported_literal_deprecated_string
|
||||
fluent::attr_unsupported_literal_deprecated_string
|
||||
}
|
||||
UnsupportedLiteralReason::DeprecatedKvPair => {
|
||||
fluent::attr::unsupported_literal_deprecated_kv_pair
|
||||
fluent::attr_unsupported_literal_deprecated_kv_pair
|
||||
}
|
||||
},
|
||||
error_code!(E0565),
|
||||
|
|
@ -227,7 +227,7 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
|||
if self.is_bytestr {
|
||||
diag.span_suggestion(
|
||||
self.start_point_span,
|
||||
fluent::attr::unsupported_literal_suggestion,
|
||||
fluent::attr_unsupported_literal_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
@ -237,7 +237,7 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_align_need_arg, code = "E0589")]
|
||||
#[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
|
||||
pub(crate) struct InvalidReprAlignNeedArg {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
|
||||
|
|
@ -245,7 +245,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::invalid_repr_generic, code = "E0589")]
|
||||
#[diag(attr_invalid_repr_generic, code = "E0589")]
|
||||
pub(crate) struct InvalidReprGeneric<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -255,14 +255,14 @@ pub(crate) struct InvalidReprGeneric<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")]
|
||||
#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
|
||||
pub(crate) struct IncorrectReprFormatAlignOneArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::incorrect_repr_format_generic, code = "E0693")]
|
||||
#[diag(attr_incorrect_repr_format_generic, code = "E0693")]
|
||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -275,7 +275,7 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
#[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")]
|
||||
#[suggestion(suggestion, code = "{name}({int})", applicability = "machine-applicable")]
|
||||
Int {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -287,11 +287,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
|||
int: u128,
|
||||
},
|
||||
|
||||
#[suggestion(
|
||||
attr::suggestion,
|
||||
code = "{name}({symbol})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
#[suggestion(suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
|
||||
Symbol {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -317,28 +313,28 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::rustc_promotable_pairing, code = "E0717")]
|
||||
#[diag(attr_rustc_promotable_pairing, code = "E0717")]
|
||||
pub(crate) struct RustcPromotablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")]
|
||||
#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
|
||||
pub(crate) struct RustcAllowedUnstablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::cfg_predicate_identifier)]
|
||||
#[diag(attr_cfg_predicate_identifier)]
|
||||
pub(crate) struct CfgPredicateIdentifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::deprecated_item_suggestion)]
|
||||
#[diag(attr_deprecated_item_suggestion)]
|
||||
pub(crate) struct DeprecatedItemSuggestion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -351,21 +347,21 @@ pub(crate) struct DeprecatedItemSuggestion {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expected_single_version_literal)]
|
||||
#[diag(attr_expected_single_version_literal)]
|
||||
pub(crate) struct ExpectedSingleVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expected_version_literal)]
|
||||
#[diag(attr_expected_version_literal)]
|
||||
pub(crate) struct ExpectedVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expects_feature_list)]
|
||||
#[diag(attr_expects_feature_list)]
|
||||
pub(crate) struct ExpectsFeatureList {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -374,7 +370,7 @@ pub(crate) struct ExpectsFeatureList {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::expects_features)]
|
||||
#[diag(attr_expects_features)]
|
||||
pub(crate) struct ExpectsFeatures {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -383,14 +379,14 @@ pub(crate) struct ExpectsFeatures {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::soft_no_args)]
|
||||
#[diag(attr_soft_no_args)]
|
||||
pub(crate) struct SoftNoArgs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr::unknown_version_literal)]
|
||||
#[diag(attr_unknown_version_literal)]
|
||||
pub(crate) struct UnknownVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
|
|||
|
|
@ -251,7 +251,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr));
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
|
||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
|
||||
|
||||
if let Some(ref value) = value {
|
||||
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
|
||||
|
|
@ -869,13 +870,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let mut found = false;
|
||||
tcx.fold_regions(tcx.type_of(region_parent), |r: ty::Region<'tcx>, _| {
|
||||
if *r == ty::ReEarlyBound(region) {
|
||||
found = true;
|
||||
}
|
||||
r
|
||||
});
|
||||
let found = tcx
|
||||
.any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
|
||||
|
||||
Some(RegionName {
|
||||
name: self.synthesize_region_name(),
|
||||
|
|
@ -888,4 +884,92 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
),
|
||||
})
|
||||
}
|
||||
|
||||
fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
|
||||
&self,
|
||||
fr: RegionVid,
|
||||
) -> Option<RegionName> {
|
||||
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
|
||||
return None;
|
||||
};
|
||||
if region.has_name() {
|
||||
return None;
|
||||
};
|
||||
|
||||
let predicates = self
|
||||
.infcx
|
||||
.tcx
|
||||
.predicates_of(self.body.source.def_id())
|
||||
.instantiate_identity(self.infcx.tcx)
|
||||
.predicates;
|
||||
|
||||
if let Some(upvar_index) = self
|
||||
.regioncx
|
||||
.universal_regions()
|
||||
.defining_ty
|
||||
.upvar_tys()
|
||||
.position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
|
||||
{
|
||||
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
||||
self.infcx.tcx,
|
||||
&self.upvars,
|
||||
upvar_index,
|
||||
);
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
||||
Some(RegionName {
|
||||
name: region_name,
|
||||
source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
|
||||
})
|
||||
} else if let Some(arg_index) = self
|
||||
.regioncx
|
||||
.universal_regions()
|
||||
.unnormalized_input_tys
|
||||
.iter()
|
||||
.position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
|
||||
{
|
||||
let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
|
||||
self.body,
|
||||
&self.local_names,
|
||||
arg_index,
|
||||
);
|
||||
let region_name = self.synthesize_region_name();
|
||||
|
||||
Some(RegionName {
|
||||
name: region_name,
|
||||
source: RegionNameSource::AnonRegionFromArgument(
|
||||
RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()),
|
||||
),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn any_param_predicate_mentions(
|
||||
&self,
|
||||
predicates: &[ty::Predicate<'tcx>],
|
||||
ty: Ty<'tcx>,
|
||||
region: ty::EarlyBoundRegion,
|
||||
) -> bool {
|
||||
let tcx = self.infcx.tcx;
|
||||
ty.walk().any(|arg| {
|
||||
if let ty::GenericArgKind::Type(ty) = arg.unpack()
|
||||
&& let ty::Param(_) = ty.kind()
|
||||
{
|
||||
predicates.iter().any(|pred| {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
|
||||
ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
|
||||
_ => return false,
|
||||
}
|
||||
tcx.any_free_region_meets(pred, |r| {
|
||||
*r == ty::ReEarlyBound(region)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_span::Span;
|
|||
use crate::diagnostics::RegionName;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::move_unsized, code = "E0161")]
|
||||
#[diag(borrowck_move_unsized, code = "E0161")]
|
||||
pub(crate) struct MoveUnsized<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
#[primary_span]
|
||||
|
|
@ -15,7 +15,7 @@ pub(crate) struct MoveUnsized<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::higher_ranked_lifetime_error)]
|
||||
#[diag(borrowck_higher_ranked_lifetime_error)]
|
||||
pub(crate) struct HigherRankedLifetimeError {
|
||||
#[subdiagnostic]
|
||||
pub cause: Option<HigherRankedErrorCause>,
|
||||
|
|
@ -25,21 +25,21 @@ pub(crate) struct HigherRankedLifetimeError {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum HigherRankedErrorCause {
|
||||
#[note(borrowck::could_not_prove)]
|
||||
#[note(borrowck_could_not_prove)]
|
||||
CouldNotProve { predicate: String },
|
||||
#[note(borrowck::could_not_normalize)]
|
||||
#[note(borrowck_could_not_normalize)]
|
||||
CouldNotNormalize { value: String },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::higher_ranked_subtype_error)]
|
||||
#[diag(borrowck_higher_ranked_subtype_error)]
|
||||
pub(crate) struct HigherRankedSubtypeError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::generic_does_not_live_long_enough)]
|
||||
#[diag(borrowck_generic_does_not_live_long_enough)]
|
||||
pub(crate) struct GenericDoesNotLiveLongEnough {
|
||||
pub kind: String,
|
||||
#[primary_span]
|
||||
|
|
@ -47,15 +47,15 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
|
|||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(borrowck::var_does_not_need_mut)]
|
||||
#[diag(borrowck_var_does_not_need_mut)]
|
||||
pub(crate) struct VarNeedNotMut {
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "")]
|
||||
pub span: Span,
|
||||
}
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::var_cannot_escape_closure)]
|
||||
#[diag(borrowck_var_cannot_escape_closure)]
|
||||
#[note]
|
||||
#[note(borrowck::cannot_escape)]
|
||||
#[note(cannot_escape)]
|
||||
pub(crate) struct FnMutError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -65,17 +65,17 @@ pub(crate) struct FnMutError {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum VarHereDenote {
|
||||
#[label(borrowck::var_here_captured)]
|
||||
#[label(borrowck_var_here_captured)]
|
||||
Captured {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::var_here_defined)]
|
||||
#[label(borrowck_var_here_defined)]
|
||||
Defined {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::closure_inferred_mut)]
|
||||
#[label(borrowck_closure_inferred_mut)]
|
||||
FnMutInferred {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -84,17 +84,17 @@ pub(crate) enum VarHereDenote {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum FnMutReturnTypeErr {
|
||||
#[label(borrowck::returned_closure_escaped)]
|
||||
#[label(borrowck_returned_closure_escaped)]
|
||||
ReturnClosure {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::returned_async_block_escaped)]
|
||||
#[label(borrowck_returned_async_block_escaped)]
|
||||
ReturnAsyncBlock {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(borrowck::returned_ref_escaped)]
|
||||
#[label(borrowck_returned_ref_escaped)]
|
||||
ReturnRef {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -102,7 +102,7 @@ pub(crate) enum FnMutReturnTypeErr {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(borrowck::lifetime_constraints_error)]
|
||||
#[diag(borrowck_lifetime_constraints_error)]
|
||||
pub(crate) struct LifetimeOutliveErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -110,7 +110,7 @@ pub(crate) struct LifetimeOutliveErr {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum LifetimeReturnCategoryErr<'a> {
|
||||
#[label(borrowck::returned_lifetime_wrong)]
|
||||
#[label(borrowck_returned_lifetime_wrong)]
|
||||
WrongReturn {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -118,7 +118,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
|
|||
outlived_fr_name: RegionName,
|
||||
fr_name: &'a RegionName,
|
||||
},
|
||||
#[label(borrowck::returned_lifetime_short)]
|
||||
#[label(borrowck_returned_lifetime_short)]
|
||||
ShortReturn {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -142,7 +142,7 @@ impl IntoDiagnosticArg for RegionName {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum RequireStaticErr {
|
||||
#[note(borrowck::used_impl_require_static)]
|
||||
#[note(borrowck_used_impl_require_static)]
|
||||
UsedImpl {
|
||||
#[primary_span]
|
||||
multi_span: MultiSpan,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub fn expand_cfg(
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros::requires_cfg_pattern)]
|
||||
#[diag(builtin_macros_requires_cfg_pattern)]
|
||||
struct RequiresCfgPattern {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -44,7 +44,7 @@ struct RequiresCfgPattern {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros::expected_one_cfg_pattern)]
|
||||
#[diag(builtin_macros_expected_one_cfg_pattern)]
|
||||
struct OneCfgPattern {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -36,13 +36,22 @@ pub fn expand_test_case(
|
|||
let sp = ecx.with_def_site_ctxt(attr_sp);
|
||||
let mut item = anno_item.expect_item();
|
||||
item = item.map(|mut item| {
|
||||
let test_path_symbol = Symbol::intern(&item_path(
|
||||
// skip the name of the root module
|
||||
&ecx.current_expansion.module.mod_path[1..],
|
||||
&item.ident,
|
||||
));
|
||||
item.vis = ast::Visibility {
|
||||
span: item.vis.span,
|
||||
kind: ast::VisibilityKind::Public,
|
||||
tokens: None,
|
||||
};
|
||||
item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
|
||||
item.attrs.push(ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker)));
|
||||
item.attrs.push(ecx.attribute(attr::mk_name_value_item_str(
|
||||
Ident::new(sym::rustc_test_marker, sp),
|
||||
test_path_symbol,
|
||||
sp,
|
||||
)));
|
||||
item
|
||||
});
|
||||
|
||||
|
|
@ -215,6 +224,12 @@ pub fn expand_test_or_bench(
|
|||
)
|
||||
};
|
||||
|
||||
let test_path_symbol = Symbol::intern(&item_path(
|
||||
// skip the name of the root module
|
||||
&cx.current_expansion.module.mod_path[1..],
|
||||
&item.ident,
|
||||
));
|
||||
|
||||
let mut test_const = cx.item(
|
||||
sp,
|
||||
Ident::new(item.ident.name, sp),
|
||||
|
|
@ -224,9 +239,14 @@ pub fn expand_test_or_bench(
|
|||
Ident::new(sym::cfg, attr_sp),
|
||||
vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))],
|
||||
)),
|
||||
// #[rustc_test_marker]
|
||||
cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)),
|
||||
],
|
||||
// #[rustc_test_marker = "test_case_sort_key"]
|
||||
cx.attribute(attr::mk_name_value_item_str(
|
||||
Ident::new(sym::rustc_test_marker, attr_sp),
|
||||
test_path_symbol,
|
||||
attr_sp,
|
||||
)),
|
||||
]
|
||||
.into(),
|
||||
// const $ident: test::TestDescAndFn =
|
||||
ast::ItemKind::Const(
|
||||
ast::Defaultness::Final,
|
||||
|
|
@ -250,14 +270,7 @@ pub fn expand_test_or_bench(
|
|||
cx.expr_call(
|
||||
sp,
|
||||
cx.expr_path(test_path("StaticTestName")),
|
||||
vec![cx.expr_str(
|
||||
sp,
|
||||
Symbol::intern(&item_path(
|
||||
// skip the name of the root module
|
||||
&cx.current_expansion.module.mod_path[1..],
|
||||
&item.ident,
|
||||
)),
|
||||
)],
|
||||
vec![cx.expr_str(sp, test_path_symbol)],
|
||||
),
|
||||
),
|
||||
// ignore: true | false
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ use thin_vec::thin_vec;
|
|||
|
||||
use std::{iter, mem};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
name: Symbol,
|
||||
}
|
||||
|
||||
struct TestCtxt<'a> {
|
||||
|
|
@ -120,10 +122,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
|||
|
||||
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||
let mut item = i.into_inner();
|
||||
if is_test_case(&self.cx.ext_cx.sess, &item) {
|
||||
if let Some(name) = get_test_name(&self.cx.ext_cx.sess, &item) {
|
||||
debug!("this is a test item");
|
||||
|
||||
let test = Test { span: item.span, ident: item.ident };
|
||||
let test = Test { span: item.span, ident: item.ident, name };
|
||||
self.tests.push(test);
|
||||
}
|
||||
|
||||
|
|
@ -357,9 +359,12 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
|
|||
debug!("building test vector from {} tests", cx.test_cases.len());
|
||||
let ecx = &cx.ext_cx;
|
||||
|
||||
let mut tests = cx.test_cases.clone();
|
||||
tests.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str()));
|
||||
|
||||
ecx.expr_array_ref(
|
||||
sp,
|
||||
cx.test_cases
|
||||
tests
|
||||
.iter()
|
||||
.map(|test| {
|
||||
ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident])))
|
||||
|
|
@ -368,8 +373,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
|
|||
)
|
||||
}
|
||||
|
||||
fn is_test_case(sess: &Session, i: &ast::Item) -> bool {
|
||||
sess.contains_name(&i.attrs, sym::rustc_test_marker)
|
||||
fn get_test_name(sess: &Session, i: &ast::Item) -> Option<Symbol> {
|
||||
sess.first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker)
|
||||
}
|
||||
|
||||
fn get_test_runner(
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-apple-darwin
|
||||
# cross-compile from Linux to Windows using mingw
|
||||
- os: ubuntu-latest
|
||||
env:
|
||||
|
|
@ -112,7 +116,7 @@ jobs:
|
|||
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: cg_clif-${{ runner.os }}
|
||||
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
|
||||
path: cg_clif.tar.xz
|
||||
|
||||
- name: Upload prebuilt cg_clif (cross compile)
|
||||
|
|
@ -122,56 +126,89 @@ jobs:
|
|||
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
|
||||
path: cg_clif.tar.xz
|
||||
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
windows:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Native Windows build with MSVC
|
||||
- os: windows-latest
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-pc-windows-msvc
|
||||
# cross-compile from Windows to Windows MinGW
|
||||
- os: windows-latest
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-pc-windows-gnu
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
#- name: Cache cargo installed crates
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: ~/.cargo/bin
|
||||
# key: ${{ runner.os }}-cargo-installed-crates
|
||||
- name: Cache cargo installed crates
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/bin
|
||||
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
|
||||
|
||||
#- name: Cache cargo registry and index
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry
|
||||
# ~/.cargo/git
|
||||
# key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Cache cargo registry and index
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
#- name: Cache cargo target dir
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: target
|
||||
# key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
- name: Cache cargo target dir
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
|
||||
|
||||
- name: Set MinGW as the default toolchain
|
||||
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
|
||||
run: rustup set default-host x86_64-pc-windows-gnu
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
git config --global user.name "User"
|
||||
git config --global core.autocrlf false
|
||||
rustup set default-host x86_64-pc-windows-gnu
|
||||
rustc y.rs -o y.exe -g
|
||||
./y.exe prepare
|
||||
|
||||
- name: Build without unstable features
|
||||
env:
|
||||
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
|
||||
# This is the config rust-lang/rust uses for builds
|
||||
run: ./y.rs build --no-unstable-features
|
||||
|
||||
- name: Build
|
||||
#name: Test
|
||||
run: ./y.rs build --sysroot none
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
# Enable backtraces for easier debugging
|
||||
#$Env:RUST_BACKTRACE=1
|
||||
$Env:RUST_BACKTRACE=1
|
||||
|
||||
# Reduce amount of benchmark runs as they are slow
|
||||
#$Env:COMPILE_RUNS=2
|
||||
#$Env:RUN_RUNS=2
|
||||
$Env:COMPILE_RUNS=2
|
||||
$Env:RUN_RUNS=2
|
||||
|
||||
# Enable extra checks
|
||||
#$Env:CG_CLIF_ENABLE_VERIFIER=1
|
||||
$Env:CG_CLIF_ENABLE_VERIFIER=1
|
||||
|
||||
# WIP Disable some tests
|
||||
|
||||
# This fails due to some weird argument handling by hyperfine, not an actual regression
|
||||
# more of a build system issue
|
||||
(Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' | Out-File config.txt
|
||||
|
||||
# This fails with a different output than expected
|
||||
(Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' | Out-File config.txt
|
||||
|
||||
./y.exe build
|
||||
./y.exe test
|
||||
|
||||
- name: Package prebuilt cg_clif
|
||||
# don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
|
||||
|
|
@ -180,5 +217,5 @@ jobs:
|
|||
- name: Upload prebuilt cg_clif
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: cg_clif-${{ runner.os }}
|
||||
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
|
||||
path: cg_clif.tar
|
||||
|
|
|
|||
6
compiler/rustc_codegen_cranelift/.gitignore
vendored
6
compiler/rustc_codegen_cranelift/.gitignore
vendored
|
|
@ -15,8 +15,4 @@ perf.data.old
|
|||
/build_sysroot/compiler-builtins
|
||||
/build_sysroot/rustc_version
|
||||
/rust
|
||||
/rand
|
||||
/regex
|
||||
/simple-raytracer
|
||||
/portable-simd
|
||||
/abi-checker
|
||||
/download
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"rust-analyzer.cargo.features": ["unstable-features"],
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"./Cargo.toml",
|
||||
//"./build_sysroot/sysroot_src/src/libstd/Cargo.toml",
|
||||
//"./build_sysroot/sysroot_src/library/std/Cargo.toml",
|
||||
{
|
||||
"roots": [
|
||||
"./example/mini_core.rs",
|
||||
|
|
@ -36,10 +36,10 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"roots": ["./scripts/filter_profile.rs"],
|
||||
"roots": ["./example/std_example.rs"],
|
||||
"crates": [
|
||||
{
|
||||
"root_module": "./scripts/filter_profile.rs",
|
||||
"root_module": "./example/std_example.rs",
|
||||
"edition": "2018",
|
||||
"deps": [{ "crate": 1, "name": "std" }],
|
||||
"cfg": [],
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ name = "ar"
|
|||
version = "0.8.0"
|
||||
source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
|
@ -36,6 +42,12 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
|
@ -50,19 +62,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358"
|
||||
checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31"
|
||||
checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
"cranelift-codegen-shared",
|
||||
|
|
@ -77,30 +91,30 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8"
|
||||
checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99"
|
||||
checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5"
|
||||
checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a"
|
||||
checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
|
|
@ -110,15 +124,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e"
|
||||
checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029"
|
||||
checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -134,9 +148,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8"
|
||||
checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -144,9 +158,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd"
|
||||
checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
|
|
@ -155,9 +169,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.87.0"
|
||||
version = "0.88.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816"
|
||||
checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -232,9 +246,9 @@ checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
|
|||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.6.7"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
|
||||
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
|
|
|
|||
|
|
@ -8,19 +8,19 @@ crate-type = ["dylib"]
|
|||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.87.0", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = "0.87.0"
|
||||
cranelift-module = "0.87.0"
|
||||
cranelift-native = "0.87.0"
|
||||
cranelift-jit = { version = "0.87.0", optional = true }
|
||||
cranelift-object = "0.87.0"
|
||||
cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
|
||||
cranelift-frontend = "0.88.1"
|
||||
cranelift-module = "0.88.1"
|
||||
cranelift-native = "0.88.1"
|
||||
cranelift-jit = { version = "0.88.1", optional = true }
|
||||
cranelift-object = "0.88.1"
|
||||
target-lexicon = "0.12.0"
|
||||
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
|
||||
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
|
||||
indexmap = "1.9.1"
|
||||
libloading = { version = "0.6.0", optional = true }
|
||||
libloading = { version = "0.7.3", optional = true }
|
||||
once_cell = "1.10.0"
|
||||
smallvec = "1.8.1"
|
||||
|
||||
|
|
|
|||
|
|
@ -55,10 +55,20 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.79"
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -123,9 +133,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
|
|
@ -135,9 +145,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
version = "0.2.135"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -182,7 +192,7 @@ name = "panic_abort"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
|
|
@ -193,7 +203,7 @@ name = "panic_unwind"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
|
|
@ -245,7 +255,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"addr2line",
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"dlmalloc",
|
||||
|
|
@ -267,7 +277,7 @@ dependencies = [
|
|||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
|
|
@ -289,7 +299,7 @@ dependencies = [
|
|||
name = "test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"core",
|
||||
"getopts",
|
||||
"libc",
|
||||
|
|
@ -301,9 +311,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
|
|
@ -315,7 +325,7 @@ name = "unwind"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
|
|
|
|||
52
compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
Normal file
52
compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
use super::build_sysroot;
|
||||
use super::config;
|
||||
use super::prepare;
|
||||
use super::utils::{cargo_command, spawn_and_wait};
|
||||
use super::SysrootKind;
|
||||
|
||||
pub(crate) fn run(
|
||||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
target_dir: &Path,
|
||||
cg_clif_dylib: &Path,
|
||||
host_triple: &str,
|
||||
target_triple: &str,
|
||||
) {
|
||||
if !config::get_bool("testsuite.abi-cafe") {
|
||||
eprintln!("[SKIP] abi-cafe");
|
||||
return;
|
||||
}
|
||||
|
||||
if host_triple != target_triple {
|
||||
eprintln!("[SKIP] abi-cafe (cross-compilation not supported)");
|
||||
return;
|
||||
}
|
||||
|
||||
eprintln!("Building sysroot for abi-cafe");
|
||||
build_sysroot::build_sysroot(
|
||||
channel,
|
||||
sysroot_kind,
|
||||
target_dir,
|
||||
cg_clif_dylib,
|
||||
host_triple,
|
||||
target_triple,
|
||||
);
|
||||
|
||||
eprintln!("Running abi-cafe");
|
||||
let abi_cafe_path = prepare::ABI_CAFE.source_dir();
|
||||
env::set_current_dir(abi_cafe_path.clone()).unwrap();
|
||||
|
||||
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
|
||||
|
||||
let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
|
||||
cmd.arg("--");
|
||||
cmd.arg("--pairs");
|
||||
cmd.args(pairs);
|
||||
cmd.arg("--add-rustc-codegen-backend");
|
||||
cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
|
||||
|
||||
spawn_and_wait(cmd);
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
use super::build_sysroot;
|
||||
use super::config;
|
||||
use super::utils::spawn_and_wait;
|
||||
use build_system::SysrootKind;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
pub(crate) fn run(
|
||||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
target_dir: &Path,
|
||||
cg_clif_build_dir: &Path,
|
||||
host_triple: &str,
|
||||
target_triple: &str,
|
||||
) {
|
||||
if !config::get_bool("testsuite.abi-checker") {
|
||||
eprintln!("[SKIP] abi-checker");
|
||||
return;
|
||||
}
|
||||
|
||||
if host_triple != target_triple {
|
||||
eprintln!("[SKIP] abi-checker (cross-compilation not supported)");
|
||||
return;
|
||||
}
|
||||
|
||||
eprintln!("Building sysroot for abi-checker");
|
||||
build_sysroot::build_sysroot(
|
||||
channel,
|
||||
sysroot_kind,
|
||||
target_dir,
|
||||
cg_clif_build_dir,
|
||||
host_triple,
|
||||
target_triple,
|
||||
);
|
||||
|
||||
eprintln!("Running abi-checker");
|
||||
let mut abi_checker_path = env::current_dir().unwrap();
|
||||
abi_checker_path.push("abi-checker");
|
||||
env::set_current_dir(abi_checker_path.clone()).unwrap();
|
||||
|
||||
let build_dir = abi_checker_path.parent().unwrap().join("build");
|
||||
let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join(
|
||||
env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
|
||||
);
|
||||
|
||||
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
|
||||
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.arg("run");
|
||||
cmd.arg("--target");
|
||||
cmd.arg(target_triple);
|
||||
cmd.arg("--");
|
||||
cmd.arg("--pairs");
|
||||
cmd.args(pairs);
|
||||
cmd.arg("--add-rustc-codegen-backend");
|
||||
cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display()));
|
||||
|
||||
spawn_and_wait(cmd);
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::utils::is_ci;
|
||||
use super::rustc_info::get_file_name;
|
||||
use super::utils::{cargo_command, is_ci};
|
||||
|
||||
pub(crate) fn build_backend(
|
||||
channel: &str,
|
||||
host_triple: &str,
|
||||
use_unstable_features: bool,
|
||||
) -> PathBuf {
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.arg("build").arg("--target").arg(host_triple);
|
||||
let source_dir = std::env::current_dir().unwrap();
|
||||
let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
|
||||
|
||||
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
|
||||
|
||||
|
|
@ -41,5 +41,9 @@ pub(crate) fn build_backend(
|
|||
eprintln!("[BUILD] rustc_codegen_cranelift");
|
||||
super::utils::spawn_and_wait(cmd);
|
||||
|
||||
Path::new("target").join(host_triple).join(channel)
|
||||
source_dir
|
||||
.join("target")
|
||||
.join(host_triple)
|
||||
.join(channel)
|
||||
.join(get_file_name("rustc_codegen_cranelift", "dylib"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::{self, Command};
|
||||
|
||||
use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
|
||||
use super::utils::{spawn_and_wait, try_hard_link};
|
||||
use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
|
||||
use super::SysrootKind;
|
||||
|
||||
pub(crate) fn build_sysroot(
|
||||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
target_dir: &Path,
|
||||
cg_clif_build_dir: &Path,
|
||||
cg_clif_dylib_src: &Path,
|
||||
host_triple: &str,
|
||||
target_triple: &str,
|
||||
) {
|
||||
|
|
@ -23,7 +23,6 @@ pub(crate) fn build_sysroot(
|
|||
fs::create_dir_all(target_dir.join("lib")).unwrap();
|
||||
|
||||
// Copy the backend
|
||||
let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib");
|
||||
let cg_clif_dylib_path = target_dir
|
||||
.join(if cfg!(windows) {
|
||||
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
|
||||
|
|
@ -32,8 +31,8 @@ pub(crate) fn build_sysroot(
|
|||
} else {
|
||||
"lib"
|
||||
})
|
||||
.join(&cg_clif_dylib);
|
||||
try_hard_link(cg_clif_build_dir.join(cg_clif_dylib), &cg_clif_dylib_path);
|
||||
.join(get_file_name("rustc_codegen_cranelift", "dylib"));
|
||||
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
|
||||
|
||||
// Build and copy rustc and cargo wrappers
|
||||
for wrapper in ["rustc-clif", "cargo-clif"] {
|
||||
|
|
@ -186,10 +185,10 @@ fn build_clif_sysroot_for_triple(
|
|||
}
|
||||
|
||||
// Build sysroot
|
||||
let mut build_cmd = Command::new("cargo");
|
||||
build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot");
|
||||
let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
|
||||
let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
|
||||
rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
|
||||
rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
|
||||
if channel == "release" {
|
||||
build_cmd.arg("--release");
|
||||
rustflags.push_str(" -Zmir-opt-level=3");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use std::{fs, process};
|
||||
use std::fs;
|
||||
use std::process;
|
||||
|
||||
fn load_config_file() -> Vec<(String, Option<String>)> {
|
||||
fs::read_to_string("config.txt")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::process;
|
|||
|
||||
use self::utils::is_ci;
|
||||
|
||||
mod abi_checker;
|
||||
mod abi_cafe;
|
||||
mod build_backend;
|
||||
mod build_sysroot;
|
||||
mod config;
|
||||
|
|
@ -122,32 +122,23 @@ pub fn main() {
|
|||
host_triple.clone()
|
||||
};
|
||||
|
||||
if target_triple.ends_with("-msvc") {
|
||||
eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift.");
|
||||
eprintln!("Switch to the MinGW toolchain for Windows support.");
|
||||
eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to");
|
||||
eprintln!("set the global default target to MinGW");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let cg_clif_build_dir =
|
||||
build_backend::build_backend(channel, &host_triple, use_unstable_features);
|
||||
let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
|
||||
match command {
|
||||
Command::Test => {
|
||||
tests::run_tests(
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&target_dir,
|
||||
&cg_clif_build_dir,
|
||||
&cg_clif_dylib,
|
||||
&host_triple,
|
||||
&target_triple,
|
||||
);
|
||||
|
||||
abi_checker::run(
|
||||
abi_cafe::run(
|
||||
channel,
|
||||
sysroot_kind,
|
||||
&target_dir,
|
||||
&cg_clif_build_dir,
|
||||
&cg_clif_dylib,
|
||||
&host_triple,
|
||||
&target_triple,
|
||||
);
|
||||
|
|
@ -157,7 +148,7 @@ pub fn main() {
|
|||
channel,
|
||||
sysroot_kind,
|
||||
&target_dir,
|
||||
&cg_clif_build_dir,
|
||||
&cg_clif_dylib,
|
||||
&host_triple,
|
||||
&target_triple,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,64 +1,63 @@
|
|||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
|
||||
use super::utils::{copy_dir_recursively, spawn_and_wait};
|
||||
use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
|
||||
|
||||
pub(crate) const ABI_CAFE: GitRepo =
|
||||
GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
|
||||
|
||||
pub(crate) const RAND: GitRepo =
|
||||
GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
|
||||
|
||||
pub(crate) const REGEX: GitRepo =
|
||||
GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
|
||||
|
||||
pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
|
||||
"rust-lang",
|
||||
"portable-simd",
|
||||
"d5cd4a8112d958bd3a252327e0d069a6363249bd",
|
||||
"portable-simd",
|
||||
);
|
||||
|
||||
pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
|
||||
"ebobby",
|
||||
"simple-raytracer",
|
||||
"804a7a21b9e673a482797aa289a18ed480e4d813",
|
||||
"<none>",
|
||||
);
|
||||
|
||||
pub(crate) fn prepare() {
|
||||
if Path::new("download").exists() {
|
||||
std::fs::remove_dir_all(Path::new("download")).unwrap();
|
||||
}
|
||||
std::fs::create_dir_all(Path::new("download")).unwrap();
|
||||
|
||||
prepare_sysroot();
|
||||
|
||||
// FIXME maybe install this only locally?
|
||||
eprintln!("[INSTALL] hyperfine");
|
||||
Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
|
||||
|
||||
clone_repo_shallow_github(
|
||||
"abi-checker",
|
||||
"Gankra",
|
||||
"abi-checker",
|
||||
"a2232d45f202846f5c02203c9f27355360f9a2ff",
|
||||
);
|
||||
apply_patches("abi-checker", Path::new("abi-checker"));
|
||||
|
||||
clone_repo_shallow_github(
|
||||
"rand",
|
||||
"rust-random",
|
||||
"rand",
|
||||
"0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
|
||||
);
|
||||
apply_patches("rand", Path::new("rand"));
|
||||
|
||||
clone_repo_shallow_github(
|
||||
"regex",
|
||||
"rust-lang",
|
||||
"regex",
|
||||
"341f207c1071f7290e3f228c710817c280c8dca1",
|
||||
);
|
||||
|
||||
clone_repo_shallow_github(
|
||||
"portable-simd",
|
||||
"rust-lang",
|
||||
"portable-simd",
|
||||
"b8d6b6844602f80af79cd96401339ec594d472d8",
|
||||
);
|
||||
apply_patches("portable-simd", Path::new("portable-simd"));
|
||||
|
||||
clone_repo_shallow_github(
|
||||
"simple-raytracer",
|
||||
"ebobby",
|
||||
"simple-raytracer",
|
||||
"804a7a21b9e673a482797aa289a18ed480e4d813",
|
||||
);
|
||||
ABI_CAFE.fetch();
|
||||
RAND.fetch();
|
||||
REGEX.fetch();
|
||||
PORTABLE_SIMD.fetch();
|
||||
SIMPLE_RAYTRACER.fetch();
|
||||
|
||||
eprintln!("[LLVM BUILD] simple-raytracer");
|
||||
let mut build_cmd = Command::new("cargo");
|
||||
build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer");
|
||||
let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
|
||||
spawn_and_wait(build_cmd);
|
||||
fs::copy(
|
||||
Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")),
|
||||
Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")),
|
||||
SIMPLE_RAYTRACER
|
||||
.source_dir()
|
||||
.join("target")
|
||||
.join("debug")
|
||||
.join(get_file_name("main", "bin")),
|
||||
SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
@ -90,38 +89,78 @@ fn prepare_sysroot() {
|
|||
apply_patches("sysroot", &sysroot_src);
|
||||
}
|
||||
|
||||
pub(crate) struct GitRepo {
|
||||
url: GitRepoUrl,
|
||||
rev: &'static str,
|
||||
patch_name: &'static str,
|
||||
}
|
||||
|
||||
enum GitRepoUrl {
|
||||
Github { user: &'static str, repo: &'static str },
|
||||
}
|
||||
|
||||
impl GitRepo {
|
||||
const fn github(
|
||||
user: &'static str,
|
||||
repo: &'static str,
|
||||
rev: &'static str,
|
||||
patch_name: &'static str,
|
||||
) -> GitRepo {
|
||||
GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
|
||||
}
|
||||
|
||||
pub(crate) fn source_dir(&self) -> PathBuf {
|
||||
match self.url {
|
||||
GitRepoUrl::Github { user: _, repo } => {
|
||||
std::env::current_dir().unwrap().join("download").join(repo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch(&self) {
|
||||
match self.url {
|
||||
GitRepoUrl::Github { user, repo } => {
|
||||
clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
|
||||
}
|
||||
}
|
||||
apply_patches(self.patch_name, &self.source_dir());
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn clone_repo(target_dir: &str, repo: &str, rev: &str) {
|
||||
fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
|
||||
eprintln!("[CLONE] {}", repo);
|
||||
// Ignore exit code as the repo may already have been checked out
|
||||
Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap();
|
||||
Command::new("git").arg("clone").arg(repo).arg(&download_dir).spawn().unwrap().wait().unwrap();
|
||||
|
||||
let mut clean_cmd = Command::new("git");
|
||||
clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir);
|
||||
clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
|
||||
spawn_and_wait(clean_cmd);
|
||||
|
||||
let mut checkout_cmd = Command::new("git");
|
||||
checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir);
|
||||
checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
|
||||
spawn_and_wait(checkout_cmd);
|
||||
}
|
||||
|
||||
fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev: &str) {
|
||||
fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
|
||||
if cfg!(windows) {
|
||||
// Older windows doesn't have tar or curl by default. Fall back to using git.
|
||||
clone_repo(target_dir, &format!("https://github.com/{}/{}.git", username, repo), rev);
|
||||
clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
|
||||
return;
|
||||
}
|
||||
|
||||
let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", username, repo, rev);
|
||||
let archive_file = format!("{}.tar.gz", rev);
|
||||
let archive_dir = format!("{}-{}", repo, rev);
|
||||
let downloads_dir = std::env::current_dir().unwrap().join("download");
|
||||
|
||||
eprintln!("[DOWNLOAD] {}/{} from {}", username, repo, archive_url);
|
||||
let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
|
||||
let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
|
||||
let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
|
||||
|
||||
eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
|
||||
|
||||
// Remove previous results if they exists
|
||||
let _ = std::fs::remove_file(&archive_file);
|
||||
let _ = std::fs::remove_dir_all(&archive_dir);
|
||||
let _ = std::fs::remove_dir_all(target_dir);
|
||||
let _ = std::fs::remove_dir_all(&download_dir);
|
||||
|
||||
// Download zip archive
|
||||
let mut download_cmd = Command::new("curl");
|
||||
|
|
@ -130,13 +169,13 @@ fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev:
|
|||
|
||||
// Unpack tar archive
|
||||
let mut unpack_cmd = Command::new("tar");
|
||||
unpack_cmd.arg("xf").arg(&archive_file);
|
||||
unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
|
||||
spawn_and_wait(unpack_cmd);
|
||||
|
||||
// Rename unpacked dir to the expected name
|
||||
std::fs::rename(archive_dir, target_dir).unwrap();
|
||||
std::fs::rename(archive_dir, &download_dir).unwrap();
|
||||
|
||||
init_git_repo(Path::new(target_dir));
|
||||
init_git_repo(&download_dir);
|
||||
|
||||
// Cleanup
|
||||
std::fs::remove_file(archive_file).unwrap();
|
||||
|
|
@ -156,14 +195,20 @@ fn init_git_repo(repo_dir: &Path) {
|
|||
spawn_and_wait(git_commit_cmd);
|
||||
}
|
||||
|
||||
fn get_patches(crate_name: &str) -> Vec<OsString> {
|
||||
let mut patches: Vec<_> = fs::read_dir("patches")
|
||||
fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
|
||||
let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
|
||||
.unwrap()
|
||||
.map(|entry| entry.unwrap().path())
|
||||
.filter(|path| path.extension() == Some(OsStr::new("patch")))
|
||||
.map(|path| path.file_name().unwrap().to_owned())
|
||||
.filter(|file_name| {
|
||||
file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name)
|
||||
.filter(|path| {
|
||||
path.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.split_once("-")
|
||||
.unwrap()
|
||||
.1
|
||||
.starts_with(crate_name)
|
||||
})
|
||||
.collect();
|
||||
patches.sort();
|
||||
|
|
@ -171,11 +216,18 @@ fn get_patches(crate_name: &str) -> Vec<OsString> {
|
|||
}
|
||||
|
||||
fn apply_patches(crate_name: &str, target_dir: &Path) {
|
||||
for patch in get_patches(crate_name) {
|
||||
eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch);
|
||||
let patch_arg = env::current_dir().unwrap().join("patches").join(patch);
|
||||
if crate_name == "<none>" {
|
||||
return;
|
||||
}
|
||||
|
||||
for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
|
||||
eprintln!(
|
||||
"[PATCH] {:?} <- {:?}",
|
||||
target_dir.file_name().unwrap(),
|
||||
patch.file_name().unwrap()
|
||||
);
|
||||
let mut apply_patch_cmd = Command::new("git");
|
||||
apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir);
|
||||
apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
|
||||
spawn_and_wait(apply_patch_cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use super::build_sysroot;
|
||||
use super::config;
|
||||
use super::prepare;
|
||||
use super::rustc_info::get_wrapper_file_name;
|
||||
use super::utils::{spawn_and_wait, spawn_and_wait_with_input};
|
||||
use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
|
||||
use build_system::SysrootKind;
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
|
|
@ -217,103 +218,95 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
|
|||
|
||||
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
||||
TestCase::new("test.rust-random/rand", &|runner| {
|
||||
runner.in_dir(["rand"], |runner| {
|
||||
runner.run_cargo(["clean"]);
|
||||
runner.in_dir(prepare::RAND.source_dir(), |runner| {
|
||||
runner.run_cargo("clean", []);
|
||||
|
||||
if runner.host_triple == runner.target_triple {
|
||||
eprintln!("[TEST] rust-random/rand");
|
||||
runner.run_cargo(["test", "--workspace"]);
|
||||
runner.run_cargo("test", ["--workspace"]);
|
||||
} else {
|
||||
eprintln!("[AOT] rust-random/rand");
|
||||
runner.run_cargo([
|
||||
"build",
|
||||
"--workspace",
|
||||
"--target",
|
||||
&runner.target_triple,
|
||||
"--tests",
|
||||
]);
|
||||
runner.run_cargo("build", ["--workspace", "--tests"]);
|
||||
}
|
||||
});
|
||||
}),
|
||||
TestCase::new("bench.simple-raytracer", &|runner| {
|
||||
runner.in_dir(["simple-raytracer"], |runner| {
|
||||
let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string());
|
||||
runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
|
||||
let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
|
||||
|
||||
if runner.host_triple == runner.target_triple {
|
||||
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
|
||||
let mut bench_compile = Command::new("hyperfine");
|
||||
bench_compile.arg("--runs");
|
||||
bench_compile.arg(&run_runs);
|
||||
bench_compile.arg("--warmup");
|
||||
bench_compile.arg("1");
|
||||
bench_compile.arg("--prepare");
|
||||
bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"])));
|
||||
let prepare = runner.cargo_command("clean", []);
|
||||
|
||||
if cfg!(windows) {
|
||||
bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\"");
|
||||
} else {
|
||||
bench_compile.arg("RUSTFLAGS='' cargo build");
|
||||
}
|
||||
let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
|
||||
|
||||
let cargo_clif = runner
|
||||
.root_dir
|
||||
.clone()
|
||||
.join("build")
|
||||
.join(get_wrapper_file_name("cargo-clif", "bin"));
|
||||
let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
|
||||
|
||||
let bench_compile =
|
||||
hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
|
||||
|
||||
bench_compile.arg(format!("{:?}", runner.cargo_command(["build"])));
|
||||
spawn_and_wait(bench_compile);
|
||||
|
||||
eprintln!("[BENCH RUN] ebobby/simple-raytracer");
|
||||
fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
|
||||
.unwrap();
|
||||
|
||||
let mut bench_run = Command::new("hyperfine");
|
||||
bench_run.arg("--runs");
|
||||
bench_run.arg(&run_runs);
|
||||
bench_run.arg(PathBuf::from("./raytracer_cg_llvm"));
|
||||
bench_run.arg(PathBuf::from("./raytracer_cg_clif"));
|
||||
let bench_run = hyperfine_command(
|
||||
0,
|
||||
run_runs,
|
||||
None,
|
||||
Command::new("./raytracer_cg_llvm"),
|
||||
Command::new("./raytracer_cg_clif"),
|
||||
);
|
||||
spawn_and_wait(bench_run);
|
||||
} else {
|
||||
runner.run_cargo(["clean"]);
|
||||
runner.run_cargo("clean", []);
|
||||
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
|
||||
eprintln!("[COMPILE] ebobby/simple-raytracer");
|
||||
runner.run_cargo(["build", "--target", &runner.target_triple]);
|
||||
runner.run_cargo("build", []);
|
||||
eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
|
||||
}
|
||||
});
|
||||
}),
|
||||
TestCase::new("test.libcore", &|runner| {
|
||||
runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| {
|
||||
runner.run_cargo(["clean"]);
|
||||
runner.in_dir(
|
||||
std::env::current_dir()
|
||||
.unwrap()
|
||||
.join("build_sysroot")
|
||||
.join("sysroot_src")
|
||||
.join("library")
|
||||
.join("core")
|
||||
.join("tests"),
|
||||
|runner| {
|
||||
runner.run_cargo("clean", []);
|
||||
|
||||
if runner.host_triple == runner.target_triple {
|
||||
runner.run_cargo(["test"]);
|
||||
} else {
|
||||
eprintln!("Cross-Compiling: Not running tests");
|
||||
runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]);
|
||||
}
|
||||
});
|
||||
if runner.host_triple == runner.target_triple {
|
||||
runner.run_cargo("test", []);
|
||||
} else {
|
||||
eprintln!("Cross-Compiling: Not running tests");
|
||||
runner.run_cargo("build", ["--tests"]);
|
||||
}
|
||||
},
|
||||
);
|
||||
}),
|
||||
TestCase::new("test.regex-shootout-regex-dna", &|runner| {
|
||||
runner.in_dir(["regex"], |runner| {
|
||||
runner.run_cargo(["clean"]);
|
||||
runner.in_dir(prepare::REGEX.source_dir(), |runner| {
|
||||
runner.run_cargo("clean", []);
|
||||
|
||||
// newer aho_corasick versions throw a deprecation warning
|
||||
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
|
||||
|
||||
let mut build_cmd = runner.cargo_command([
|
||||
"build",
|
||||
"--example",
|
||||
"shootout-regex-dna",
|
||||
"--target",
|
||||
&runner.target_triple,
|
||||
]);
|
||||
let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
|
||||
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
|
||||
spawn_and_wait(build_cmd);
|
||||
|
||||
if runner.host_triple == runner.target_triple {
|
||||
let mut run_cmd = runner.cargo_command([
|
||||
"run",
|
||||
"--example",
|
||||
"shootout-regex-dna",
|
||||
"--target",
|
||||
&runner.target_triple,
|
||||
]);
|
||||
let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
|
||||
run_cmd.env("RUSTFLAGS", lint_rust_flags);
|
||||
|
||||
let input =
|
||||
|
|
@ -353,41 +346,43 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
|||
});
|
||||
}),
|
||||
TestCase::new("test.regex", &|runner| {
|
||||
runner.in_dir(["regex"], |runner| {
|
||||
runner.run_cargo(["clean"]);
|
||||
runner.in_dir(prepare::REGEX.source_dir(), |runner| {
|
||||
runner.run_cargo("clean", []);
|
||||
|
||||
// newer aho_corasick versions throw a deprecation warning
|
||||
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
|
||||
|
||||
if runner.host_triple == runner.target_triple {
|
||||
let mut run_cmd = runner.cargo_command([
|
||||
let mut run_cmd = runner.cargo_command(
|
||||
"test",
|
||||
"--tests",
|
||||
"--",
|
||||
"--exclude-should-panic",
|
||||
"--test-threads",
|
||||
"1",
|
||||
"-Zunstable-options",
|
||||
"-q",
|
||||
]);
|
||||
[
|
||||
"--tests",
|
||||
"--",
|
||||
"--exclude-should-panic",
|
||||
"--test-threads",
|
||||
"1",
|
||||
"-Zunstable-options",
|
||||
"-q",
|
||||
],
|
||||
);
|
||||
run_cmd.env("RUSTFLAGS", lint_rust_flags);
|
||||
spawn_and_wait(run_cmd);
|
||||
} else {
|
||||
eprintln!("Cross-Compiling: Not running tests");
|
||||
let mut build_cmd =
|
||||
runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]);
|
||||
runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
|
||||
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
|
||||
spawn_and_wait(build_cmd);
|
||||
}
|
||||
});
|
||||
}),
|
||||
TestCase::new("test.portable-simd", &|runner| {
|
||||
runner.in_dir(["portable-simd"], |runner| {
|
||||
runner.run_cargo(["clean"]);
|
||||
runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]);
|
||||
runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
|
||||
runner.run_cargo("clean", []);
|
||||
runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
|
||||
|
||||
if runner.host_triple == runner.target_triple {
|
||||
runner.run_cargo(["test", "-q"]);
|
||||
runner.run_cargo("test", ["-q"]);
|
||||
}
|
||||
});
|
||||
}),
|
||||
|
|
@ -397,7 +392,7 @@ pub(crate) fn run_tests(
|
|||
channel: &str,
|
||||
sysroot_kind: SysrootKind,
|
||||
target_dir: &Path,
|
||||
cg_clif_build_dir: &Path,
|
||||
cg_clif_dylib: &Path,
|
||||
host_triple: &str,
|
||||
target_triple: &str,
|
||||
) {
|
||||
|
|
@ -408,7 +403,7 @@ pub(crate) fn run_tests(
|
|||
channel,
|
||||
SysrootKind::None,
|
||||
&target_dir,
|
||||
cg_clif_build_dir,
|
||||
cg_clif_dylib,
|
||||
&host_triple,
|
||||
&target_triple,
|
||||
);
|
||||
|
|
@ -427,7 +422,7 @@ pub(crate) fn run_tests(
|
|||
channel,
|
||||
sysroot_kind,
|
||||
&target_dir,
|
||||
cg_clif_build_dir,
|
||||
cg_clif_dylib,
|
||||
&host_triple,
|
||||
&target_triple,
|
||||
);
|
||||
|
|
@ -521,16 +516,8 @@ impl TestRunner {
|
|||
}
|
||||
}
|
||||
|
||||
fn in_dir<'a, I, F>(&self, dir: I, callback: F)
|
||||
where
|
||||
I: IntoIterator<Item = &'a str>,
|
||||
F: FnOnce(&TestRunner),
|
||||
{
|
||||
fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
|
||||
let current = env::current_dir().unwrap();
|
||||
let mut new = current.clone();
|
||||
for d in dir {
|
||||
new.push(d);
|
||||
}
|
||||
|
||||
env::set_current_dir(new).unwrap();
|
||||
callback(self);
|
||||
|
|
@ -595,25 +582,29 @@ impl TestRunner {
|
|||
spawn_and_wait(cmd);
|
||||
}
|
||||
|
||||
fn cargo_command<I, S>(&self, args: I) -> Command
|
||||
fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
I: IntoIterator<Item = &'a str>,
|
||||
{
|
||||
let mut cargo_clif = self.root_dir.clone();
|
||||
cargo_clif.push("build");
|
||||
cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
|
||||
|
||||
let mut cmd = Command::new(cargo_clif);
|
||||
let mut cmd = cargo_command(
|
||||
cargo_clif,
|
||||
subcommand,
|
||||
if subcommand == "clean" { None } else { Some(&self.target_triple) },
|
||||
Path::new("."),
|
||||
);
|
||||
cmd.args(args);
|
||||
cmd.env("RUSTFLAGS", &self.rust_flags);
|
||||
cmd
|
||||
}
|
||||
|
||||
fn run_cargo<'a, I>(&self, args: I)
|
||||
fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
|
||||
where
|
||||
I: IntoIterator<Item = &'a str>,
|
||||
{
|
||||
spawn_and_wait(self.cargo_command(args));
|
||||
spawn_and_wait(self.cargo_command(subcommand, args));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,52 @@ use std::io::Write;
|
|||
use std::path::Path;
|
||||
use std::process::{self, Command, Stdio};
|
||||
|
||||
pub(crate) fn cargo_command(
|
||||
cargo: impl AsRef<Path>,
|
||||
subcommand: &str,
|
||||
triple: Option<&str>,
|
||||
source_dir: &Path,
|
||||
) -> Command {
|
||||
let mut cmd = Command::new(cargo.as_ref());
|
||||
cmd.arg(subcommand)
|
||||
.arg("--manifest-path")
|
||||
.arg(source_dir.join("Cargo.toml"))
|
||||
.arg("--target-dir")
|
||||
.arg(source_dir.join("target"));
|
||||
|
||||
if let Some(triple) = triple {
|
||||
cmd.arg("--target").arg(triple);
|
||||
}
|
||||
|
||||
cmd
|
||||
}
|
||||
|
||||
pub(crate) fn hyperfine_command(
|
||||
warmup: u64,
|
||||
runs: u64,
|
||||
prepare: Option<Command>,
|
||||
a: Command,
|
||||
b: Command,
|
||||
) -> Command {
|
||||
let mut bench = Command::new("hyperfine");
|
||||
|
||||
if warmup != 0 {
|
||||
bench.arg("--warmup").arg(warmup.to_string());
|
||||
}
|
||||
|
||||
if runs != 0 {
|
||||
bench.arg("--runs").arg(runs.to_string());
|
||||
}
|
||||
|
||||
if let Some(prepare) = prepare {
|
||||
bench.arg("--prepare").arg(format!("{:?}", prepare));
|
||||
}
|
||||
|
||||
bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
|
||||
|
||||
bench
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
|
||||
let src = src.as_ref();
|
||||
|
|
|
|||
|
|
@ -3,4 +3,8 @@ set -e
|
|||
|
||||
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
|
||||
rm -rf target/ build/ perf.data{,.old} y.bin
|
||||
rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/
|
||||
rm -rf download/
|
||||
|
||||
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
|
||||
# FIXME remove at some point in the future
|
||||
rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/
|
||||
|
|
|
|||
|
|
@ -49,4 +49,4 @@ test.regex-shootout-regex-dna
|
|||
test.regex
|
||||
test.portable-simd
|
||||
|
||||
testsuite.abi-checker
|
||||
testsuite.abi-cafe
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
// Test that we can handle unsized types with an extern type tail part.
|
||||
// Regression test for issue #91827.
|
||||
|
||||
#![feature(const_ptr_offset_from)]
|
||||
#![feature(extern_types)]
|
||||
|
||||
use std::ptr::addr_of;
|
||||
|
|
|
|||
|
|
@ -559,16 +559,22 @@ pub union MaybeUninit<T> {
|
|||
|
||||
pub mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn size_of<T>() -> usize;
|
||||
pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn min_align_of<T>() -> usize;
|
||||
pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
|
||||
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
pub fn transmute<T, U>(e: T) -> U;
|
||||
pub fn ctlz_nonzero<T>(x: T) -> T;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn needs_drop<T: ?::Sized>() -> bool;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn bitreverse<T>(x: T) -> T;
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn bswap<T>(x: T) -> T;
|
||||
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ fn start<T: Termination + 'static>(
|
|||
main: fn() -> T,
|
||||
argc: isize,
|
||||
argv: *const *const u8,
|
||||
_sigpipe: u8,
|
||||
) -> isize {
|
||||
if argc == 3 {
|
||||
unsafe { puts(*argv as *const i8); }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
From 2b15fee2bb5fd14e34c7e17e44d99cb34f4c555d Mon Sep 17 00:00:00 2001
|
||||
From: Afonso Bordado <afonsobordado@az8.co>
|
||||
Date: Tue, 27 Sep 2022 07:55:17 +0100
|
||||
Subject: [PATCH] Disable some test on x86_64-pc-windows-gnu
|
||||
|
||||
---
|
||||
src/report.rs | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/src/report.rs b/src/report.rs
|
||||
index eeec614..f582867 100644
|
||||
--- a/src/report.rs
|
||||
+++ b/src/report.rs
|
||||
@@ -48,6 +48,12 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
|
||||
//
|
||||
// THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
|
||||
|
||||
+ // x86_64-pc-windows-gnu has some broken i128 tests that aren't disabled by default
|
||||
+ if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" {
|
||||
+ result.run = Link;
|
||||
+ result.check = Pass(Link);
|
||||
+ }
|
||||
+
|
||||
// END OF VENDOR RESERVED AREA
|
||||
//
|
||||
//
|
||||
--
|
||||
2.30.1.windows.1
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001
|
||||
From: Afonso Bordado <afonso360@users.noreply.github.com>
|
||||
Date: Fri, 12 Aug 2022 22:51:58 +0000
|
||||
Subject: [PATCH] Disable abi-checker tests
|
||||
|
||||
---
|
||||
src/report.rs | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/report.rs b/src/report.rs
|
||||
index 7346f5e..8347762 100644
|
||||
--- a/src/report.rs
|
||||
+++ b/src/report.rs
|
||||
@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
|
||||
//
|
||||
// THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
|
||||
|
||||
+ // Currently MSVC has some broken ABI issues. Furthermore, they cause
|
||||
+ // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link.
|
||||
+ if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") {
|
||||
+ result.run = Link;
|
||||
+ result.check = Pass(Link);
|
||||
+ }
|
||||
+
|
||||
+ // structs is broken in the current release of cranelift for aarch64.
|
||||
+ // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634
|
||||
+ if cfg!(target_arch = "aarch64") && test.test_name == "structs" {
|
||||
+ result.run = Link;
|
||||
+ result.check = Pass(Link);
|
||||
+ }
|
||||
+
|
||||
// END OF VENDOR RESERVED AREA
|
||||
//
|
||||
//
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -1,80 +1,29 @@
|
|||
From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001
|
||||
From b742f03694b920cc14400727d54424e8e1b60928 Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Thu, 18 Nov 2021 19:28:40 +0100
|
||||
Subject: [PATCH] Disable unsupported tests
|
||||
|
||||
---
|
||||
crates/core_simd/src/math.rs | 6 ++++++
|
||||
crates/core_simd/src/vector.rs | 2 ++
|
||||
crates/core_simd/tests/masks.rs | 2 ++
|
||||
crates/core_simd/tests/ops_macros.rs | 4 ++++
|
||||
4 files changed, 14 insertions(+)
|
||||
crates/core_simd/src/elements/int.rs | 8 ++++++++
|
||||
crates/core_simd/src/elements/uint.rs | 4 ++++
|
||||
crates/core_simd/src/masks/full_masks.rs | 6 ++++++
|
||||
crates/core_simd/src/vector.rs | 2 ++
|
||||
crates/core_simd/tests/masks.rs | 3 ---
|
||||
5 files changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs
|
||||
index 2bae414..2f87499 100644
|
||||
--- a/crates/core_simd/src/math.rs
|
||||
+++ b/crates/core_simd/src/math.rs
|
||||
@@ -5,6 +5,7 @@ macro_rules! impl_uint_arith {
|
||||
($($ty:ty),+) => {
|
||||
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
|
||||
|
||||
+ /*
|
||||
/// Lanewise saturating add.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -43,6 +44,7 @@ macro_rules! impl_uint_arith {
|
||||
pub fn saturating_sub(self, second: Self) -> Self {
|
||||
unsafe { simd_saturating_sub(self, second) }
|
||||
}
|
||||
+ */
|
||||
})+
|
||||
}
|
||||
}
|
||||
@@ -51,6 +53,7 @@ macro_rules! impl_int_arith {
|
||||
($($ty:ty),+) => {
|
||||
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
|
||||
|
||||
+ /*
|
||||
/// Lanewise saturating add.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -89,6 +92,7 @@ macro_rules! impl_int_arith {
|
||||
pub fn saturating_sub(self, second: Self) -> Self {
|
||||
unsafe { simd_saturating_sub(self, second) }
|
||||
}
|
||||
+ */
|
||||
|
||||
/// Lanewise absolute value, implemented in Rust.
|
||||
/// Every lane becomes its absolute value.
|
||||
@@ -109,6 +113,7 @@ macro_rules! impl_int_arith {
|
||||
(self^m) - m
|
||||
}
|
||||
|
||||
+ /*
|
||||
/// Lanewise saturating absolute value, implemented in Rust.
|
||||
/// As abs(), except the MIN value becomes MAX instead of itself.
|
||||
///
|
||||
@@ -151,6 +156,7 @@ macro_rules! impl_int_arith {
|
||||
pub fn saturating_neg(self) -> Self {
|
||||
Self::splat(0).saturating_sub(self)
|
||||
}
|
||||
+ */
|
||||
})+
|
||||
}
|
||||
}
|
||||
diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs
|
||||
index 7c5ec2b..c8631e8 100644
|
||||
index e8e8f68..7173c24 100644
|
||||
--- a/crates/core_simd/src/vector.rs
|
||||
+++ b/crates/core_simd/src/vector.rs
|
||||
@@ -75,6 +75,7 @@ where
|
||||
Self(array)
|
||||
@@ -250,6 +250,7 @@ where
|
||||
unsafe { intrinsics::simd_cast(self) }
|
||||
}
|
||||
|
||||
+ /*
|
||||
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
|
||||
/// If an index is out-of-bounds, the lane is instead selected from the `or` vector.
|
||||
///
|
||||
@@ -297,6 +298,7 @@ where
|
||||
@@ -473,6 +474,7 @@ where
|
||||
// Cleared ☢️ *mut T Zone
|
||||
}
|
||||
}
|
||||
|
|
@ -82,26 +31,5 @@ index 7c5ec2b..c8631e8 100644
|
|||
}
|
||||
|
||||
impl<T, const LANES: usize> Copy for Simd<T, LANES>
|
||||
diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs
|
||||
index 6a8ecd3..68fcb49 100644
|
||||
--- a/crates/core_simd/tests/masks.rs
|
||||
+++ b/crates/core_simd/tests/masks.rs
|
||||
@@ -68,6 +68,7 @@ macro_rules! test_mask_api {
|
||||
assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask);
|
||||
}
|
||||
|
||||
+ /*
|
||||
#[cfg(feature = "generic_const_exprs")]
|
||||
#[test]
|
||||
fn roundtrip_bitmask_conversion() {
|
||||
@@ -80,6 +81,7 @@ macro_rules! test_mask_api {
|
||||
assert_eq!(bitmask, [0b01001001, 0b10000011]);
|
||||
assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
|
||||
}
|
||||
+ */
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.26.2.7.g19db9cfb68
|
||||
|
||||
2.25.1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
From eec874c889b8d24e5ad50faded24288150f057b1 Mon Sep 17 00:00:00 2001
|
||||
From: Afonso Bordado <afonsobordado@az8.co>
|
||||
Date: Tue, 27 Sep 2022 08:13:58 +0100
|
||||
Subject: [PATCH] Disable rand tests on mingw
|
||||
|
||||
---
|
||||
rand_distr/src/pareto.rs | 2 ++
|
||||
rand_distr/tests/value_stability.rs | 4 ++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs
|
||||
index 217899e..9cedeb7 100644
|
||||
--- a/rand_distr/src/pareto.rs
|
||||
+++ b/rand_distr/src/pareto.rs
|
||||
@@ -107,6 +107,8 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
+ // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation
|
||||
+ #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
|
||||
fn value_stability() {
|
||||
fn test_samples<F: Float + core::fmt::Debug, D: Distribution<F>>(
|
||||
distr: D, zero: F, expected: &[F],
|
||||
diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs
|
||||
index 192ba74..0101ace 100644
|
||||
--- a/rand_distr/tests/value_stability.rs
|
||||
+++ b/rand_distr/tests/value_stability.rs
|
||||
@@ -72,6 +72,8 @@ fn unit_disc_stability() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
+// This is broken on x86_64-pc-windows-gnu
|
||||
+#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
|
||||
fn pareto_stability() {
|
||||
test_samples(213, Pareto::new(1.0, 1.0).unwrap(), &[
|
||||
1.0423688f32, 2.1235929, 4.132709, 1.4679428,
|
||||
@@ -143,6 +145,8 @@ fn inverse_gaussian_stability() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
+// This is broken on x86_64-pc-windows-gnu
|
||||
+#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
|
||||
fn gamma_stability() {
|
||||
// Gamma has 3 cases: shape == 1, shape < 1, shape > 1
|
||||
test_samples(223, Gamma::new(1.0, 5.0).unwrap(), &[
|
||||
--
|
||||
2.25.1
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2022-08-24"
|
||||
channel = "nightly-2022-10-23"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ git fetch
|
|||
git checkout -- .
|
||||
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
|
||||
|
||||
git am ../patches/*-sysroot-*.patch
|
||||
|
||||
git apply - <<EOF
|
||||
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
|
||||
index d95b5b7f17f..00b6f0e3635 100644
|
||||
|
|
@ -66,3 +68,7 @@ popd
|
|||
|
||||
# FIXME remove once inline asm is fully supported
|
||||
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
|
||||
|
||||
# Allow the testsuite to use llvm tools
|
||||
host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
|
||||
export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
|
||||
|
|
|
|||
|
|
@ -29,10 +29,6 @@ rm src/test/incremental/change_crate_dep_kind.rs
|
|||
rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101)
|
||||
|
||||
# requires compiling with -Cpanic=unwind
|
||||
rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process"
|
||||
rm src/test/ui/async-await/async-fn-size-moved-locals.rs # -Cpanic=abort shrinks some generator by one byte
|
||||
rm src/test/ui/async-await/async-fn-size-uninit-locals.rs # same
|
||||
rm src/test/ui/generator/size-moved-locals.rs # same
|
||||
rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
|
||||
|
||||
# vendor intrinsics
|
||||
|
|
@ -67,6 +63,7 @@ rm src/test/ui/target-feature/missing-plusminus.rs # error not implemented
|
|||
rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
|
||||
rm -r src/test/run-make/emit-named-files # requires full --emit support
|
||||
rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
|
||||
rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
|
||||
|
||||
# optimization tests
|
||||
# ==================
|
||||
|
|
@ -110,12 +107,13 @@ rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unorde
|
|||
# bugs in the test suite
|
||||
# ======================
|
||||
rm src/test/ui/backtrace.rs # TODO warning
|
||||
rm src/test/ui/empty_global_asm.rs # TODO add needs-asm-support
|
||||
rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
|
||||
rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
|
||||
# not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
|
||||
rm -r src/test/run-make/native-link-modifier-bundle
|
||||
|
||||
rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
|
||||
|
||||
echo "[TEST] rustc test suite"
|
||||
RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental}
|
||||
popd
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
|
||||
(CallTarget::Indirect(sig, method), Some(ptr))
|
||||
(CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
|
||||
}
|
||||
|
||||
// Normal call
|
||||
|
|
@ -560,7 +560,19 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
// we don't actually need to drop anything
|
||||
} else {
|
||||
match ty.kind() {
|
||||
ty::Dynamic(..) => {
|
||||
ty::Dynamic(_, _, ty::Dyn) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn Trait)
|
||||
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
|
||||
// args[0] args[1]
|
||||
//
|
||||
// args = ( Data, Vtable )
|
||||
// |
|
||||
// v
|
||||
// /-------\
|
||||
// | ... |
|
||||
// \-------/
|
||||
//
|
||||
let (ptr, vtable) = drop_place.to_ptr_maybe_unsized();
|
||||
let ptr = ptr.get_addr(fx);
|
||||
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
|
||||
|
|
@ -578,6 +590,43 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
let sig = fx.bcx.import_signature(sig);
|
||||
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
|
||||
}
|
||||
ty::Dynamic(_, _, ty::DynStar) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn* Trait)
|
||||
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
|
||||
//
|
||||
// args = [ * ]
|
||||
// |
|
||||
// v
|
||||
// ( Data, Vtable )
|
||||
// |
|
||||
// v
|
||||
// /-------\
|
||||
// | ... |
|
||||
// \-------/
|
||||
//
|
||||
//
|
||||
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
|
||||
//
|
||||
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
|
||||
// vtable = (*args[0]).1 // loads the vtable out
|
||||
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
|
||||
//
|
||||
// SO THEN WE CAN USE THE ABOVE CODE.
|
||||
let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
|
||||
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
|
||||
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
|
||||
substs: drop_instance.substs,
|
||||
};
|
||||
let fn_abi =
|
||||
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
|
||||
}
|
||||
_ => {
|
||||
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ fn codegen_inner(
|
|||
let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();
|
||||
|
||||
let mut ctx = Context::new();
|
||||
ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
|
||||
ctx.func.signature = sig.clone();
|
||||
{
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
|
||||
|
|
@ -116,7 +116,7 @@ fn codegen_inner(
|
|||
let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap();
|
||||
|
||||
let mut ctx = Context::new();
|
||||
ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
|
||||
ctx.func.signature = sig;
|
||||
{
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
|||
_lib_name: &str,
|
||||
_dll_imports: &[rustc_session::cstore::DllImport],
|
||||
_tmpdir: &Path,
|
||||
_is_direct_dependency: bool,
|
||||
) -> PathBuf {
|
||||
bug!("creating dll imports is not supported");
|
||||
}
|
||||
|
|
@ -159,6 +160,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
let err = err.to_string();
|
||||
if err == "Unknown file magic" {
|
||||
// Not an object file; skip it.
|
||||
} else if object::read::archive::ArchiveFile::parse(&*data).is_ok() {
|
||||
// Nested archive file; skip it.
|
||||
} else {
|
||||
sess.fatal(&format!(
|
||||
"error parsing `{}` during archive creation: {}",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ use rustc_middle::ty::adjustment::PointerCast;
|
|||
use rustc_middle::ty::layout::FnAbiOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
|
||||
use cranelift_codegen::ir::UserFuncName;
|
||||
|
||||
use crate::constant::ConstantCx;
|
||||
use crate::debuginfo::FunctionDebugContext;
|
||||
use crate::prelude::*;
|
||||
|
|
@ -64,7 +66,7 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
let mut func = cached_func;
|
||||
func.clear();
|
||||
func.name = ExternalName::user(0, func_id.as_u32());
|
||||
func.name = UserFuncName::user(0, func_id.as_u32());
|
||||
func.signature = sig;
|
||||
func.collect_debug_info();
|
||||
|
||||
|
|
@ -706,9 +708,9 @@ fn codegen_stmt<'tcx>(
|
|||
let operand = codegen_operand(fx, operand);
|
||||
operand.unsize_value(fx, lval);
|
||||
}
|
||||
Rvalue::Cast(CastKind::DynStar, _, _) => {
|
||||
// FIXME(dyn-star)
|
||||
unimplemented!()
|
||||
Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
operand.coerce_dyn_star(fx, lval);
|
||||
}
|
||||
Rvalue::Discriminant(place) => {
|
||||
let place = codegen_place(fx, place);
|
||||
|
|
@ -922,7 +924,7 @@ pub(crate) fn codegen_operand<'tcx>(
|
|||
let cplace = codegen_place(fx, *place);
|
||||
cplace.to_cvalue(fx)
|
||||
}
|
||||
Operand::Constant(const_) => crate::constant::codegen_constant(fx, const_),
|
||||
Operand::Constant(const_) => crate::constant::codegen_constant_operand(fx, const_),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ pub(super) struct ConcurrencyLimiter {
|
|||
helper_thread: Option<HelperThread>,
|
||||
state: Arc<Mutex<state::ConcurrencyLimiterState>>,
|
||||
available_token_condvar: Arc<Condvar>,
|
||||
finished: bool,
|
||||
}
|
||||
|
||||
impl ConcurrencyLimiter {
|
||||
|
|
@ -32,6 +33,7 @@ impl ConcurrencyLimiter {
|
|||
helper_thread: Some(helper_thread),
|
||||
state,
|
||||
available_token_condvar: Arc::new(Condvar::new()),
|
||||
finished: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -56,16 +58,23 @@ impl ConcurrencyLimiter {
|
|||
let mut state = self.state.lock().unwrap();
|
||||
state.job_already_done();
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ConcurrencyLimiter {
|
||||
fn drop(&mut self) {
|
||||
//
|
||||
pub(crate) fn finished(mut self) {
|
||||
self.helper_thread.take();
|
||||
|
||||
// Assert that all jobs have finished
|
||||
let state = Mutex::get_mut(Arc::get_mut(&mut self.state).unwrap()).unwrap();
|
||||
state.assert_done();
|
||||
|
||||
self.finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ConcurrencyLimiter {
|
||||
fn drop(&mut self) {
|
||||
if !self.finished && !std::thread::panicking() {
|
||||
panic!("Forgot to call finished() on ConcurrencyLimiter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use rustc_middle::mir::interpret::{
|
|||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use cranelift_codegen::ir::GlobalValueData;
|
||||
use cranelift_module::*;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
|
@ -81,52 +80,45 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
|||
CValue::by_val(tls_ptr, layout)
|
||||
}
|
||||
|
||||
fn codegen_static_ref<'tcx>(
|
||||
pub(crate) fn eval_mir_constant<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
def_id: DefId,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> CPlace<'tcx> {
|
||||
let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", def_id));
|
||||
}
|
||||
let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
|
||||
assert!(!layout.is_unsized(), "unsized statics aren't supported");
|
||||
assert!(
|
||||
matches!(
|
||||
fx.bcx.func.global_values[local_data_id],
|
||||
GlobalValueData::Symbol { tls: false, .. }
|
||||
),
|
||||
"tls static referenced without Rvalue::ThreadLocalRef"
|
||||
);
|
||||
CPlace::for_ptr(crate::pointer::Pointer::new(global_ptr), layout)
|
||||
constant: &Constant<'tcx>,
|
||||
) -> (ConstValue<'tcx>, Ty<'tcx>) {
|
||||
let constant_kind = fx.monomorphize(constant.literal);
|
||||
let uv = match constant_kind {
|
||||
ConstantKind::Ty(const_) => match const_.kind() {
|
||||
ty::ConstKind::Unevaluated(uv) => uv.expand(),
|
||||
ty::ConstKind::Value(val) => {
|
||||
return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty());
|
||||
}
|
||||
err => span_bug!(
|
||||
constant.span,
|
||||
"encountered bad ConstKind after monomorphizing: {:?}",
|
||||
err
|
||||
),
|
||||
},
|
||||
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
|
||||
if fx.tcx.is_static(def.did) =>
|
||||
{
|
||||
span_bug!(constant.span, "MIR constant refers to static");
|
||||
}
|
||||
ConstantKind::Unevaluated(uv, _) => uv,
|
||||
ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
|
||||
};
|
||||
|
||||
(
|
||||
fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
|
||||
span_bug!(constant.span, "erroneous constant not captured by required_consts");
|
||||
}),
|
||||
constant_kind.ty(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_constant<'tcx>(
|
||||
pub(crate) fn codegen_constant_operand<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
constant: &Constant<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
let (const_val, ty) = match fx.monomorphize(constant.literal) {
|
||||
ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
|
||||
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty)
|
||||
if fx.tcx.is_static(def.did) =>
|
||||
{
|
||||
assert!(substs.is_empty());
|
||||
assert!(promoted.is_none());
|
||||
|
||||
return codegen_static_ref(fx, def.did, fx.layout_of(ty)).to_cvalue(fx);
|
||||
}
|
||||
ConstantKind::Unevaluated(unevaluated, ty) => {
|
||||
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
|
||||
Ok(const_val) => (const_val, ty),
|
||||
Err(_) => {
|
||||
span_bug!(constant.span, "erroneous constant not captured by required_consts");
|
||||
}
|
||||
}
|
||||
}
|
||||
ConstantKind::Val(val, ty) => (val, ty),
|
||||
};
|
||||
let (const_val, ty) = eval_mir_constant(fx, constant);
|
||||
|
||||
codegen_const_value(fx, const_val, ty)
|
||||
}
|
||||
|
|
@ -244,7 +236,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pointer_for_allocation<'tcx>(
|
||||
fn pointer_for_allocation<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
alloc: ConstAllocation<'tcx>,
|
||||
) -> crate::pointer::Pointer {
|
||||
|
|
@ -467,14 +459,13 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
|||
operand: &Operand<'tcx>,
|
||||
) -> Option<ConstValue<'tcx>> {
|
||||
match operand {
|
||||
Operand::Constant(const_) => match const_.literal {
|
||||
ConstantKind::Ty(const_) => fx
|
||||
.monomorphize(const_)
|
||||
.eval_for_mir(fx.tcx, ParamEnv::reveal_all())
|
||||
.try_to_value(fx.tcx),
|
||||
Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
|
||||
ConstantKind::Ty(const_) => Some(
|
||||
const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(),
|
||||
),
|
||||
ConstantKind::Val(val, _) => Some(val),
|
||||
ConstantKind::Unevaluated(uv, _) => {
|
||||
fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).ok()
|
||||
Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap())
|
||||
}
|
||||
},
|
||||
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ impl OngoingCodegen {
|
|||
}
|
||||
}
|
||||
|
||||
drop(self.concurrency_limiter);
|
||||
self.concurrency_limiter.finished();
|
||||
|
||||
(
|
||||
CodegenResults {
|
||||
|
|
|
|||
|
|
@ -67,13 +67,12 @@ fn create_jit_module(
|
|||
hotswap: bool,
|
||||
) -> (JITModule, CodegenCx) {
|
||||
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
|
||||
let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info);
|
||||
|
||||
let isa = crate::build_isa(tcx.sess, backend_config);
|
||||
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
|
||||
jit_builder.hotswap(hotswap);
|
||||
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
|
||||
jit_builder.symbols(imported_symbols);
|
||||
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
|
||||
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
|
||||
let mut jit_module = JITModule::new(jit_builder);
|
||||
|
||||
|
|
@ -286,10 +285,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
})
|
||||
}
|
||||
|
||||
fn load_imported_symbols_for_jit(
|
||||
fn dep_symbol_lookup_fn(
|
||||
sess: &Session,
|
||||
crate_info: CrateInfo,
|
||||
) -> Vec<(String, *const u8)> {
|
||||
) -> Box<dyn Fn(&str) -> Option<*const u8>> {
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
|
||||
let mut dylib_paths = Vec::new();
|
||||
|
|
@ -316,39 +315,23 @@ fn load_imported_symbols_for_jit(
|
|||
}
|
||||
}
|
||||
|
||||
let mut imported_symbols = Vec::new();
|
||||
for path in dylib_paths {
|
||||
use object::{Object, ObjectSymbol};
|
||||
let lib = libloading::Library::new(&path).unwrap();
|
||||
let obj = std::fs::read(path).unwrap();
|
||||
let obj = object::File::parse(&*obj).unwrap();
|
||||
imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
|
||||
let name = symbol.name().unwrap().to_string();
|
||||
if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
|
||||
return None;
|
||||
}
|
||||
if name.starts_with("rust_metadata_") {
|
||||
// The metadata is part of a section that is not loaded by the dynamic linker in
|
||||
// case of cg_llvm.
|
||||
return None;
|
||||
}
|
||||
let dlsym_name = if cfg!(target_os = "macos") {
|
||||
// On macOS `dlsym` expects the name without leading `_`.
|
||||
assert!(name.starts_with('_'), "{:?}", name);
|
||||
&name[1..]
|
||||
} else {
|
||||
&name
|
||||
};
|
||||
let symbol: libloading::Symbol<'_, *const u8> =
|
||||
unsafe { lib.get(dlsym_name.as_bytes()) }.unwrap();
|
||||
Some((name, *symbol))
|
||||
}));
|
||||
std::mem::forget(lib)
|
||||
}
|
||||
let imported_dylibs = Box::leak(
|
||||
dylib_paths
|
||||
.into_iter()
|
||||
.map(|path| unsafe { libloading::Library::new(&path).unwrap() })
|
||||
.collect::<Box<[_]>>(),
|
||||
);
|
||||
|
||||
sess.abort_if_errors();
|
||||
|
||||
imported_symbols
|
||||
Box::new(move |sym_name| {
|
||||
for dylib in &*imported_dylibs {
|
||||
if let Ok(sym) = unsafe { dylib.get::<*const u8>(sym_name.as_bytes()) } {
|
||||
return Some(*sym);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
fn codegen_shim<'tcx>(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
}
|
||||
|
||||
// Used by stdarch
|
||||
if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string())
|
||||
if template[0] == InlineAsmTemplatePiece::String("mov ".to_string())
|
||||
&& matches!(
|
||||
template[1],
|
||||
InlineAsmTemplatePiece::Placeholder {
|
||||
|
|
@ -36,24 +36,26 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
span: _
|
||||
}
|
||||
)
|
||||
&& template[2] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[3] == InlineAsmTemplatePiece::String("cpuid".to_string())
|
||||
&& template[4] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[5] == InlineAsmTemplatePiece::String("xchgq %rbx, ".to_string())
|
||||
&& template[2] == InlineAsmTemplatePiece::String(", rbx".to_string())
|
||||
&& template[3] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[4] == InlineAsmTemplatePiece::String("cpuid".to_string())
|
||||
&& template[5] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[6] == InlineAsmTemplatePiece::String("xchg ".to_string())
|
||||
&& matches!(
|
||||
template[6],
|
||||
template[7],
|
||||
InlineAsmTemplatePiece::Placeholder {
|
||||
operand_idx: 0,
|
||||
modifier: Some('r'),
|
||||
span: _
|
||||
}
|
||||
)
|
||||
&& template[8] == InlineAsmTemplatePiece::String(", rbx".to_string())
|
||||
{
|
||||
assert_eq!(operands.len(), 4);
|
||||
let (leaf, eax_place) = match operands[1] {
|
||||
InlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
late: true,
|
||||
late: _,
|
||||
ref in_value,
|
||||
out_place: Some(out_place),
|
||||
} => (
|
||||
|
|
@ -68,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::reg,
|
||||
)),
|
||||
late: true,
|
||||
late: _,
|
||||
place: Some(place),
|
||||
} => crate::base::codegen_place(fx, place),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -76,7 +78,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
let (sub_leaf, ecx_place) = match operands[2] {
|
||||
InlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
|
||||
late: true,
|
||||
late: _,
|
||||
ref in_value,
|
||||
out_place: Some(out_place),
|
||||
} => (
|
||||
|
|
@ -88,7 +90,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
let edx_place = match operands[3] {
|
||||
InlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
|
||||
late: true,
|
||||
late: _,
|
||||
place: Some(place),
|
||||
} => crate::base::codegen_place(fx, place),
|
||||
_ => unreachable!(),
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
|
|||
target: Option<BasicBlock>,
|
||||
) {
|
||||
match intrinsic {
|
||||
"llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
|
||||
// Spin loop hint
|
||||
}
|
||||
|
||||
// Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
|
||||
"llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
|
|
@ -25,8 +29,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
|
|||
let mut res = fx.bcx.ins().iconst(types::I32, 0);
|
||||
|
||||
for lane in (0..lane_count).rev() {
|
||||
let a_lane =
|
||||
a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);
|
||||
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
|
||||
|
||||
// cast float to int
|
||||
let a_lane = match lane_ty {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,30 @@ fn simd_for_each_lane<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn simd_pair_for_each_lane_typed<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
x: CValue<'tcx>,
|
||||
y: CValue<'tcx>,
|
||||
ret: CPlace<'tcx>,
|
||||
f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, CValue<'tcx>, CValue<'tcx>) -> CValue<'tcx>,
|
||||
) {
|
||||
assert_eq!(x.layout(), y.layout());
|
||||
let layout = x.layout();
|
||||
|
||||
let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
|
||||
let (ret_lane_count, _ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
|
||||
assert_eq!(lane_count, ret_lane_count);
|
||||
|
||||
for lane_idx in 0..lane_count {
|
||||
let x_lane = x.value_lane(fx, lane_idx);
|
||||
let y_lane = y.value_lane(fx, lane_idx);
|
||||
|
||||
let res_lane = f(fx, x_lane, y_lane);
|
||||
|
||||
ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane);
|
||||
}
|
||||
}
|
||||
|
||||
fn simd_pair_for_each_lane<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
x: CValue<'tcx>,
|
||||
|
|
@ -504,37 +528,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let signed = type_sign(lhs.layout().ty);
|
||||
|
||||
let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
|
||||
|
||||
let (val, has_overflow) = checked_res.load_scalar_pair(fx);
|
||||
let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
|
||||
|
||||
let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
|
||||
|
||||
let val = match (intrinsic, signed) {
|
||||
(sym::saturating_add, false) => fx.bcx.ins().select(has_overflow, max, val),
|
||||
(sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val),
|
||||
(sym::saturating_add, true) => {
|
||||
let rhs = rhs.load_scalar(fx);
|
||||
let rhs_ge_zero =
|
||||
fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
|
||||
let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
|
||||
fx.bcx.ins().select(has_overflow, sat_val, val)
|
||||
}
|
||||
(sym::saturating_sub, true) => {
|
||||
let rhs = rhs.load_scalar(fx);
|
||||
let rhs_ge_zero =
|
||||
fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
|
||||
let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
|
||||
fx.bcx.ins().select(has_overflow, sat_val, val)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let res = CValue::by_val(val, lhs.layout());
|
||||
|
||||
let res = crate::num::codegen_saturating_int_binop(fx, bin_op, lhs, rhs);
|
||||
ret.write_cvalue(fx, res);
|
||||
}
|
||||
sym::rotate_left => {
|
||||
|
|
@ -819,8 +813,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
sym::ptr_guaranteed_cmp => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
|
||||
let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b);
|
||||
ret.write_cvalue(fx, val);
|
||||
let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b).load_scalar(fx);
|
||||
ret.write_cvalue(fx, CValue::by_val(val, fx.layout_of(fx.tcx.types.u8)));
|
||||
}
|
||||
|
||||
sym::caller_location => {
|
||||
|
|
@ -1206,7 +1200,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
// FIXME once unwinding is supported, change this to actually catch panics
|
||||
let f_sig = fx.bcx.func.import_signature(Signature {
|
||||
call_conv: fx.target_config.default_call_conv,
|
||||
params: vec![AbiParam::new(fx.bcx.func.dfg.value_type(data))],
|
||||
params: vec![AbiParam::new(pointer_ty(fx.tcx))],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::Endian;
|
||||
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
|
|
@ -26,7 +27,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
span: Span,
|
||||
) {
|
||||
match intrinsic {
|
||||
sym::simd_cast => {
|
||||
sym::simd_as | sym::simd_cast => {
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
|
||||
if !a.layout().ty.is_simd() {
|
||||
|
|
@ -162,6 +163,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// FIXME remove this case
|
||||
intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap()
|
||||
};
|
||||
|
||||
|
|
@ -650,8 +652,128 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
// simd_saturating_*
|
||||
// simd_bitmask
|
||||
sym::simd_select_bitmask => {
|
||||
intrinsic_args!(fx, args => (m, a, b); intrinsic);
|
||||
|
||||
if !a.layout().ty.is_simd() {
|
||||
report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
|
||||
return;
|
||||
}
|
||||
assert_eq!(a.layout(), b.layout());
|
||||
|
||||
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let lane_layout = fx.layout_of(lane_ty);
|
||||
|
||||
let m = m.load_scalar(fx);
|
||||
|
||||
for lane in 0..lane_count {
|
||||
let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64);
|
||||
let m_lane = fx.bcx.ins().band_imm(m_lane, 1);
|
||||
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
|
||||
let b_lane = b.value_lane(fx, lane).load_scalar(fx);
|
||||
|
||||
let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0);
|
||||
let res_lane =
|
||||
CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout);
|
||||
|
||||
ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
|
||||
}
|
||||
}
|
||||
|
||||
sym::simd_bitmask => {
|
||||
intrinsic_args!(fx, args => (a); intrinsic);
|
||||
|
||||
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let lane_clif_ty = fx.clif_type(lane_ty).unwrap();
|
||||
|
||||
// The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
|
||||
// vector mask and returns the most significant bit (MSB) of each lane in the form
|
||||
// of either:
|
||||
// * an unsigned integer
|
||||
// * an array of `u8`
|
||||
// If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
|
||||
//
|
||||
// The bit order of the result depends on the byte endianness, LSB-first for little
|
||||
// endian and MSB-first for big endian.
|
||||
let expected_int_bits = lane_count.max(8);
|
||||
let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
|
||||
|
||||
match lane_ty.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {}
|
||||
_ => {
|
||||
fx.tcx.sess.span_fatal(
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `simd_bitmask` intrinsic: \
|
||||
vector argument `{}`'s element type `{}`, expected integer element \
|
||||
type",
|
||||
a.layout().ty,
|
||||
lane_ty
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let res_type =
|
||||
Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
|
||||
let mut res = fx.bcx.ins().iconst(res_type, 0);
|
||||
|
||||
let lanes = match fx.tcx.sess.target.endian {
|
||||
Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
|
||||
Endian::Little => Box::new((0..lane_count).rev()) as Box<dyn Iterator<Item = u64>>,
|
||||
};
|
||||
for lane in lanes {
|
||||
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
|
||||
|
||||
// extract sign bit of an int
|
||||
let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_clif_ty.bits() - 1));
|
||||
|
||||
// shift sign bit into result
|
||||
let a_lane_sign = clif_intcast(fx, a_lane_sign, res_type, false);
|
||||
res = fx.bcx.ins().ishl_imm(res, 1);
|
||||
res = fx.bcx.ins().bor(res, a_lane_sign);
|
||||
}
|
||||
|
||||
match ret.layout().ty.kind() {
|
||||
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {}
|
||||
ty::Array(elem, len)
|
||||
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||
&& len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all())
|
||||
== Some(expected_bytes) => {}
|
||||
_ => {
|
||||
fx.tcx.sess.span_fatal(
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `simd_bitmask` intrinsic: \
|
||||
cannot return `{}`, expected `u{}` or `[u8; {}]`",
|
||||
ret.layout().ty,
|
||||
expected_int_bits,
|
||||
expected_bytes
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let res = CValue::by_val(res, ret.layout());
|
||||
ret.write_cvalue(fx, res);
|
||||
}
|
||||
|
||||
sym::simd_saturating_add | sym::simd_saturating_sub => {
|
||||
intrinsic_args!(fx, args => (x, y); intrinsic);
|
||||
|
||||
let bin_op = match intrinsic {
|
||||
sym::simd_saturating_add => BinOp::Add,
|
||||
sym::simd_saturating_sub => BinOp::Sub,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// FIXME use vector instructions when possible
|
||||
simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
|
||||
crate::num::codegen_saturating_int_binop(fx, bin_op, x_lane, y_lane)
|
||||
});
|
||||
}
|
||||
|
||||
// simd_arith_offset
|
||||
// simd_scatter
|
||||
// simd_gather
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ mod prelude {
|
|||
pub(crate) use cranelift_codegen::ir::function::Function;
|
||||
pub(crate) use cranelift_codegen::ir::types;
|
||||
pub(crate) use cranelift_codegen::ir::{
|
||||
AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
|
||||
StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
|
||||
AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot,
|
||||
StackSlotData, StackSlotKind, TrapCode, Type, Value,
|
||||
};
|
||||
pub(crate) use cranelift_codegen::isa::{self, CallConv};
|
||||
pub(crate) use cranelift_codegen::Context;
|
||||
|
|
@ -251,7 +251,6 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
|
|||
|
||||
let mut flags_builder = settings::builder();
|
||||
flags_builder.enable("is_pic").unwrap();
|
||||
flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
|
||||
let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
|
||||
flags_builder.set("enable_verifier", enable_verifier).unwrap();
|
||||
flags_builder.set("regalloc_checker", enable_verifier).unwrap();
|
||||
|
|
@ -279,6 +278,15 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
|
|||
}
|
||||
}
|
||||
|
||||
if target_triple.architecture == target_lexicon::Architecture::X86_64 {
|
||||
// Windows depends on stack probes to grow the committed part of the stack
|
||||
flags_builder.enable("enable_probestack").unwrap();
|
||||
flags_builder.set("probestack_strategy", "inline").unwrap();
|
||||
} else {
|
||||
// __cranelift_probestack is not provided and inline stack probes are only supported on x86_64
|
||||
flags_builder.set("enable_probestack", "false").unwrap();
|
||||
}
|
||||
|
||||
let flags = settings::Flags::new(flags_builder);
|
||||
|
||||
let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
|
||||
|
||||
let mut ctx = Context::new();
|
||||
ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig);
|
||||
ctx.func.signature = cmain_sig;
|
||||
{
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
|
||||
|
|
|
|||
|
|
@ -150,18 +150,12 @@ pub(crate) fn codegen_int_binop<'tcx>(
|
|||
BinOp::BitXor => b.bxor(lhs, rhs),
|
||||
BinOp::BitAnd => b.band(lhs, rhs),
|
||||
BinOp::BitOr => b.bor(lhs, rhs),
|
||||
BinOp::Shl => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
fx.bcx.ins().ishl(lhs, actual_shift)
|
||||
}
|
||||
BinOp::Shl => b.ishl(lhs, rhs),
|
||||
BinOp::Shr => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
if signed {
|
||||
fx.bcx.ins().sshr(lhs, actual_shift)
|
||||
b.sshr(lhs, rhs)
|
||||
} else {
|
||||
fx.bcx.ins().ushr(lhs, actual_shift)
|
||||
b.ushr(lhs, rhs)
|
||||
}
|
||||
}
|
||||
// Compare binops handles by `codegen_binop`.
|
||||
|
|
@ -279,22 +273,15 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
|
|||
}
|
||||
}
|
||||
BinOp::Shl => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
let val = fx.bcx.ins().ishl(lhs, masked_shift);
|
||||
let val = fx.bcx.ins().ishl(lhs, rhs);
|
||||
let ty = fx.bcx.func.dfg.value_type(val);
|
||||
let max_shift = i64::from(ty.bits()) - 1;
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
|
||||
(val, has_overflow)
|
||||
}
|
||||
BinOp::Shr => {
|
||||
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
|
||||
let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
|
||||
let val = if !signed {
|
||||
fx.bcx.ins().ushr(lhs, masked_shift)
|
||||
} else {
|
||||
fx.bcx.ins().sshr(lhs, masked_shift)
|
||||
};
|
||||
let val =
|
||||
if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) };
|
||||
let ty = fx.bcx.func.dfg.value_type(val);
|
||||
let max_shift = i64::from(ty.bits()) - 1;
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
|
||||
|
|
@ -309,6 +296,42 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
|
|||
CValue::by_val_pair(res, has_overflow, out_layout)
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_saturating_int_binop<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
bin_op: BinOp,
|
||||
lhs: CValue<'tcx>,
|
||||
rhs: CValue<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
assert_eq!(lhs.layout().ty, rhs.layout().ty);
|
||||
|
||||
let signed = type_sign(lhs.layout().ty);
|
||||
let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
|
||||
let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
|
||||
|
||||
let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
|
||||
let (val, has_overflow) = checked_res.load_scalar_pair(fx);
|
||||
|
||||
let val = match (bin_op, signed) {
|
||||
(BinOp::Add, false) => fx.bcx.ins().select(has_overflow, max, val),
|
||||
(BinOp::Sub, false) => fx.bcx.ins().select(has_overflow, min, val),
|
||||
(BinOp::Add, true) => {
|
||||
let rhs = rhs.load_scalar(fx);
|
||||
let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
|
||||
let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
|
||||
fx.bcx.ins().select(has_overflow, sat_val, val)
|
||||
}
|
||||
(BinOp::Sub, true) => {
|
||||
let rhs = rhs.load_scalar(fx);
|
||||
let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
|
||||
let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
|
||||
fx.bcx.ins().select(has_overflow, sat_val, val)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
CValue::by_val(val, lhs.layout())
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_float_binop<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
bin_op: BinOp,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,12 @@ pub(crate) fn unsized_info<'tcx>(
|
|||
.bcx
|
||||
.ins()
|
||||
.iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
|
||||
(&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
|
||||
(
|
||||
&ty::Dynamic(ref data_a, _, src_dyn_kind),
|
||||
&ty::Dynamic(ref data_b, _, target_dyn_kind),
|
||||
) => {
|
||||
assert_eq!(src_dyn_kind, target_dyn_kind);
|
||||
|
||||
let old_info =
|
||||
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
|
||||
if data_a.principal_def_id() == data_b.principal_def_id() {
|
||||
|
|
@ -101,6 +106,21 @@ fn unsize_ptr<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
|
||||
pub(crate) fn cast_to_dyn_star<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
src: Value,
|
||||
src_ty_and_layout: TyAndLayout<'tcx>,
|
||||
dst_ty: Ty<'tcx>,
|
||||
old_info: Option<Value>,
|
||||
) -> (Value, Value) {
|
||||
assert!(
|
||||
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
|
||||
"destination type must be a dyn*"
|
||||
);
|
||||
(src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info))
|
||||
}
|
||||
|
||||
/// Coerce `src`, which is a reference to a value of type `src_ty`,
|
||||
/// to a value of type `dst_ty` and store the result in `dst`
|
||||
pub(crate) fn coerce_unsized_into<'tcx>(
|
||||
|
|
@ -147,6 +167,24 @@ pub(crate) fn coerce_unsized_into<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn coerce_dyn_star<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
src: CValue<'tcx>,
|
||||
dst: CPlace<'tcx>,
|
||||
) {
|
||||
let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() {
|
||||
let (data, vtable) = src.load_scalar_pair(fx);
|
||||
(data, Some(vtable))
|
||||
} else {
|
||||
let data = src.load_scalar(fx);
|
||||
(data, None)
|
||||
};
|
||||
|
||||
let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra);
|
||||
|
||||
dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
|
||||
|
||||
pub(crate) fn size_and_align_of_dst<'tcx>(
|
||||
|
|
|
|||
|
|
@ -107,6 +107,50 @@ impl<'tcx> CValue<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME remove
|
||||
// Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
|
||||
// vtable pointer.
|
||||
pub(crate) fn dyn_star_force_data_on_stack(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
) -> (Value, Value) {
|
||||
assert!(self.1.ty.is_dyn_star());
|
||||
|
||||
match self.0 {
|
||||
CValueInner::ByRef(ptr, None) => {
|
||||
let (a_scalar, b_scalar) = match self.1.abi {
|
||||
Abi::ScalarPair(a, b) => (a, b),
|
||||
_ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
|
||||
};
|
||||
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
|
||||
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
|
||||
let mut flags = MemFlags::new();
|
||||
flags.set_notrap();
|
||||
let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags);
|
||||
(ptr.get_addr(fx), vtable)
|
||||
}
|
||||
CValueInner::ByValPair(data, vtable) => {
|
||||
let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
|
||||
kind: StackSlotKind::ExplicitSlot,
|
||||
// FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
|
||||
// specify stack slot alignment.
|
||||
size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15)
|
||||
/ 16
|
||||
* 16,
|
||||
});
|
||||
let data_ptr = Pointer::stack_slot(stack_slot);
|
||||
let mut flags = MemFlags::new();
|
||||
flags.set_notrap();
|
||||
data_ptr.store(fx, data, flags);
|
||||
|
||||
(data_ptr.get_addr(fx), vtable)
|
||||
}
|
||||
CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => {
|
||||
unreachable!("dyn_star_force_data_on_stack({:?})", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
|
||||
match self.0 {
|
||||
CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
|
||||
|
|
@ -236,6 +280,10 @@ impl<'tcx> CValue<'tcx> {
|
|||
crate::unsize::coerce_unsized_into(fx, self, dest);
|
||||
}
|
||||
|
||||
pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) {
|
||||
crate::unsize::coerce_dyn_star(fx, self, dest);
|
||||
}
|
||||
|
||||
/// If `ty` is signed, `const_val` must already be sign extended.
|
||||
pub(crate) fn const_val(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
|
|
|
|||
|
|
@ -45,12 +45,26 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
|||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
arg: CValue<'tcx>,
|
||||
idx: usize,
|
||||
) -> (Value, Value) {
|
||||
let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
|
||||
arg.load_scalar_pair(fx)
|
||||
} else {
|
||||
let (ptr, vtable) = arg.try_to_ptr().unwrap();
|
||||
(ptr.get_addr(fx), vtable.unwrap())
|
||||
) -> (Pointer, Value) {
|
||||
let (ptr, vtable) = 'block: {
|
||||
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
|
||||
if ty.is_dyn_star() {
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr();
|
||||
let vtable =
|
||||
dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx);
|
||||
break 'block (ptr, vtable);
|
||||
}
|
||||
}
|
||||
|
||||
if let Abi::ScalarPair(_, _) = arg.layout().abi {
|
||||
let (ptr, vtable) = arg.load_scalar_pair(fx);
|
||||
(Pointer::new(ptr), vtable)
|
||||
} else {
|
||||
let (ptr, vtable) = arg.try_to_ptr().unwrap();
|
||||
(ptr, vtable.unwrap())
|
||||
}
|
||||
};
|
||||
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
|||
_lib_name: &str,
|
||||
_dll_imports: &[DllImport],
|
||||
_tmpdir: &Path,
|
||||
_is_direct_dependency: bool,
|
||||
) -> PathBuf {
|
||||
unimplemented!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl IntoDiagnosticArg for ExitCode {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::ranlib_failure)]
|
||||
#[diag(codegen_gcc_ranlib_failure)]
|
||||
pub(crate) struct RanlibFailure {
|
||||
exit_code: ExitCode,
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ impl RanlibFailure {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_basic_integer, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -38,7 +38,7 @@ pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_invalid_float_vector, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -48,7 +48,7 @@ pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_not_float, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -57,7 +57,7 @@ pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_unrecognized, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationUnrecognized {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -65,7 +65,7 @@ pub(crate) struct InvalidMonomorphizationUnrecognized {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -75,7 +75,7 @@ pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_unsupported_element, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -86,7 +86,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_invalid_bitmask, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -97,7 +97,7 @@ pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_simd_shuffle, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -106,7 +106,7 @@ pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_expected_simd, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -116,7 +116,7 @@ pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_mask_type, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationMaskType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -125,7 +125,7 @@ pub(crate) struct InvalidMonomorphizationMaskType<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_return_length, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -136,7 +136,7 @@ pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_return_length_input_type, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -148,7 +148,7 @@ pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_return_element, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -160,7 +160,7 @@ pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_return_type, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationReturnType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -171,7 +171,7 @@ pub(crate) struct InvalidMonomorphizationReturnType<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_inserted_type, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -182,7 +182,7 @@ pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_return_integer_type, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -192,7 +192,7 @@ pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_mismatched_lengths, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationMismatchedLengths {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -202,7 +202,7 @@ pub(crate) struct InvalidMonomorphizationMismatchedLengths {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_unsupported_cast, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -214,7 +214,7 @@ pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::invalid_monomorphization_unsupported_operation, code = "E0511")]
|
||||
#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")]
|
||||
pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -224,18 +224,18 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::linkage_const_or_mut_type)]
|
||||
#[diag(codegen_gcc_linkage_const_or_mut_type)]
|
||||
pub(crate) struct LinkageConstOrMutType {
|
||||
#[primary_span]
|
||||
pub span: Span
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::lto_not_supported)]
|
||||
#[diag(codegen_gcc_lto_not_supported)]
|
||||
pub(crate) struct LTONotSupported;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc::unwinding_inline_asm)]
|
||||
#[diag(codegen_gcc_unwinding_inline_asm)]
|
||||
pub(crate) struct UnwindingInlineAsm {
|
||||
#[primary_span]
|
||||
pub span: Span
|
||||
|
|
|
|||
|
|
@ -165,10 +165,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
lib_name: &str,
|
||||
dll_imports: &[DllImport],
|
||||
tmpdir: &Path,
|
||||
is_direct_dependency: bool,
|
||||
) -> PathBuf {
|
||||
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
|
||||
let output_path = {
|
||||
let mut output_path: PathBuf = tmpdir.to_path_buf();
|
||||
output_path.push(format!("{}_imports", lib_name));
|
||||
output_path.push(format!("{}{}", lib_name, name_suffix));
|
||||
output_path.with_extension("lib")
|
||||
};
|
||||
|
||||
|
|
@ -195,7 +197,8 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
// that loaded but crashed with an AV upon calling one of the imported
|
||||
// functions. Therefore, use binutils to create the import library instead,
|
||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||
let def_file_path = tmpdir.join(format!("{}_imports", lib_name)).with_extension("def");
|
||||
let def_file_path =
|
||||
tmpdir.join(format!("{}{}", lib_name, name_suffix)).with_extension("def");
|
||||
|
||||
let def_file_content = format!(
|
||||
"EXPORTS\n{}",
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
|
|||
|
||||
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false,
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
CrateType::Rlib | CrateType::ProcMacro => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,17 +73,6 @@ fn prepare_lto(
|
|||
// with either fat or thin LTO
|
||||
let mut upstream_modules = Vec::new();
|
||||
if cgcx.lto != Lto::ThinLocal {
|
||||
if cgcx.opts.cg.prefer_dynamic {
|
||||
diag_handler
|
||||
.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||
.note(
|
||||
"only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||
supported with LTO",
|
||||
)
|
||||
.emit();
|
||||
return Err(FatalError);
|
||||
}
|
||||
|
||||
// Make sure we actually can run LTO
|
||||
for crate_type in cgcx.crate_types.iter() {
|
||||
if !crate_type_allows_lto(*crate_type) {
|
||||
|
|
@ -92,9 +81,25 @@ fn prepare_lto(
|
|||
static library outputs",
|
||||
);
|
||||
return Err(e);
|
||||
} else if *crate_type == CrateType::Dylib {
|
||||
if !cgcx.opts.unstable_opts.dylib_lto {
|
||||
return Err(diag_handler
|
||||
.fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
|
||||
diag_handler
|
||||
.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||
.note(
|
||||
"only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||
supported with LTO",
|
||||
)
|
||||
.emit();
|
||||
return Err(FatalError);
|
||||
}
|
||||
|
||||
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
|
||||
let exported_symbols =
|
||||
cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
|
|||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||
// should use dllimport for functions.
|
||||
if cx.use_dll_storage_attrs
|
||||
&& tcx.is_dllimport_foreign_item(instance_def_id)
|
||||
&& let Some(library) = tcx.native_library(instance_def_id)
|
||||
&& library.kind.is_dllimport()
|
||||
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
|
||||
{
|
||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
||||
|
|
|
|||
|
|
@ -332,7 +332,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
if self.use_dll_storage_attrs && self.tcx.is_dllimport_foreign_item(def_id) {
|
||||
if self.use_dll_storage_attrs
|
||||
&& let Some(library) = self.tcx.native_library(def_id)
|
||||
&& library.kind.is_dllimport()
|
||||
{
|
||||
// For foreign (native) libs we know the exact storage type to use.
|
||||
unsafe {
|
||||
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ pub trait ArchiveBuilderBuilder {
|
|||
lib_name: &str,
|
||||
dll_imports: &[DllImport],
|
||||
tmpdir: &Path,
|
||||
is_direct_dependency: bool,
|
||||
) -> PathBuf;
|
||||
|
||||
fn extract_bundled_libs(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
|
|||
use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
|
|
@ -39,6 +39,7 @@ use cc::windows_registry;
|
|||
use regex::Regex;
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::OnceCell;
|
||||
use std::collections::BTreeSet;
|
||||
|
|
@ -208,11 +209,29 @@ pub fn link_binary<'a>(
|
|||
}
|
||||
|
||||
pub fn each_linked_rlib(
|
||||
sess: &Session,
|
||||
info: &CrateInfo,
|
||||
f: &mut dyn FnMut(CrateNum, &Path),
|
||||
) -> Result<(), errors::LinkRlibError> {
|
||||
let crates = info.used_crates.iter();
|
||||
let mut fmts = None;
|
||||
|
||||
let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
|
||||
if lto_active {
|
||||
for combination in info.dependency_formats.iter().combinations(2) {
|
||||
let (ty1, list1) = &combination[0];
|
||||
let (ty2, list2) = &combination[1];
|
||||
if list1 != list2 {
|
||||
return Err(errors::LinkRlibError::IncompatibleDependencyFormats {
|
||||
ty1: format!("{ty1:?}"),
|
||||
ty2: format!("{ty2:?}"),
|
||||
list1: format!("{list1:?}"),
|
||||
list2: format!("{list2:?}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ty, list) in info.dependency_formats.iter() {
|
||||
match ty {
|
||||
CrateType::Executable
|
||||
|
|
@ -222,6 +241,10 @@ pub fn each_linked_rlib(
|
|||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
CrateType::Dylib if lto_active => {
|
||||
fmts = Some(list);
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -368,13 +391,14 @@ fn link_rlib<'a>(
|
|||
}
|
||||
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
|
||||
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
|
||||
{
|
||||
let output_path = archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
&raw_dylib_imports,
|
||||
tmpdir.as_ref(),
|
||||
true,
|
||||
);
|
||||
|
||||
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
|
||||
|
|
@ -426,9 +450,9 @@ fn link_rlib<'a>(
|
|||
/// then the CodegenResults value contains one NativeLib instance for each block. However, the
|
||||
/// linker appears to expect only a single import library for each library used, so we need to
|
||||
/// collate the symbols together by library name before generating the import libraries.
|
||||
fn collate_raw_dylibs(
|
||||
sess: &Session,
|
||||
used_libraries: &[NativeLib],
|
||||
fn collate_raw_dylibs<'a, 'b>(
|
||||
sess: &'a Session,
|
||||
used_libraries: impl IntoIterator<Item = &'b NativeLib>,
|
||||
) -> Result<Vec<(String, Vec<DllImport>)>, ErrorGuaranteed> {
|
||||
// Use index maps to preserve original order of imports and libraries.
|
||||
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
|
||||
|
|
@ -490,7 +514,7 @@ fn link_staticlib<'a>(
|
|||
)?;
|
||||
let mut all_native_libs = vec![];
|
||||
|
||||
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
|
||||
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
||||
let name = codegen_results.crate_info.crate_name[&cnum];
|
||||
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||
|
||||
|
|
@ -2045,13 +2069,43 @@ fn linker_with_args<'a>(
|
|||
|
||||
// Link with the import library generated for any raw-dylib functions.
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
|
||||
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
|
||||
{
|
||||
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
&raw_dylib_imports,
|
||||
tmpdir,
|
||||
true,
|
||||
));
|
||||
}
|
||||
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
|
||||
// they are used within inlined functions or instantiated generic functions. We do this *after*
|
||||
// handling the raw-dylib symbols in the current crate to make sure that those are chosen first
|
||||
// by the linker.
|
||||
let (_, dependency_linkage) = codegen_results
|
||||
.crate_info
|
||||
.dependency_formats
|
||||
.iter()
|
||||
.find(|(ty, _)| *ty == crate_type)
|
||||
.expect("failed to find crate type in dependency format list");
|
||||
let native_libraries_from_nonstatics = codegen_results
|
||||
.crate_info
|
||||
.native_libraries
|
||||
.iter()
|
||||
.filter_map(|(cnum, libraries)| {
|
||||
(dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then(|| libraries)
|
||||
})
|
||||
.flatten();
|
||||
for (raw_dylib_name, raw_dylib_imports) in
|
||||
collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
|
||||
{
|
||||
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
|
||||
sess,
|
||||
&raw_dylib_name,
|
||||
&raw_dylib_imports,
|
||||
tmpdir,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
|
|||
"riscv32" => Architecture::Riscv32,
|
||||
"riscv64" => Architecture::Riscv64,
|
||||
"sparc64" => Architecture::Sparc64,
|
||||
"avr" => Architecture::Avr,
|
||||
"msp430" => Architecture::Msp430,
|
||||
"hexagon" => Architecture::Hexagon,
|
||||
"bpf" => Architecture::Bpf,
|
||||
// Unsupported architecture.
|
||||
_ => return None,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_middle::ty::query::{ExternProviders, Providers};
|
|||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::{self, SymbolName, TyCtxt};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::config::{CrateType, OomStrategy};
|
||||
use rustc_target::spec::SanitizerSet;
|
||||
|
||||
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
|
||||
|
|
@ -76,7 +76,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
|
|||
// let it through if it's included statically.
|
||||
match tcx.hir().get_by_def_id(def_id) {
|
||||
Node::ForeignItem(..) => {
|
||||
tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
|
||||
tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id)
|
||||
}
|
||||
|
||||
// Only consider nodes that actually have exported symbols.
|
||||
|
|
@ -206,6 +206,15 @@ fn exported_symbols_provider_local<'tcx>(
|
|||
},
|
||||
));
|
||||
}
|
||||
|
||||
symbols.push((
|
||||
ExportedSymbol::NoDefId(SymbolName::new(tcx, OomStrategy::SYMBOL)),
|
||||
SymbolExportInfo {
|
||||
level: SymbolExportLevel::Rust,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: false,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
|
||||
|
|
|
|||
|
|
@ -999,6 +999,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
let coordinator_send = tx_to_llvm_workers;
|
||||
let sess = tcx.sess;
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
// Compute the set of symbols we need to retain when doing LTO (if we need to)
|
||||
let exported_symbols = {
|
||||
let mut exported_symbols = FxHashMap::default();
|
||||
|
|
@ -1020,7 +1028,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
}
|
||||
Lto::Fat | Lto::Thin => {
|
||||
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
|
||||
for &cnum in tcx.crates(()).iter() {
|
||||
for &(cnum, ref _path) in &each_linked_rlib_for_lto {
|
||||
exported_symbols.insert(cnum, copy_symbols(cnum));
|
||||
}
|
||||
Some(Arc::new(exported_symbols))
|
||||
|
|
@ -1040,14 +1048,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
})
|
||||
.expect("failed to spawn helper thread");
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
|
||||
if link::ignored_for_lto(sess, crate_info, cnum) {
|
||||
return;
|
||||
}
|
||||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
let ol =
|
||||
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
|
||||
// If we know that we won’t be doing codegen, create target machines without optimisation.
|
||||
|
|
|
|||
|
|
@ -337,40 +337,26 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
op: hir::BinOpKind,
|
||||
lhs: Bx::Value,
|
||||
rhs: Bx::Value,
|
||||
) -> Bx::Value {
|
||||
cast_shift_rhs(bx, op, lhs, rhs)
|
||||
}
|
||||
|
||||
fn cast_shift_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
op: hir::BinOpKind,
|
||||
lhs: Bx::Value,
|
||||
rhs: Bx::Value,
|
||||
) -> Bx::Value {
|
||||
// Shifts may have any size int on the rhs
|
||||
if op.is_shift() {
|
||||
let mut rhs_llty = bx.cx().val_ty(rhs);
|
||||
let mut lhs_llty = bx.cx().val_ty(lhs);
|
||||
if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
|
||||
rhs_llty = bx.cx().element_type(rhs_llty)
|
||||
}
|
||||
if bx.cx().type_kind(lhs_llty) == TypeKind::Vector {
|
||||
lhs_llty = bx.cx().element_type(lhs_llty)
|
||||
}
|
||||
let rhs_sz = bx.cx().int_width(rhs_llty);
|
||||
let lhs_sz = bx.cx().int_width(lhs_llty);
|
||||
if lhs_sz < rhs_sz {
|
||||
bx.trunc(rhs, lhs_llty)
|
||||
} else if lhs_sz > rhs_sz {
|
||||
// FIXME (#1877: If in the future shifting by negative
|
||||
// values is no longer undefined then this is wrong.
|
||||
bx.zext(rhs, lhs_llty)
|
||||
} else {
|
||||
rhs
|
||||
}
|
||||
let mut rhs_llty = bx.cx().val_ty(rhs);
|
||||
let mut lhs_llty = bx.cx().val_ty(lhs);
|
||||
if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
|
||||
rhs_llty = bx.cx().element_type(rhs_llty)
|
||||
}
|
||||
if bx.cx().type_kind(lhs_llty) == TypeKind::Vector {
|
||||
lhs_llty = bx.cx().element_type(lhs_llty)
|
||||
}
|
||||
let rhs_sz = bx.cx().int_width(rhs_llty);
|
||||
let lhs_sz = bx.cx().int_width(lhs_llty);
|
||||
if lhs_sz < rhs_sz {
|
||||
bx.trunc(rhs, lhs_llty)
|
||||
} else if lhs_sz > rhs_sz {
|
||||
// FIXME (#1877: If in the future shifting by negative
|
||||
// values is no longer undefined then this is wrong.
|
||||
bx.zext(rhs, lhs_llty)
|
||||
} else {
|
||||
rhs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
|
||||
|
|
@ -140,7 +139,7 @@ pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
lhs: Bx::Value,
|
||||
rhs: Bx::Value,
|
||||
) -> Bx::Value {
|
||||
let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
|
||||
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
|
||||
// #1877, #10183: Ensure that input is always valid
|
||||
let rhs = shift_mask_rhs(bx, rhs);
|
||||
bx.shl(lhs, rhs)
|
||||
|
|
@ -152,7 +151,7 @@ pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
lhs: Bx::Value,
|
||||
rhs: Bx::Value,
|
||||
) -> Bx::Value {
|
||||
let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
|
||||
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
|
||||
// #1877, #10183: Ensure that input is always valid
|
||||
let rhs = shift_mask_rhs(bx, rhs);
|
||||
let is_signed = lhs_t.is_signed();
|
||||
|
|
|
|||
|
|
@ -666,10 +666,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
|
|||
hcx.while_hashing_spans(false, |hcx| {
|
||||
ct.to_valtree().hash_stable(hcx, &mut hasher)
|
||||
});
|
||||
// Note: Don't use `StableHashResult` impl of `u64` here directly, since that
|
||||
// would lead to endianness problems.
|
||||
let hash: u128 = hasher.finish();
|
||||
(hash.to_le() as u64).to_le()
|
||||
let hash: u64 = hasher.finish();
|
||||
hash
|
||||
});
|
||||
|
||||
if cpp_like_debuginfo(tcx) {
|
||||
|
|
|
|||
|
|
@ -13,43 +13,43 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::ExitStatus;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::lib_def_write_failure)]
|
||||
#[diag(codegen_ssa_lib_def_write_failure)]
|
||||
pub struct LibDefWriteFailure {
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::version_script_write_failure)]
|
||||
#[diag(codegen_ssa_version_script_write_failure)]
|
||||
pub struct VersionScriptWriteFailure {
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::symbol_file_write_failure)]
|
||||
#[diag(codegen_ssa_symbol_file_write_failure)]
|
||||
pub struct SymbolFileWriteFailure {
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::ld64_unimplemented_modifier)]
|
||||
#[diag(codegen_ssa_ld64_unimplemented_modifier)]
|
||||
pub struct Ld64UnimplementedModifier;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::linker_unsupported_modifier)]
|
||||
#[diag(codegen_ssa_linker_unsupported_modifier)]
|
||||
pub struct LinkerUnsupportedModifier;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::L4Bender_exporting_symbols_unimplemented)]
|
||||
#[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)]
|
||||
pub struct L4BenderExportingSymbolsUnimplemented;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::no_natvis_directory)]
|
||||
#[diag(codegen_ssa_no_natvis_directory)]
|
||||
pub struct NoNatvisDirectory {
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::copy_path_buf)]
|
||||
#[diag(codegen_ssa_copy_path_buf)]
|
||||
pub struct CopyPathBuf {
|
||||
pub source_file: PathBuf,
|
||||
pub output_path: PathBuf,
|
||||
|
|
@ -58,7 +58,7 @@ pub struct CopyPathBuf {
|
|||
|
||||
// Reports Paths using `Debug` implementation rather than Path's `Display` implementation.
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::copy_path)]
|
||||
#[diag(codegen_ssa_copy_path)]
|
||||
pub struct CopyPath<'a> {
|
||||
from: DebugArgPath<'a>,
|
||||
to: DebugArgPath<'a>,
|
||||
|
|
@ -80,36 +80,36 @@ impl IntoDiagnosticArg for DebugArgPath<'_> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::ignoring_emit_path)]
|
||||
#[diag(codegen_ssa_ignoring_emit_path)]
|
||||
pub struct IgnoringEmitPath {
|
||||
pub extension: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::ignoring_output)]
|
||||
#[diag(codegen_ssa_ignoring_output)]
|
||||
pub struct IgnoringOutput {
|
||||
pub extension: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::create_temp_dir)]
|
||||
#[diag(codegen_ssa_create_temp_dir)]
|
||||
pub struct CreateTempDir {
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::incompatible_linking_modifiers)]
|
||||
#[diag(codegen_ssa_incompatible_linking_modifiers)]
|
||||
pub struct IncompatibleLinkingModifiers;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::add_native_library)]
|
||||
#[diag(codegen_ssa_add_native_library)]
|
||||
pub struct AddNativeLibrary {
|
||||
pub library_path: PathBuf,
|
||||
pub error: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa::multiple_external_func_decl)]
|
||||
#[diag(codegen_ssa_multiple_external_func_decl)]
|
||||
pub struct MultipleExternalFuncDecl<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -119,14 +119,17 @@ pub struct MultipleExternalFuncDecl<'a> {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum LinkRlibError {
|
||||
#[diag(codegen_ssa::rlib_missing_format)]
|
||||
#[diag(codegen_ssa_rlib_missing_format)]
|
||||
MissingFormat,
|
||||
|
||||
#[diag(codegen_ssa::rlib_only_rmeta_found)]
|
||||
#[diag(codegen_ssa_rlib_only_rmeta_found)]
|
||||
OnlyRmetaFound { crate_name: Symbol },
|
||||
|
||||
#[diag(codegen_ssa::rlib_not_found)]
|
||||
#[diag(codegen_ssa_rlib_not_found)]
|
||||
NotFound { crate_name: Symbol },
|
||||
|
||||
#[diag(codegen_ssa_rlib_incompatible_dependency_formats)]
|
||||
IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String },
|
||||
}
|
||||
|
||||
pub struct ThorinErrorWrapper(pub thorin::Error);
|
||||
|
|
@ -136,188 +139,188 @@ impl IntoDiagnostic<'_> for ThorinErrorWrapper {
|
|||
let mut diag;
|
||||
match self.0 {
|
||||
thorin::Error::ReadInput(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_read_input_failure);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_read_input_failure);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseFileKind(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_file_kind);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseObjectFile(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_object_file);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseArchiveFile(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_input_archive_file);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseArchiveMember(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_archive_member);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_archive_member);
|
||||
diag
|
||||
}
|
||||
thorin::Error::InvalidInputKind => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_invalid_input_kind);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DecompressData(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_decompress_data);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_decompress_data);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NamelessSection(_, offset) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_section_without_name);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_section_without_name);
|
||||
diag.set_arg("offset", format!("0x{:08x}", offset));
|
||||
diag
|
||||
}
|
||||
thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
|
||||
diag =
|
||||
handler.struct_err(fluent::codegen_ssa::thorin_relocation_with_invalid_symbol);
|
||||
handler.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{:08x}", offset));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleRelocations(section, offset) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_relocations);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_relocations);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{:08x}", offset));
|
||||
diag
|
||||
}
|
||||
thorin::Error::UnsupportedRelocation(section, offset) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_unsupported_relocation);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("offset", format!("0x{:08x}", offset));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingDwoName(id) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_dwo_name);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name);
|
||||
diag.set_arg("id", format!("0x{:08x}", id));
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoCompilationUnits => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_no_compilation_units);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_no_compilation_units);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoDie => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_no_die);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_no_die);
|
||||
diag
|
||||
}
|
||||
thorin::Error::TopLevelDieNotUnit => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_top_level_die_not_unit);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingRequiredSection(section) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_required_section);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_required_section);
|
||||
diag.set_arg("section", section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitAbbreviations(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_abbreviations);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitAttribute(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_attribute);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnitHeader(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit_header);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_header);
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseUnit(_) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_unit);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_incompatible_index_version);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version);
|
||||
diag.set_arg("section", section);
|
||||
diag.set_arg("actual", actual);
|
||||
diag.set_arg("format", format);
|
||||
diag
|
||||
}
|
||||
thorin::Error::OffsetAtIndex(_, index) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_offset_at_index);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_offset_at_index);
|
||||
diag.set_arg("index", index);
|
||||
diag
|
||||
}
|
||||
thorin::Error::StrAtOffset(_, offset) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_str_at_offset);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_str_at_offset);
|
||||
diag.set_arg("offset", format!("0x{:08x}", offset));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ParseIndex(_, section) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_parse_index);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_index);
|
||||
diag.set_arg("section", section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::UnitNotInIndex(unit) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_unit_not_in_index);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index);
|
||||
diag.set_arg("unit", format!("0x{:08x}", unit));
|
||||
diag
|
||||
}
|
||||
thorin::Error::RowNotInIndex(_, row) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_row_not_in_index);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_row_not_in_index);
|
||||
diag.set_arg("row", row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::SectionNotInRow => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_section_not_in_row);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_section_not_in_row);
|
||||
diag
|
||||
}
|
||||
thorin::Error::EmptyUnit(unit) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_empty_unit);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_empty_unit);
|
||||
diag.set_arg("unit", format!("0x{:08x}", unit));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleDebugInfoSection => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_debug_info_section);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::MultipleDebugTypesSection => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_multiple_debug_types_section);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section);
|
||||
diag
|
||||
}
|
||||
thorin::Error::NotSplitUnit => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_not_split_unit);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_not_split_unit);
|
||||
diag
|
||||
}
|
||||
thorin::Error::DuplicateUnit(unit) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_duplicate_unit);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_duplicate_unit);
|
||||
diag.set_arg("unit", format!("0x{:08x}", unit));
|
||||
diag
|
||||
}
|
||||
thorin::Error::MissingReferencedUnit(unit) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_missing_referenced_unit);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit);
|
||||
diag.set_arg("unit", format!("0x{:08x}", unit));
|
||||
diag
|
||||
}
|
||||
thorin::Error::NoOutputObjectCreated => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_not_output_object_created);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_not_output_object_created);
|
||||
diag
|
||||
}
|
||||
thorin::Error::MixedInputEncodings => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_mixed_input_encodings);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings);
|
||||
diag
|
||||
}
|
||||
thorin::Error::Io(e) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_io);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_io);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ObjectRead(e) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_object_read);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_object_read);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::ObjectWrite(e) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_object_write);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_object_write);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::GimliRead(e) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_gimli_read);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_read);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
thorin::Error::GimliWrite(e) => {
|
||||
diag = handler.struct_err(fluent::codegen_ssa::thorin_gimli_write);
|
||||
diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_write);
|
||||
diag.set_arg("error", format!("{e}"));
|
||||
diag
|
||||
}
|
||||
|
|
@ -335,7 +338,7 @@ pub struct LinkingFailed<'a> {
|
|||
|
||||
impl IntoDiagnostic<'_> for LinkingFailed<'_> {
|
||||
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let mut diag = handler.struct_err(fluent::codegen_ssa::linking_failed);
|
||||
let mut diag = handler.struct_err(fluent::codegen_ssa_linking_failed);
|
||||
diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
|
||||
diag.set_arg("exit_status", format!("{}", self.exit_status));
|
||||
|
||||
|
|
@ -344,9 +347,9 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> {
|
|||
// Trying to match an error from OS linkers
|
||||
// which by now we have no way to translate.
|
||||
if self.escaped_output.contains("undefined reference to") {
|
||||
diag.note(fluent::codegen_ssa::extern_funcs_not_found)
|
||||
.note(fluent::codegen_ssa::specify_libraries_to_link)
|
||||
.note(fluent::codegen_ssa::use_cargo_directive);
|
||||
diag.note(fluent::codegen_ssa_extern_funcs_not_found)
|
||||
.note(fluent::codegen_ssa_specify_libraries_to_link)
|
||||
.note(fluent::codegen_ssa_use_cargo_directive);
|
||||
}
|
||||
diag
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
|
||||
/// Get a basic block (creating it if necessary), possibly with a landing
|
||||
/// pad next to it.
|
||||
fn llbb_with_landing_pad<Bx: BuilderMethods<'a, 'tcx>>(
|
||||
&self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, Bx>,
|
||||
target: mir::BasicBlock,
|
||||
|
|
@ -73,32 +75,36 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
let target_funclet = fx.cleanup_kinds[target].funclet_bb(target);
|
||||
match (self.funclet_bb, target_funclet) {
|
||||
(None, None) => (lltarget, false),
|
||||
(Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => {
|
||||
(lltarget, false)
|
||||
}
|
||||
// jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC
|
||||
(None, Some(_)) => (fx.landing_pad_for(target), false),
|
||||
(Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator),
|
||||
(Some(_), Some(_)) => (fx.landing_pad_for(target), true),
|
||||
(Some(f), Some(t_f)) => {
|
||||
if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) {
|
||||
(lltarget, false)
|
||||
} else {
|
||||
(fx.landing_pad_for(target), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a basic block.
|
||||
fn llblock<Bx: BuilderMethods<'a, 'tcx>>(
|
||||
/// Get a basic block (creating it if necessary), possibly with cleanup
|
||||
/// stuff in it or next to it.
|
||||
fn llbb_with_cleanup<Bx: BuilderMethods<'a, 'tcx>>(
|
||||
&self,
|
||||
fx: &mut FunctionCx<'a, 'tcx, Bx>,
|
||||
target: mir::BasicBlock,
|
||||
) -> Bx::BasicBlock {
|
||||
let (lltarget, is_cleanupret) = self.lltarget(fx, target);
|
||||
let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target);
|
||||
if is_cleanupret {
|
||||
// MSVC cross-funclet jump - need a trampoline
|
||||
|
||||
debug!("llblock: creating cleanup trampoline for {:?}", target);
|
||||
debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess));
|
||||
debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
|
||||
let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
|
||||
let trampoline = Bx::append_block(fx.cx, fx.llfn, name);
|
||||
let mut trampoline_bx = Bx::build(fx.cx, trampoline);
|
||||
let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
|
||||
let mut trampoline_bx = Bx::build(fx.cx, trampoline_llbb);
|
||||
trampoline_bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
|
||||
trampoline
|
||||
trampoline_llbb
|
||||
} else {
|
||||
lltarget
|
||||
}
|
||||
|
|
@ -110,10 +116,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
bx: &mut Bx,
|
||||
target: mir::BasicBlock,
|
||||
) {
|
||||
let (lltarget, is_cleanupret) = self.lltarget(fx, target);
|
||||
let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target);
|
||||
if is_cleanupret {
|
||||
// micro-optimization: generate a `ret` rather than a jump
|
||||
// MSVC micro-optimization: generate a `ret` rather than a jump
|
||||
// to a trampoline.
|
||||
debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess));
|
||||
bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
|
||||
} else {
|
||||
bx.br(lltarget);
|
||||
|
|
@ -138,7 +145,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
|
||||
|
||||
let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
|
||||
Some(self.llblock(fx, cleanup))
|
||||
Some(self.llbb_with_cleanup(fx, cleanup))
|
||||
} else if fx.mir[self.bb].is_cleanup
|
||||
&& fn_abi.can_unwind
|
||||
&& !base::wants_msvc_seh(fx.cx.tcx().sess)
|
||||
|
|
@ -231,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
options,
|
||||
line_spans,
|
||||
instance,
|
||||
Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))),
|
||||
Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))),
|
||||
);
|
||||
} else {
|
||||
bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None);
|
||||
|
|
@ -281,8 +288,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if target_iter.len() == 1 {
|
||||
// If there are two targets (one conditional, one fallback), emit br instead of switch
|
||||
let (test_value, target) = target_iter.next().unwrap();
|
||||
let lltrue = helper.llblock(self, target);
|
||||
let llfalse = helper.llblock(self, targets.otherwise());
|
||||
let lltrue = helper.llbb_with_cleanup(self, target);
|
||||
let llfalse = helper.llbb_with_cleanup(self, targets.otherwise());
|
||||
if switch_ty == bx.tcx().types.bool {
|
||||
// Don't generate trivial icmps when switching on bool
|
||||
match test_value {
|
||||
|
|
@ -299,8 +306,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
} else {
|
||||
bx.switch(
|
||||
discr.immediate(),
|
||||
helper.llblock(self, targets.otherwise()),
|
||||
target_iter.map(|(value, target)| (value, helper.llblock(self, target))),
|
||||
helper.llbb_with_cleanup(self, targets.otherwise()),
|
||||
target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let cond = bx.expect(cond, expected);
|
||||
|
||||
// Create the failure block and the conditional branch to it.
|
||||
let lltarget = helper.llblock(self, target);
|
||||
let lltarget = helper.llbb_with_cleanup(self, target);
|
||||
let panic_block = bx.append_sibling_block("panic");
|
||||
if expected {
|
||||
bx.cond_br(cond, lltarget, panic_block);
|
||||
|
|
@ -1459,20 +1466,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// bar();
|
||||
// }
|
||||
Some(&mir::TerminatorKind::Abort) => {
|
||||
let cs_bb =
|
||||
let cs_llbb =
|
||||
Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb));
|
||||
let cp_bb =
|
||||
let cp_llbb =
|
||||
Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb));
|
||||
ret_llbb = cs_bb;
|
||||
ret_llbb = cs_llbb;
|
||||
|
||||
let mut cs_bx = Bx::build(self.cx, cs_bb);
|
||||
let cs = cs_bx.catch_switch(None, None, &[cp_bb]);
|
||||
let mut cs_bx = Bx::build(self.cx, cs_llbb);
|
||||
let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
|
||||
|
||||
// The "null" here is actually a RTTI type descriptor for the
|
||||
// C++ personality function, but `catch (...)` has no type so
|
||||
// it's null. The 64 here is actually a bitfield which
|
||||
// represents that this is a catch-all block.
|
||||
let mut cp_bx = Bx::build(self.cx, cp_bb);
|
||||
let mut cp_bx = Bx::build(self.cx, cp_llbb);
|
||||
let null = cp_bx.const_null(
|
||||
cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space),
|
||||
);
|
||||
|
|
@ -1481,10 +1488,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
cp_bx.br(llbb);
|
||||
}
|
||||
_ => {
|
||||
let cleanup_bb =
|
||||
let cleanup_llbb =
|
||||
Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
|
||||
ret_llbb = cleanup_bb;
|
||||
let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
|
||||
ret_llbb = cleanup_llbb;
|
||||
let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
|
||||
funclet = cleanup_bx.cleanup_pad(None, &[]);
|
||||
cleanup_bx.br(llbb);
|
||||
}
|
||||
|
|
@ -1492,19 +1499,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.funclets[bb] = Some(funclet);
|
||||
ret_llbb
|
||||
} else {
|
||||
let bb = Bx::append_block(self.cx, self.llfn, "cleanup");
|
||||
let mut bx = Bx::build(self.cx, bb);
|
||||
let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup");
|
||||
let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
|
||||
|
||||
let llpersonality = self.cx.eh_personality();
|
||||
let llretty = self.landing_pad_type();
|
||||
let lp = bx.cleanup_landing_pad(llretty, llpersonality);
|
||||
let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality);
|
||||
|
||||
let slot = self.get_personality_slot(&mut bx);
|
||||
slot.storage_live(&mut bx);
|
||||
Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot);
|
||||
let slot = self.get_personality_slot(&mut cleanup_bx);
|
||||
slot.storage_live(&mut cleanup_bx);
|
||||
Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1))
|
||||
.store(&mut cleanup_bx, slot);
|
||||
|
||||
bx.br(llbb);
|
||||
bx.llbb()
|
||||
cleanup_bx.br(llbb);
|
||||
cleanup_llbb
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -148,10 +148,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
|
||||
|
||||
let start_llbb = Bx::append_block(cx, llfn, "start");
|
||||
let mut bx = Bx::build(cx, start_llbb);
|
||||
let mut start_bx = Bx::build(cx, start_llbb);
|
||||
|
||||
if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) {
|
||||
bx.set_personality_fn(cx.eh_personality());
|
||||
start_bx.set_personality_fn(cx.eh_personality());
|
||||
}
|
||||
|
||||
let cleanup_kinds = analyze::cleanup_kinds(&mir);
|
||||
|
|
@ -180,7 +180,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
caller_location: None,
|
||||
};
|
||||
|
||||
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx);
|
||||
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
|
||||
|
||||
// Evaluate all required consts; codegen later assumes that CTFE will never fail.
|
||||
let mut all_consts_ok = true;
|
||||
|
|
@ -206,29 +206,29 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
// Allocate variable and temp allocas
|
||||
fx.locals = {
|
||||
let args = arg_local_refs(&mut bx, &mut fx, &memory_locals);
|
||||
let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals);
|
||||
|
||||
let mut allocate_local = |local| {
|
||||
let decl = &mir.local_decls[local];
|
||||
let layout = bx.layout_of(fx.monomorphize(decl.ty));
|
||||
let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
|
||||
assert!(!layout.ty.has_erasable_regions());
|
||||
|
||||
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
|
||||
debug!("alloc: {:?} (return place) -> place", local);
|
||||
let llretptr = bx.get_param(0);
|
||||
let llretptr = start_bx.get_param(0);
|
||||
return LocalRef::Place(PlaceRef::new_sized(llretptr, layout));
|
||||
}
|
||||
|
||||
if memory_locals.contains(local) {
|
||||
debug!("alloc: {:?} -> place", local);
|
||||
if layout.is_unsized() {
|
||||
LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout))
|
||||
LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut start_bx, layout))
|
||||
} else {
|
||||
LocalRef::Place(PlaceRef::alloca(&mut bx, layout))
|
||||
LocalRef::Place(PlaceRef::alloca(&mut start_bx, layout))
|
||||
}
|
||||
} else {
|
||||
debug!("alloc: {:?} -> operand", local);
|
||||
LocalRef::new_operand(&mut bx, layout)
|
||||
LocalRef::new_operand(&mut start_bx, layout)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
};
|
||||
|
||||
// Apply debuginfo to the newly allocated locals.
|
||||
fx.debug_introduce_locals(&mut bx);
|
||||
fx.debug_introduce_locals(&mut start_bx);
|
||||
|
||||
// Codegen the body of each block using reverse postorder
|
||||
for (bb, _) in traversal::reverse_postorder(&mir) {
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@ use rustc_macros::Diagnostic;
|
|||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unstable_in_stable)]
|
||||
#[diag(const_eval_unstable_in_stable)]
|
||||
pub(crate) struct UnstableInStable {
|
||||
pub gate: String,
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(
|
||||
const_eval::unstable_sugg,
|
||||
unstable_sugg,
|
||||
code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
|
||||
applicability = "has-placeholders"
|
||||
)]
|
||||
#[suggestion(
|
||||
const_eval::bypass_sugg,
|
||||
bypass_sugg,
|
||||
code = "#[rustc_allow_const_fn_unstable({gate})]\n",
|
||||
applicability = "has-placeholders"
|
||||
)]
|
||||
|
|
@ -22,35 +22,35 @@ pub(crate) struct UnstableInStable {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::thread_local_access, code = "E0625")]
|
||||
#[diag(const_eval_thread_local_access, code = "E0625")]
|
||||
pub(crate) struct NonConstOpErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::static_access, code = "E0013")]
|
||||
#[diag(const_eval_static_access, code = "E0013")]
|
||||
#[help]
|
||||
pub(crate) struct StaticAccessErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: ConstContext,
|
||||
#[note(const_eval::teach_note)]
|
||||
#[help(const_eval::teach_help)]
|
||||
#[note(teach_note)]
|
||||
#[help(teach_help)]
|
||||
pub teach: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::raw_ptr_to_int)]
|
||||
#[diag(const_eval_raw_ptr_to_int)]
|
||||
#[note]
|
||||
#[note(const_eval::note2)]
|
||||
#[note(note2)]
|
||||
pub(crate) struct RawPtrToIntErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::raw_ptr_comparison)]
|
||||
#[diag(const_eval_raw_ptr_comparison)]
|
||||
#[note]
|
||||
pub(crate) struct RawPtrComparisonErr {
|
||||
#[primary_span]
|
||||
|
|
@ -58,14 +58,14 @@ pub(crate) struct RawPtrComparisonErr {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::panic_non_str)]
|
||||
#[diag(const_eval_panic_non_str)]
|
||||
pub(crate) struct PanicNonStrErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::mut_deref, code = "E0658")]
|
||||
#[diag(const_eval_mut_deref, code = "E0658")]
|
||||
pub(crate) struct MutDerefErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -73,7 +73,7 @@ pub(crate) struct MutDerefErr {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::transient_mut_borrow, code = "E0658")]
|
||||
#[diag(const_eval_transient_mut_borrow, code = "E0658")]
|
||||
pub(crate) struct TransientMutBorrowErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -81,7 +81,7 @@ pub(crate) struct TransientMutBorrowErr {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::transient_mut_borrow_raw, code = "E0658")]
|
||||
#[diag(const_eval_transient_mut_borrow_raw, code = "E0658")]
|
||||
pub(crate) struct TransientMutBorrowErrRaw {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -89,7 +89,7 @@ pub(crate) struct TransientMutBorrowErrRaw {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::max_num_nodes_in_const)]
|
||||
#[diag(const_eval_max_num_nodes_in_const)]
|
||||
pub(crate) struct MaxNumNodesInConstErr {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -97,7 +97,7 @@ pub(crate) struct MaxNumNodesInConstErr {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unallowed_fn_pointer_call)]
|
||||
#[diag(const_eval_unallowed_fn_pointer_call)]
|
||||
pub(crate) struct UnallowedFnPointerCall {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -105,7 +105,7 @@ pub(crate) struct UnallowedFnPointerCall {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unstable_const_fn)]
|
||||
#[diag(const_eval_unstable_const_fn)]
|
||||
pub(crate) struct UnstableConstFn {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -113,26 +113,26 @@ pub(crate) struct UnstableConstFn {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unallowed_mutable_refs, code = "E0764")]
|
||||
#[diag(const_eval_unallowed_mutable_refs, code = "E0764")]
|
||||
pub(crate) struct UnallowedMutableRefs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: ConstContext,
|
||||
#[note(const_eval::teach_note)]
|
||||
#[note(teach_note)]
|
||||
pub teach: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unallowed_mutable_refs_raw, code = "E0764")]
|
||||
#[diag(const_eval_unallowed_mutable_refs_raw, code = "E0764")]
|
||||
pub(crate) struct UnallowedMutableRefsRaw {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: ConstContext,
|
||||
#[note(const_eval::teach_note)]
|
||||
#[note(teach_note)]
|
||||
pub teach: Option<()>,
|
||||
}
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::non_const_fmt_macro_call, code = "E0015")]
|
||||
#[diag(const_eval_non_const_fmt_macro_call, code = "E0015")]
|
||||
pub(crate) struct NonConstFmtMacroCall {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -140,7 +140,7 @@ pub(crate) struct NonConstFmtMacroCall {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::non_const_fn_call, code = "E0015")]
|
||||
#[diag(const_eval_non_const_fn_call, code = "E0015")]
|
||||
pub(crate) struct NonConstFnCall {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -149,7 +149,7 @@ pub(crate) struct NonConstFnCall {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unallowed_op_in_const_context)]
|
||||
#[diag(const_eval_unallowed_op_in_const_context)]
|
||||
pub(crate) struct UnallowedOpInConstContext {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -157,18 +157,18 @@ pub(crate) struct UnallowedOpInConstContext {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unallowed_heap_allocations, code = "E0010")]
|
||||
#[diag(const_eval_unallowed_heap_allocations, code = "E0010")]
|
||||
pub(crate) struct UnallowedHeapAllocations {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub kind: ConstContext,
|
||||
#[note(const_eval::teach_note)]
|
||||
#[note(teach_note)]
|
||||
pub teach: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::unallowed_inline_asm, code = "E0015")]
|
||||
#[diag(const_eval_unallowed_inline_asm, code = "E0015")]
|
||||
pub(crate) struct UnallowedInlineAsm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -176,7 +176,7 @@ pub(crate) struct UnallowedInlineAsm {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::interior_mutable_data_refer, code = "E0492")]
|
||||
#[diag(const_eval_interior_mutable_data_refer, code = "E0492")]
|
||||
pub(crate) struct InteriorMutableDataRefer {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -184,12 +184,12 @@ pub(crate) struct InteriorMutableDataRefer {
|
|||
#[help]
|
||||
pub opt_help: Option<()>,
|
||||
pub kind: ConstContext,
|
||||
#[note(const_eval::teach_note)]
|
||||
#[note(teach_note)]
|
||||
pub teach: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(const_eval::interior_mutability_borrow)]
|
||||
#[diag(const_eval_interior_mutability_borrow)]
|
||||
pub(crate) struct InteriorMutabilityBorrow {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
|
|||
|
|
@ -42,10 +42,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let res = self.pointer_from_exposed_address_cast(&src, cast_ty)?;
|
||||
self.write_immediate(res, dest)?;
|
||||
}
|
||||
// FIXME: We shouldn't use `misc_cast` for these but handle them separately.
|
||||
IntToInt | FloatToInt | FloatToFloat | IntToFloat | FnPtrToPtr | PtrToPtr => {
|
||||
|
||||
IntToInt | IntToFloat => {
|
||||
let src = self.read_immediate(src)?;
|
||||
let res = self.misc_cast(&src, cast_ty)?;
|
||||
let res = self.int_to_int_or_float(&src, cast_ty)?;
|
||||
self.write_immediate(res, dest)?;
|
||||
}
|
||||
|
||||
FloatToFloat | FloatToInt => {
|
||||
let src = self.read_immediate(src)?;
|
||||
let res = self.float_to_float_or_int(&src, cast_ty)?;
|
||||
self.write_immediate(res, dest)?;
|
||||
}
|
||||
|
||||
FnPtrToPtr | PtrToPtr => {
|
||||
let src = self.read_immediate(&src)?;
|
||||
let res = self.ptr_to_ptr(&src, cast_ty)?;
|
||||
self.write_immediate(res, dest)?;
|
||||
}
|
||||
|
||||
|
|
@ -126,13 +138,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn misc_cast(
|
||||
pub fn int_to_int_or_float(
|
||||
&mut self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
if (src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool())
|
||||
&& (cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char())
|
||||
{
|
||||
let scalar = src.to_scalar();
|
||||
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
|
||||
} else {
|
||||
bug!("Unexpected cast from type {:?}", src.layout.ty)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float_to_float_or_int(
|
||||
&mut self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
use rustc_type_ir::sty::TyKind::*;
|
||||
trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, cast_ty);
|
||||
|
||||
match src.layout.ty.kind() {
|
||||
// Floating point
|
||||
|
|
@ -142,19 +168,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Float(FloatTy::F64) => {
|
||||
return Ok(self.cast_from_float(src.to_scalar().to_f64()?, cast_ty).into());
|
||||
}
|
||||
// The rest is integer/pointer-"like", including fn ptr casts
|
||||
_ => assert!(
|
||||
src.layout.ty.is_bool()
|
||||
|| src.layout.ty.is_char()
|
||||
|| src.layout.ty.is_integral()
|
||||
|| src.layout.ty.is_any_ptr(),
|
||||
"Unexpected cast from type {:?}",
|
||||
src.layout.ty
|
||||
),
|
||||
_ => {
|
||||
bug!("Can't cast 'Float' type into {:?}", cast_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// # First handle non-scalar source values.
|
||||
|
||||
/// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
|
||||
pub fn ptr_to_ptr(
|
||||
&mut self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
// Handle casting any ptr to raw ptr (might be a fat ptr).
|
||||
if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() {
|
||||
let dest_layout = self.layout_of(cast_ty)?;
|
||||
|
|
@ -178,11 +203,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
bug!("Can't cast 'Ptr' or 'FnPtr' into {:?}", cast_ty);
|
||||
}
|
||||
|
||||
// # The remaining source values are scalar and "int-like".
|
||||
let scalar = src.to_scalar();
|
||||
Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
|
||||
}
|
||||
|
||||
pub fn pointer_expose_address_cast(
|
||||
|
|
|
|||
|
|
@ -556,21 +556,36 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));
|
||||
}
|
||||
Rvalue::Cast(kind, operand, target_type) => {
|
||||
let op_ty = operand.ty(self.body, self.tcx);
|
||||
match kind {
|
||||
CastKind::DynStar => {
|
||||
// FIXME(dyn-star): make sure nothing needs to be done here.
|
||||
}
|
||||
// Nothing to check here
|
||||
// FIXME: Add Checks for these
|
||||
CastKind::PointerFromExposedAddress
|
||||
| CastKind::PointerExposeAddress
|
||||
| CastKind::Pointer(_) => {}
|
||||
_ => {
|
||||
let op_ty = operand.ty(self.body, self.tcx);
|
||||
if op_ty.is_enum() {
|
||||
CastKind::IntToInt | CastKind::IntToFloat => {
|
||||
let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
|
||||
let target_valid = target_type.is_numeric() || target_type.is_char();
|
||||
if !input_valid || !target_valid {
|
||||
self.fail(
|
||||
location,
|
||||
format!("Wrong cast kind {kind:?} for the type {op_ty}",),
|
||||
);
|
||||
}
|
||||
}
|
||||
CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
|
||||
if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) {
|
||||
self.fail(location, "Can't cast {op_ty} into 'Ptr'");
|
||||
}
|
||||
}
|
||||
CastKind::FloatToFloat | CastKind::FloatToInt => {
|
||||
if !op_ty.is_floating_point() || !target_type.is_numeric() {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"enum -> int casts should go through `Rvalue::Discriminant`: {operand:?}:{op_ty} as {target_type}",
|
||||
"Trying to cast non 'Float' as {kind:?} into {target_type:?}"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub struct SsoHashSet<T> {
|
|||
map: SsoHashMap<T, ()>,
|
||||
}
|
||||
|
||||
/// Adapter function used ot return
|
||||
/// Adapter function used to return
|
||||
/// result if SsoHashMap functions into
|
||||
/// result SsoHashSet should return.
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -1,39 +1,39 @@
|
|||
use rustc_macros::Diagnostic;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::rlink_unable_to_read)]
|
||||
#[diag(driver_rlink_unable_to_read)]
|
||||
pub(crate) struct RlinkUnableToRead {
|
||||
pub err: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::rlink_wrong_file_type)]
|
||||
#[diag(driver_rlink_wrong_file_type)]
|
||||
pub(crate) struct RLinkWrongFileType;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::rlink_empty_version_number)]
|
||||
#[diag(driver_rlink_empty_version_number)]
|
||||
pub(crate) struct RLinkEmptyVersionNumber;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::rlink_encoding_version_mismatch)]
|
||||
#[diag(driver_rlink_encoding_version_mismatch)]
|
||||
pub(crate) struct RLinkEncodingVersionMismatch {
|
||||
pub version_array: String,
|
||||
pub rlink_version: u32,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::rlink_rustc_version_mismatch)]
|
||||
#[diag(driver_rlink_rustc_version_mismatch)]
|
||||
pub(crate) struct RLinkRustcVersionMismatch<'a> {
|
||||
pub rustc_version: String,
|
||||
pub current_version: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::rlink_no_a_file)]
|
||||
#[diag(driver_rlink_no_a_file)]
|
||||
pub(crate) struct RlinkNotAFile;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(driver::unpretty_dump_fail)]
|
||||
#[diag(driver_unpretty_dump_fail)]
|
||||
pub(crate) struct UnprettyDumpFail {
|
||||
pub path: String,
|
||||
pub err: String,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,5 @@ Let `Ti` be the first such type.
|
|||
For information on the design of the orphan rules,
|
||||
see [RFC 2451] and [RFC 1023].
|
||||
|
||||
For information on the design of the orphan rules, see [RFC 1023].
|
||||
|
||||
[RFC 2451]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html
|
||||
[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, fo
|
|||
|
||||
codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
|
||||
|
||||
codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
|
||||
|
||||
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
|
||||
|
||||
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
|
||||
|
|
|
|||
|
|
@ -164,7 +164,9 @@ infer_region_explanation = {$pref_kind ->
|
|||
}
|
||||
|
||||
infer_mismatched_static_lifetime = incompatible lifetime on type
|
||||
infer_msl_impl_note = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
|
||||
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
|
||||
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
|
||||
infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
|
||||
infer_msl_introduces_static = introduces a `'static` lifetime requirement
|
||||
infer_msl_unmet_req = because this has an unmet lifetime requirement
|
||||
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
||||
|
|
|
|||
|
|
@ -54,3 +54,7 @@ session_crate_name_empty = crate name must not be empty
|
|||
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
|
||||
|
||||
session_expr_parentheses_needed = parentheses are required to parse this as an expression
|
||||
|
||||
session_skipping_const_checks = skipping const checks
|
||||
session_unleashed_feature_help_named = skipping check for `{$gate}` feature
|
||||
session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
|
||||
|
|
|
|||
|
|
@ -567,6 +567,11 @@ impl Diagnostic {
|
|||
style: SuggestionStyle,
|
||||
) -> &mut Self {
|
||||
assert!(!suggestion.is_empty());
|
||||
debug_assert!(
|
||||
!(suggestion.iter().any(|(sp, text)| sp.is_empty() && text.is_empty())),
|
||||
"Span must not be empty and have no suggestion"
|
||||
);
|
||||
|
||||
self.push_suggestion(CodeSuggestion {
|
||||
substitutions: vec![Substitution {
|
||||
parts: suggestion
|
||||
|
|
@ -644,6 +649,10 @@ impl Diagnostic {
|
|||
applicability: Applicability,
|
||||
style: SuggestionStyle,
|
||||
) -> &mut Self {
|
||||
debug_assert!(
|
||||
!(sp.is_empty() && suggestion.to_string().is_empty()),
|
||||
"Span must not be empty and have no suggestion"
|
||||
);
|
||||
self.push_suggestion(CodeSuggestion {
|
||||
substitutions: vec![Substitution {
|
||||
parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
|
||||
|
|
@ -684,6 +693,12 @@ impl Diagnostic {
|
|||
) -> &mut Self {
|
||||
let mut suggestions: Vec<_> = suggestions.collect();
|
||||
suggestions.sort();
|
||||
|
||||
debug_assert!(
|
||||
!(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())),
|
||||
"Span must not be empty and have no suggestion"
|
||||
);
|
||||
|
||||
let substitutions = suggestions
|
||||
.into_iter()
|
||||
.map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
|
||||
|
|
@ -705,8 +720,18 @@ impl Diagnostic {
|
|||
suggestions: impl Iterator<Item = Vec<(Span, String)>>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self {
|
||||
let suggestions: Vec<_> = suggestions.collect();
|
||||
debug_assert!(
|
||||
!(suggestions
|
||||
.iter()
|
||||
.flat_map(|suggs| suggs)
|
||||
.any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
|
||||
"Span must not be empty and have no suggestion"
|
||||
);
|
||||
|
||||
self.push_suggestion(CodeSuggestion {
|
||||
substitutions: suggestions
|
||||
.into_iter()
|
||||
.map(|sugg| Substitution {
|
||||
parts: sugg
|
||||
.into_iter()
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use crate::{
|
||||
fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
|
||||
};
|
||||
use rustc_target::abi::TargetDataLayoutErrors;
|
||||
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint_defs::Level;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
|
||||
use rustc_target::abi::TargetDataLayoutErrors;
|
||||
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::num::ParseIntError;
|
||||
|
|
@ -155,19 +155,34 @@ impl IntoDiagnosticArg for ast::token::TokenKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for Level {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Borrowed(match self {
|
||||
Level::Allow => "-A",
|
||||
Level::Warn => "-W",
|
||||
Level::ForceWarn(_) => "--force-warn",
|
||||
Level::Deny => "-D",
|
||||
Level::Forbid => "-F",
|
||||
Level::Expect(_) => {
|
||||
unreachable!("lints with the level of `expect` should not run this code");
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
||||
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
||||
let mut diag;
|
||||
match self {
|
||||
TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_invalid_address_space);
|
||||
diag = handler.struct_fatal(fluent::errors_target_invalid_address_space);
|
||||
diag.set_arg("addr_space", addr_space);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err", err);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_invalid_bits);
|
||||
diag = handler.struct_fatal(fluent::errors_target_invalid_bits);
|
||||
diag.set_arg("kind", kind);
|
||||
diag.set_arg("bit", bit);
|
||||
diag.set_arg("cause", cause);
|
||||
|
|
@ -175,30 +190,30 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
|
|||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::MissingAlignment { cause } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_missing_alignment);
|
||||
diag = handler.struct_fatal(fluent::errors_target_missing_alignment);
|
||||
diag.set_arg("cause", cause);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_invalid_alignment);
|
||||
diag = handler.struct_fatal(fluent::errors_target_invalid_alignment);
|
||||
diag.set_arg("cause", cause);
|
||||
diag.set_arg("err", err);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_inconsistent_architecture);
|
||||
diag = handler.struct_fatal(fluent::errors_target_inconsistent_architecture);
|
||||
diag.set_arg("dl", dl);
|
||||
diag.set_arg("target", target);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_inconsistent_pointer_width);
|
||||
diag = handler.struct_fatal(fluent::errors_target_inconsistent_pointer_width);
|
||||
diag.set_arg("pointer_size", pointer_size);
|
||||
diag.set_arg("target", target);
|
||||
diag
|
||||
}
|
||||
TargetDataLayoutErrors::InvalidBitsSize { err } => {
|
||||
diag = handler.struct_fatal(fluent::errors::target_invalid_bits_size);
|
||||
diag = handler.struct_fatal(fluent::errors_target_invalid_bits_size);
|
||||
diag.set_arg("err", err);
|
||||
diag
|
||||
}
|
||||
|
|
|
|||
|
|
@ -463,6 +463,9 @@ pub enum StashKey {
|
|||
UnderscoreForArrayLengths,
|
||||
EarlySyntaxWarning,
|
||||
CallIntoMethod,
|
||||
/// When an invalid lifetime e.g. `'2` should be reinterpreted
|
||||
/// as a char literal in the parser
|
||||
LifetimeIsChar,
|
||||
}
|
||||
|
||||
fn default_track_diagnostic(_: &Diagnostic) {}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use rustc_span::edition::Edition;
|
|||
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{FileName, Span, DUMMY_SP};
|
||||
use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use std::default::Default;
|
||||
|
|
@ -1228,8 +1228,9 @@ pub fn expr_to_spanned_string<'a>(
|
|||
ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
|
||||
ast::LitKind::ByteStr(_) => {
|
||||
let mut err = cx.struct_span_err(l.span, err_msg);
|
||||
let span = expr.span.shrink_to_lo();
|
||||
err.span_suggestion(
|
||||
expr.span.shrink_to_lo(),
|
||||
span.with_hi(span.lo() + BytePos(1)),
|
||||
"consider removing the leading `b`",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
|
|
@ -1422,16 +1423,40 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
|
|||
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
|
||||
if let [variant] = &*enum_def.variants {
|
||||
if variant.ident.name == sym::Input {
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
&PROC_MACRO_BACK_COMPAT,
|
||||
item.ident.span,
|
||||
ast::CRATE_NODE_ID,
|
||||
"using `procedural-masquerade` crate",
|
||||
BuiltinLintDiagnostics::ProcMacroBackCompat(
|
||||
"The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. \
|
||||
Versions of this crate below 0.1.7 will eventually stop compiling.".to_string())
|
||||
);
|
||||
return true;
|
||||
let filename = sess.source_map().span_to_filename(item.ident.span);
|
||||
if let FileName::Real(RealFileName::LocalPath(path)) = filename {
|
||||
if let Some(c) = path
|
||||
.components()
|
||||
.flat_map(|c| c.as_os_str().to_str())
|
||||
.find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
|
||||
{
|
||||
let crate_matches = if c.starts_with("allsorts-rental") {
|
||||
true
|
||||
} else {
|
||||
let mut version = c.trim_start_matches("rental-").split(".");
|
||||
version.next() == Some("0")
|
||||
&& version.next() == Some("5")
|
||||
&& version
|
||||
.next()
|
||||
.and_then(|c| c.parse::<u32>().ok())
|
||||
.map_or(false, |v| v < 6)
|
||||
};
|
||||
|
||||
if crate_matches {
|
||||
sess.buffer_lint_with_diagnostic(
|
||||
&PROC_MACRO_BACK_COMPAT,
|
||||
item.ident.span,
|
||||
ast::CRATE_NODE_ID,
|
||||
"using an old version of `rental`",
|
||||
BuiltinLintDiagnostics::ProcMacroBackCompat(
|
||||
"older versions of the `rental` crate will stop compiling in future versions of Rust; \
|
||||
please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string()
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,28 +3,28 @@ use rustc_span::symbol::MacroRulesNormalizedIdent;
|
|||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand::expr_repeat_no_syntax_vars)]
|
||||
#[diag(expand_expr_repeat_no_syntax_vars)]
|
||||
pub(crate) struct NoSyntaxVarsExprRepeat {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand::must_repeat_once)]
|
||||
#[diag(expand_must_repeat_once)]
|
||||
pub(crate) struct MustRepeatOnce {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand::count_repetition_misplaced)]
|
||||
#[diag(expand_count_repetition_misplaced)]
|
||||
pub(crate) struct CountRepetitionMisplaced {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand::meta_var_expr_unrecognized_var)]
|
||||
#[diag(expand_meta_var_expr_unrecognized_var)]
|
||||
pub(crate) struct MetaVarExprUnrecognizedVar {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -32,7 +32,7 @@ pub(crate) struct MetaVarExprUnrecognizedVar {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand::var_still_repeating)]
|
||||
#[diag(expand_var_still_repeating)]
|
||||
pub(crate) struct VarStillRepeating {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -40,7 +40,7 @@ pub(crate) struct VarStillRepeating {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(expand::meta_var_dif_seq_matchers)]
|
||||
#[diag(expand_meta_var_dif_seq_matchers)]
|
||||
pub(crate) struct MetaVarsDifSeqMatchers {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
|
|||
|
|
@ -598,12 +598,12 @@ pub fn compile_declarative_macro(
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
enum ExplainDocComment {
|
||||
#[label(expand::explain_doc_comment_inner)]
|
||||
#[label(expand_explain_doc_comment_inner)]
|
||||
Inner {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(expand::explain_doc_comment_outer)]
|
||||
#[label(expand_explain_doc_comment_outer)]
|
||||
Outer {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -296,20 +296,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
|
||||
// Lints:
|
||||
ungated!(
|
||||
warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
|
||||
warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
|
||||
DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(
|
||||
allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
|
||||
allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
|
||||
DuplicatesOk, @only_local: true,
|
||||
),
|
||||
gated!(
|
||||
expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk,
|
||||
lint_reasons, experimental!(expect)
|
||||
),
|
||||
ungated!(
|
||||
forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
|
||||
forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
|
||||
DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(
|
||||
deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
|
||||
deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
|
||||
DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing),
|
||||
gated!(
|
||||
|
|
@ -340,7 +344,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
),
|
||||
ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||
ungated!(no_link, Normal, template!(Word), WarnFollowing),
|
||||
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk),
|
||||
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, @only_local: true),
|
||||
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true),
|
||||
|
|
@ -382,7 +386,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true),
|
||||
ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true),
|
||||
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
|
||||
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
|
||||
ungated!(
|
||||
target_feature, Normal, template!(List: r#"enable = "name""#),
|
||||
DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
|
||||
gated!(
|
||||
no_sanitize, Normal,
|
||||
|
|
@ -488,18 +495,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
// Internal attributes: Stability, deprecation, and unsafe:
|
||||
// ==========================================================================
|
||||
|
||||
ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk),
|
||||
ungated!(
|
||||
feature, CrateLevel,
|
||||
template!(List: "name1, name2, ..."), DuplicatesOk, @only_local: true,
|
||||
),
|
||||
// DuplicatesOk since it has its own validation
|
||||
ungated!(
|
||||
stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
|
||||
stable, Normal,
|
||||
template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(
|
||||
unstable, Normal,
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
|
||||
),
|
||||
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
||||
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
|
||||
ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
|
||||
ungated!(
|
||||
rustc_const_stable, Normal,
|
||||
template!(List: r#"feature = "name""#), DuplicatesOk, @only_local: true,
|
||||
),
|
||||
ungated!(
|
||||
rustc_default_body_unstable, Normal,
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk
|
||||
|
|
@ -517,6 +530,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
|
||||
"allow_internal_unsafe side-steps the unsafe_code lint",
|
||||
),
|
||||
ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
|
||||
rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing,
|
||||
"rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
|
||||
through unstable paths"),
|
||||
|
|
@ -732,7 +746,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
for reserving for `for<T> From<!> for T` impl"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_test_marker, Normal, template!(Word), WarnFollowing,
|
||||
rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
|
||||
"the `#[rustc_test_marker]` attribute is used internally to track tests",
|
||||
),
|
||||
rustc_attr!(
|
||||
|
|
@ -823,6 +837,8 @@ pub fn is_builtin_attr_name(name: Symbol) -> bool {
|
|||
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
|
||||
}
|
||||
|
||||
/// Whether this builtin attribute is only used in the local crate.
|
||||
/// If so, it is not encoded in the crate metadata.
|
||||
pub fn is_builtin_only_local(name: Symbol) -> bool {
|
||||
BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
assoc_bindings
|
||||
}
|
||||
|
||||
pub(crate) fn create_substs_for_associated_item(
|
||||
pub fn create_substs_for_associated_item(
|
||||
&self,
|
||||
span: Span,
|
||||
item_def_id: DefId,
|
||||
|
|
@ -3051,24 +3051,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
.map_or(false, |s| s.trim_end().ends_with('<'));
|
||||
|
||||
let is_global = poly_trait_ref.trait_ref.path.is_global();
|
||||
let sugg = Vec::from_iter([
|
||||
(
|
||||
self_ty.span.shrink_to_lo(),
|
||||
format!(
|
||||
"{}dyn {}",
|
||||
if needs_bracket { "<" } else { "" },
|
||||
if is_global { "(" } else { "" },
|
||||
),
|
||||
|
||||
let mut sugg = Vec::from_iter([(
|
||||
self_ty.span.shrink_to_lo(),
|
||||
format!(
|
||||
"{}dyn {}",
|
||||
if needs_bracket { "<" } else { "" },
|
||||
if is_global { "(" } else { "" },
|
||||
),
|
||||
(
|
||||
)]);
|
||||
|
||||
if is_global || needs_bracket {
|
||||
sugg.push((
|
||||
self_ty.span.shrink_to_hi(),
|
||||
format!(
|
||||
"{}{}",
|
||||
if is_global { ")" } else { "" },
|
||||
if needs_bracket { ">" } else { "" },
|
||||
),
|
||||
),
|
||||
]);
|
||||
));
|
||||
}
|
||||
|
||||
if self_ty.span.edition() >= Edition::Edition2021 {
|
||||
let msg = "trait objects must include the `dyn` keyword";
|
||||
let label = "add `dyn` keyword before this trait";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use crate::check::intrinsicck::InlineAsmCtxt;
|
||||
|
||||
use super::coercion::CoerceMany;
|
||||
use super::compare_method::check_type_bounds;
|
||||
use super::compare_method::{compare_impl_method, compare_ty_impl};
|
||||
use super::*;
|
||||
|
|
@ -10,10 +9,8 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ItemKind, Node, PathSegment};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
|
||||
|
|
@ -34,7 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
|
||||
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
|
||||
match tcx.sess.target.is_abi_supported(abi) {
|
||||
Some(true) => (),
|
||||
Some(false) => {
|
||||
|
|
@ -69,313 +66,6 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper used for fns and closures. Does the grungy work of checking a function
|
||||
/// body and returns the function context used for that purpose, since in the case of a fn item
|
||||
/// there is still a bit more to do.
|
||||
///
|
||||
/// * ...
|
||||
/// * inherited: other fields inherited from the enclosing fn (if any)
|
||||
#[instrument(skip(inherited, body), level = "debug")]
|
||||
pub(super) fn check_fn<'a, 'tcx>(
|
||||
inherited: &'a Inherited<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
fn_sig: ty::FnSig<'tcx>,
|
||||
decl: &'tcx hir::FnDecl<'tcx>,
|
||||
fn_id: hir::HirId,
|
||||
body: &'tcx hir::Body<'tcx>,
|
||||
can_be_generator: Option<hir::Movability>,
|
||||
return_type_pre_known: bool,
|
||||
) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
|
||||
// Create the function context. This is either derived from scratch or,
|
||||
// in the case of closures, based on the outer context.
|
||||
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
|
||||
fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
|
||||
fcx.return_type_pre_known = return_type_pre_known;
|
||||
|
||||
let tcx = fcx.tcx;
|
||||
let hir = tcx.hir();
|
||||
|
||||
let declared_ret_ty = fn_sig.output();
|
||||
|
||||
let ret_ty =
|
||||
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
|
||||
declared_ret_ty,
|
||||
body.value.hir_id,
|
||||
decl.output.span(),
|
||||
param_env,
|
||||
));
|
||||
// If we replaced declared_ret_ty with infer vars, then we must be inferring
|
||||
// an opaque type, so set a flag so we can improve diagnostics.
|
||||
fcx.return_type_has_opaque = ret_ty != declared_ret_ty;
|
||||
|
||||
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
|
||||
|
||||
let span = body.value.span;
|
||||
|
||||
fn_maybe_err(tcx, span, fn_sig.abi);
|
||||
|
||||
if fn_sig.abi == Abi::RustCall {
|
||||
let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
|
||||
|
||||
let err = || {
|
||||
let item = match tcx.hir().get(fn_id) {
|
||||
Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
|
||||
Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(header, ..), ..
|
||||
}) => Some(header),
|
||||
Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(header, ..),
|
||||
..
|
||||
}) => Some(header),
|
||||
// Closures are RustCall, but they tuple their arguments, so shouldn't be checked
|
||||
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
|
||||
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
|
||||
};
|
||||
|
||||
if let Some(header) = item {
|
||||
tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
|
||||
}
|
||||
};
|
||||
|
||||
if fn_sig.inputs().len() != expected_args {
|
||||
err()
|
||||
} else {
|
||||
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
|
||||
// This will probably require wide-scale changes to support a TupleKind obligation
|
||||
// We can't resolve this without knowing the type of the param
|
||||
if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
|
||||
err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if body.generator_kind.is_some() && can_be_generator.is_some() {
|
||||
let yield_ty = fcx
|
||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
|
||||
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
|
||||
|
||||
// Resume type defaults to `()` if the generator has no argument.
|
||||
let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit());
|
||||
|
||||
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
|
||||
}
|
||||
|
||||
GatherLocalsVisitor::new(&fcx).visit_body(body);
|
||||
|
||||
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
|
||||
// (as it's created inside the body itself, not passed in from outside).
|
||||
let maybe_va_list = if fn_sig.c_variadic {
|
||||
let span = body.params.last().unwrap().span;
|
||||
let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
|
||||
let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
|
||||
|
||||
Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()]))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Add formal parameters.
|
||||
let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
|
||||
let inputs_fn = fn_sig.inputs().iter().copied();
|
||||
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
|
||||
// Check the pattern.
|
||||
let ty_span = try { inputs_hir?.get(idx)?.span };
|
||||
fcx.check_pat_top(¶m.pat, param_ty, ty_span, false);
|
||||
|
||||
// Check that argument is Sized.
|
||||
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
|
||||
// for simple cases like `fn foo(x: Trait)`,
|
||||
// where we would error once on the parameter as a whole, and once on the binding `x`.
|
||||
if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
|
||||
fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
|
||||
}
|
||||
|
||||
fcx.write_ty(param.hir_id, param_ty);
|
||||
}
|
||||
|
||||
inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
|
||||
|
||||
fcx.in_tail_expr = true;
|
||||
if let ty::Dynamic(..) = declared_ret_ty.kind() {
|
||||
// FIXME: We need to verify that the return type is `Sized` after the return expression has
|
||||
// been evaluated so that we have types available for all the nodes being returned, but that
|
||||
// requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
|
||||
// causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
|
||||
// while keeping the current ordering we will ignore the tail expression's type because we
|
||||
// don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
|
||||
// because we will trigger "unreachable expression" lints unconditionally.
|
||||
// Because of all of this, we perform a crude check to know whether the simplest `!Sized`
|
||||
// case that a newcomer might make, returning a bare trait, and in that case we populate
|
||||
// the tail expression's type so that the suggestion will be correct, but ignore all other
|
||||
// possible cases.
|
||||
fcx.check_expr(&body.value);
|
||||
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
|
||||
} else {
|
||||
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
|
||||
fcx.check_return_expr(&body.value, false);
|
||||
}
|
||||
fcx.in_tail_expr = false;
|
||||
|
||||
// We insert the deferred_generator_interiors entry after visiting the body.
|
||||
// This ensures that all nested generators appear before the entry of this generator.
|
||||
// resolve_generator_interiors relies on this property.
|
||||
let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) {
|
||||
let interior = fcx
|
||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
|
||||
fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind));
|
||||
|
||||
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
|
||||
Some(GeneratorTypes {
|
||||
resume_ty,
|
||||
yield_ty,
|
||||
interior,
|
||||
movability: can_be_generator.unwrap(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Finalize the return check by taking the LUB of the return types
|
||||
// we saw and assigning it to the expected return type. This isn't
|
||||
// really expected to fail, since the coercions would have failed
|
||||
// earlier when trying to find a LUB.
|
||||
let coercion = fcx.ret_coercion.take().unwrap().into_inner();
|
||||
let mut actual_return_ty = coercion.complete(&fcx);
|
||||
debug!("actual_return_ty = {:?}", actual_return_ty);
|
||||
if let ty::Dynamic(..) = declared_ret_ty.kind() {
|
||||
// We have special-cased the case where the function is declared
|
||||
// `-> dyn Foo` and we don't actually relate it to the
|
||||
// `fcx.ret_coercion`, so just substitute a type variable.
|
||||
actual_return_ty =
|
||||
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
|
||||
debug!("actual_return_ty replaced with {:?}", actual_return_ty);
|
||||
}
|
||||
|
||||
// HACK(oli-obk, compiler-errors): We should be comparing this against
|
||||
// `declared_ret_ty`, but then anything uninferred would be inferred to
|
||||
// the opaque type itself. That again would cause writeback to assume
|
||||
// we have a recursive call site and do the sadly stabilized fallback to `()`.
|
||||
fcx.demand_suptype(span, ret_ty, actual_return_ty);
|
||||
|
||||
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
|
||||
if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
|
||||
&& panic_impl_did == hir.local_def_id(fn_id).to_def_id()
|
||||
{
|
||||
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
|
||||
}
|
||||
|
||||
// Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
|
||||
if let Some(alloc_error_handler_did) = tcx.lang_items().oom()
|
||||
&& alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id()
|
||||
{
|
||||
check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty);
|
||||
}
|
||||
|
||||
(fcx, gen_ty)
|
||||
}
|
||||
|
||||
fn check_panic_info_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
fn_id: LocalDefId,
|
||||
fn_sig: ty::FnSig<'_>,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
declared_ret_ty: Ty<'_>,
|
||||
) {
|
||||
let Some(panic_info_did) = tcx.lang_items().panic_info() else {
|
||||
tcx.sess.err("language item required, but not found: `panic_info`");
|
||||
return;
|
||||
};
|
||||
|
||||
if *declared_ret_ty.kind() != ty::Never {
|
||||
tcx.sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
}
|
||||
|
||||
let inputs = fn_sig.inputs();
|
||||
if inputs.len() != 1 {
|
||||
tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
|
||||
return;
|
||||
}
|
||||
|
||||
let arg_is_panic_info = match *inputs[0].kind() {
|
||||
ty::Ref(region, ty, mutbl) => match *ty.kind() {
|
||||
ty::Adt(ref adt, _) => {
|
||||
adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static()
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !arg_is_panic_info {
|
||||
tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
|
||||
}
|
||||
|
||||
let DefKind::Fn = tcx.def_kind(fn_id) else {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "should be a function");
|
||||
return;
|
||||
};
|
||||
|
||||
let generic_counts = tcx.generics_of(fn_id).own_counts();
|
||||
if generic_counts.types != 0 {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "should have no type parameters");
|
||||
}
|
||||
if generic_counts.consts != 0 {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "should have no const parameters");
|
||||
}
|
||||
}
|
||||
|
||||
fn check_alloc_error_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
fn_id: LocalDefId,
|
||||
fn_sig: ty::FnSig<'_>,
|
||||
decl: &hir::FnDecl<'_>,
|
||||
declared_ret_ty: Ty<'_>,
|
||||
) {
|
||||
let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else {
|
||||
tcx.sess.err("language item required, but not found: `alloc_layout`");
|
||||
return;
|
||||
};
|
||||
|
||||
if *declared_ret_ty.kind() != ty::Never {
|
||||
tcx.sess.span_err(decl.output.span(), "return type should be `!`");
|
||||
}
|
||||
|
||||
let inputs = fn_sig.inputs();
|
||||
if inputs.len() != 1 {
|
||||
tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
|
||||
return;
|
||||
}
|
||||
|
||||
let arg_is_alloc_layout = match inputs[0].kind() {
|
||||
ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !arg_is_alloc_layout {
|
||||
tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
|
||||
}
|
||||
|
||||
let DefKind::Fn = tcx.def_kind(fn_id) else {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function");
|
||||
return;
|
||||
};
|
||||
|
||||
let generic_counts = tcx.generics_of(fn_id).own_counts();
|
||||
if generic_counts.types != 0 {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters");
|
||||
}
|
||||
if generic_counts.consts != 0 {
|
||||
let span = tcx.def_span(fn_id);
|
||||
tcx.sess
|
||||
.span_err(span, "`#[alloc_error_handler]` function should have no const parameters");
|
||||
}
|
||||
}
|
||||
|
||||
fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let def = tcx.adt_def(def_id);
|
||||
let span = tcx.def_span(def_id);
|
||||
|
|
|
|||
|
|
@ -598,8 +598,16 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
|
|||
let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
|
||||
let ty = tcx.fold_regions(ty, |region, _| {
|
||||
let ty::ReFree(_) = region.kind() else { return region; };
|
||||
let ty::ReEarlyBound(e) = map[®ion.into()].expect_region().kind()
|
||||
else { bug!("expected ReFree to map to ReEarlyBound"); };
|
||||
let Some(ty::ReEarlyBound(e)) = map.get(®ion.into()).map(|r| r.expect_region().kind())
|
||||
else {
|
||||
tcx
|
||||
.sess
|
||||
.delay_span_bug(
|
||||
return_span,
|
||||
"expected ReFree to map to ReEarlyBound"
|
||||
);
|
||||
return tcx.lifetimes.re_static;
|
||||
};
|
||||
tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
|
||||
def_id: e.def_id,
|
||||
name: e.name,
|
||||
|
|
@ -664,10 +672,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
|
|||
});
|
||||
self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
|
||||
// Recurse into bounds
|
||||
for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
|
||||
let pred_span = pred.0.1;
|
||||
|
||||
let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
|
||||
for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
|
||||
let pred = pred.fold_with(self);
|
||||
let pred = self.ocx.normalize(
|
||||
ObligationCause::misc(self.span, self.body_id),
|
||||
|
|
@ -1752,15 +1757,10 @@ pub fn check_type_bounds<'tcx>(
|
|||
|
||||
let obligations = tcx
|
||||
.bound_explicit_item_bounds(trait_ty.def_id)
|
||||
.transpose_iter()
|
||||
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
|
||||
.map(|(bound, span)| {
|
||||
debug!(?bound);
|
||||
// this is where opaque type is found
|
||||
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
|
||||
.subst_iter_copied(tcx, rebased_substs)
|
||||
.map(|(concrete_ty_bound, span)| {
|
||||
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
|
||||
|
||||
traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
|
||||
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
|
||||
})
|
||||
.collect();
|
||||
debug!("check_type_bounds: item_bounds={:?}", obligations);
|
||||
|
|
|
|||
|
|
@ -184,13 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
let p = p.kind();
|
||||
match (predicate.skip_binder(), p.skip_binder()) {
|
||||
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
|
||||
// Since struct predicates cannot have ~const, project the impl predicate
|
||||
// onto one that ignores the constness. This is equivalent to saying that
|
||||
// we match a `Trait` bound on the struct with a `Trait` or `~const Trait`
|
||||
// in the impl.
|
||||
let non_const_a =
|
||||
ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a };
|
||||
relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok()
|
||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||
}
|
||||
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
|
||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||
|
|
@ -198,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
(
|
||||
ty::PredicateKind::ConstEvaluatable(a),
|
||||
ty::PredicateKind::ConstEvaluatable(b),
|
||||
) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))),
|
||||
) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
|
||||
(
|
||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
||||
|
|
|
|||
|
|
@ -1,117 +1,11 @@
|
|||
use hir::HirId;
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
|
||||
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::{Symbol, DUMMY_SP};
|
||||
use rustc_target::abi::{Pointer, VariantIdx};
|
||||
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
|
||||
|
||||
use super::FnCtxt;
|
||||
|
||||
/// If the type is `Option<T>`, it will return `T`, otherwise
|
||||
/// the type itself. Works on most `Option`-like types.
|
||||
fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty::Adt(def, substs) = *ty.kind() else { return ty };
|
||||
|
||||
if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() {
|
||||
let data_idx;
|
||||
|
||||
let one = VariantIdx::new(1);
|
||||
let zero = VariantIdx::new(0);
|
||||
|
||||
if def.variant(zero).fields.is_empty() {
|
||||
data_idx = one;
|
||||
} else if def.variant(one).fields.is_empty() {
|
||||
data_idx = zero;
|
||||
} else {
|
||||
return ty;
|
||||
}
|
||||
|
||||
if def.variant(data_idx).fields.len() == 1 {
|
||||
return def.variant(data_idx).fields[0].ty(tcx, substs);
|
||||
}
|
||||
}
|
||||
|
||||
ty
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
|
||||
let tcx = self.tcx;
|
||||
let span = tcx.hir().span(hir_id);
|
||||
let normalize = |ty| {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
self.tcx.normalize_erasing_regions(self.param_env, ty)
|
||||
};
|
||||
let from = normalize(from);
|
||||
let to = normalize(to);
|
||||
trace!(?from, ?to);
|
||||
|
||||
// Transmutes that are only changing lifetimes are always ok.
|
||||
if from == to {
|
||||
return;
|
||||
}
|
||||
|
||||
let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env);
|
||||
let sk_from = skel(from);
|
||||
let sk_to = skel(to);
|
||||
trace!(?sk_from, ?sk_to);
|
||||
|
||||
// Check for same size using the skeletons.
|
||||
if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
|
||||
if sk_from.same_size(sk_to) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special-case transmuting from `typeof(function)` and
|
||||
// `Option<typeof(function)>` to present a clearer error.
|
||||
let from = unpack_option_like(tcx, from);
|
||||
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&tcx) {
|
||||
struct_span_err!(tcx.sess, span, E0591, "can't transmute zero-sized type")
|
||||
.note(&format!("source type: {from}"))
|
||||
.note(&format!("target type: {to}"))
|
||||
.help("cast with `as` to a pointer instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to display a sensible error with as much information as possible.
|
||||
let skeleton_string = |ty: Ty<'tcx>, sk| match sk {
|
||||
Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()),
|
||||
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
|
||||
Err(LayoutError::Unknown(bad)) => {
|
||||
if bad == ty {
|
||||
"this type does not have a fixed size".to_owned()
|
||||
} else {
|
||||
format!("size can vary because of {bad}")
|
||||
}
|
||||
}
|
||||
Err(err) => err.to_string(),
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0512,
|
||||
"cannot transmute between types of different sizes, \
|
||||
or dependently-sized types"
|
||||
);
|
||||
if from == to {
|
||||
err.note(&format!("`{from}` does not have a fixed size"));
|
||||
} else {
|
||||
err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
|
||||
.note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InlineAsmCtxt<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
|
|||
|
|
@ -62,191 +62,45 @@ a type parameter).
|
|||
|
||||
*/
|
||||
|
||||
pub mod _match;
|
||||
mod autoderef;
|
||||
mod callee;
|
||||
pub mod cast;
|
||||
mod check;
|
||||
mod closure;
|
||||
pub mod coercion;
|
||||
mod compare_method;
|
||||
pub mod demand;
|
||||
mod diverges;
|
||||
pub mod dropck;
|
||||
mod expectation;
|
||||
mod expr;
|
||||
mod fallback;
|
||||
mod fn_ctxt;
|
||||
mod gather_locals;
|
||||
mod generator_interior;
|
||||
mod inherited;
|
||||
pub mod intrinsic;
|
||||
mod intrinsicck;
|
||||
pub mod method;
|
||||
mod op;
|
||||
mod pat;
|
||||
mod place_op;
|
||||
pub mod intrinsicck;
|
||||
mod region;
|
||||
pub mod rvalue_scopes;
|
||||
mod upvar;
|
||||
pub mod wfcheck;
|
||||
pub mod writeback;
|
||||
|
||||
use check::{check_abi, check_fn, check_mod_item_types};
|
||||
pub use diverges::Diverges;
|
||||
pub use expectation::Expectation;
|
||||
pub use fn_ctxt::*;
|
||||
pub use inherited::{Inherited, InheritedBuilder};
|
||||
pub use check::check_abi;
|
||||
|
||||
use crate::astconv::AstConv;
|
||||
use crate::check::gather_locals::GatherLocalsVisitor;
|
||||
use check::check_mod_item_types;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{
|
||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
|
||||
};
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||
use rustc_session::config;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::{self, BytePos, Span, Symbol};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
|
||||
use std::cell::RefCell;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::require_c_abi_if_c_variadic;
|
||||
use crate::util::common::indenter;
|
||||
|
||||
use self::coercion::DynamicCoerceMany;
|
||||
use self::compare_method::collect_trait_impl_trait_tys;
|
||||
use self::region::region_scope_tree;
|
||||
pub use self::Expectation::*;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! type_error_struct {
|
||||
($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
|
||||
let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
|
||||
|
||||
if $typ.references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
||||
err
|
||||
})
|
||||
}
|
||||
|
||||
/// The type of a local binding, including the revealed type for anon types.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct LocalTy<'tcx> {
|
||||
decl_ty: Ty<'tcx>,
|
||||
revealed_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Needs {
|
||||
MutPlace,
|
||||
None,
|
||||
}
|
||||
|
||||
impl Needs {
|
||||
fn maybe_mut_place(m: hir::Mutability) -> Self {
|
||||
match m {
|
||||
hir::Mutability::Mut => Needs::MutPlace,
|
||||
hir::Mutability::Not => Needs::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct UnsafetyState {
|
||||
pub def: hir::HirId,
|
||||
pub unsafety: hir::Unsafety,
|
||||
from_fn: bool,
|
||||
}
|
||||
|
||||
impl UnsafetyState {
|
||||
pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
|
||||
UnsafetyState { def, unsafety, from_fn: true }
|
||||
}
|
||||
|
||||
pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
|
||||
use hir::BlockCheckMode;
|
||||
match self.unsafety {
|
||||
// If this unsafe, then if the outer function was already marked as
|
||||
// unsafe we shouldn't attribute the unsafe'ness to the block. This
|
||||
// way the block can be warned about instead of ignoring this
|
||||
// extraneous block (functions are never warned about).
|
||||
hir::Unsafety::Unsafe if self.from_fn => self,
|
||||
|
||||
unsafety => {
|
||||
let (unsafety, def) = match blk.rules {
|
||||
BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
|
||||
BlockCheckMode::DefaultBlock => (unsafety, self.def),
|
||||
};
|
||||
UnsafetyState { def, unsafety, from_fn: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum PlaceOp {
|
||||
Deref,
|
||||
Index,
|
||||
}
|
||||
|
||||
pub struct BreakableCtxt<'tcx> {
|
||||
may_break: bool,
|
||||
|
||||
// this is `null` for loops where break with a value is illegal,
|
||||
// such as `while`, `for`, and `while let`
|
||||
coerce: Option<DynamicCoerceMany<'tcx>>,
|
||||
}
|
||||
|
||||
pub struct EnclosingBreakables<'tcx> {
|
||||
stack: Vec<BreakableCtxt<'tcx>>,
|
||||
by_id: HirIdMap<usize>,
|
||||
}
|
||||
|
||||
impl<'tcx> EnclosingBreakables<'tcx> {
|
||||
fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
|
||||
self.opt_find_breakable(target_id).unwrap_or_else(|| {
|
||||
bug!("could not find enclosing breakable with id {}", target_id);
|
||||
})
|
||||
}
|
||||
|
||||
fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
|
||||
match self.by_id.get(&target_id) {
|
||||
Some(ix) => Some(&mut self.stack[*ix]),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
method::provide(providers);
|
||||
wfcheck::provide(providers);
|
||||
*providers = Providers {
|
||||
typeck_item_bodies,
|
||||
typeck_const_arg,
|
||||
typeck,
|
||||
diagnostic_only_typeck,
|
||||
has_typeck_results,
|
||||
adt_destructor,
|
||||
used_trait_imports,
|
||||
check_mod_item_types,
|
||||
region_scope_tree,
|
||||
collect_trait_impl_trait_tys,
|
||||
|
|
@ -259,259 +113,6 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
|
|||
tcx.calculate_dtor(def_id, dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
/// If this `DefId` is a "primary tables entry", returns
|
||||
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
|
||||
///
|
||||
/// If this function returns `Some`, then `typeck_results(def_id)` will
|
||||
/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
|
||||
/// may not succeed. In some cases where this function returns `None`
|
||||
/// (notably closures), `typeck_results(def_id)` would wind up
|
||||
/// redirecting to the owning function.
|
||||
fn primary_body_of(
|
||||
tcx: TyCtxt<'_>,
|
||||
id: hir::HirId,
|
||||
) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
|
||||
match tcx.hir().get(id) {
|
||||
Node::Item(item) => match item.kind {
|
||||
hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
|
||||
Some((body, Some(ty), None))
|
||||
}
|
||||
hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
|
||||
_ => None,
|
||||
},
|
||||
Node::TraitItem(item) => match item.kind {
|
||||
hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
|
||||
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
|
||||
Some((body, None, Some(sig)))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
Node::ImplItem(item) => match item.kind {
|
||||
hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
|
||||
hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
|
||||
_ => None,
|
||||
},
|
||||
Node::AnonConst(constant) => Some((constant.body, None, None)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
// Closures' typeck results come from their outermost function,
|
||||
// as they are part of the same "inference environment".
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
|
||||
if typeck_root_def_id != def_id {
|
||||
return tcx.has_typeck_results(typeck_root_def_id);
|
||||
}
|
||||
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
let id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
primary_body_of(tcx, id).is_some()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
|
||||
&*tcx.typeck(def_id).used_trait_imports
|
||||
}
|
||||
|
||||
fn typeck_const_arg<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
(did, param_did): (LocalDefId, DefId),
|
||||
) -> &ty::TypeckResults<'tcx> {
|
||||
let fallback = move || tcx.type_of(param_did);
|
||||
typeck_with_fallback(tcx, did, fallback)
|
||||
}
|
||||
|
||||
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
|
||||
if let Some(param_did) = tcx.opt_const_param_of(def_id) {
|
||||
tcx.typeck_const_arg((def_id, param_did))
|
||||
} else {
|
||||
let fallback = move || tcx.type_of(def_id.to_def_id());
|
||||
typeck_with_fallback(tcx, def_id, fallback)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used only to get `TypeckResults` for type inference during error recovery.
|
||||
/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
|
||||
fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
|
||||
let fallback = move || {
|
||||
let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
|
||||
tcx.ty_error_with_message(span, "diagnostic only typeck table used")
|
||||
};
|
||||
typeck_with_fallback(tcx, def_id, fallback)
|
||||
}
|
||||
|
||||
fn typeck_with_fallback<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
fallback: impl Fn() -> Ty<'tcx> + 'tcx,
|
||||
) -> &'tcx ty::TypeckResults<'tcx> {
|
||||
// Closures' typeck results come from their outermost function,
|
||||
// as they are part of the same "inference environment".
|
||||
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
|
||||
if typeck_root_def_id != def_id {
|
||||
return tcx.typeck(typeck_root_def_id);
|
||||
}
|
||||
|
||||
let id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let span = tcx.hir().span(id);
|
||||
|
||||
// Figure out what primary body this item has.
|
||||
let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
|
||||
span_bug!(span, "can't type-check body of {:?}", def_id);
|
||||
});
|
||||
let body = tcx.hir().body(body_id);
|
||||
|
||||
let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
|
||||
let param_env = tcx.param_env(def_id);
|
||||
let mut fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
|
||||
let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
|
||||
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
|
||||
<dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
|
||||
} else {
|
||||
tcx.fn_sig(def_id)
|
||||
};
|
||||
|
||||
check_abi(tcx, id, span, fn_sig.abi());
|
||||
|
||||
// Compute the function signature from point of view of inside the fn.
|
||||
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
|
||||
let fn_sig = inh.normalize_associated_types_in(
|
||||
body.value.span,
|
||||
body_id.hir_id,
|
||||
param_env,
|
||||
fn_sig,
|
||||
);
|
||||
check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
|
||||
} else {
|
||||
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
|
||||
let expected_type = body_ty
|
||||
.and_then(|ty| match ty.kind {
|
||||
hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| match tcx.hir().get(id) {
|
||||
Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
|
||||
Node::Expr(&hir::Expr {
|
||||
kind: hir::ExprKind::ConstBlock(ref anon_const),
|
||||
..
|
||||
}) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span,
|
||||
}),
|
||||
Node::Ty(&hir::Ty {
|
||||
kind: hir::TyKind::Typeof(ref anon_const), ..
|
||||
}) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span,
|
||||
}),
|
||||
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
|
||||
let operand_ty = asm
|
||||
.operands
|
||||
.iter()
|
||||
.filter_map(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const }
|
||||
if anon_const.hir_id == id =>
|
||||
{
|
||||
// Inline assembly constants must be integers.
|
||||
Some(fcx.next_int_var())
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { anon_const }
|
||||
if anon_const.hir_id == id =>
|
||||
{
|
||||
Some(fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span,
|
||||
}))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.next();
|
||||
operand_ty.unwrap_or_else(fallback)
|
||||
}
|
||||
_ => fallback(),
|
||||
},
|
||||
_ => fallback(),
|
||||
});
|
||||
|
||||
let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
|
||||
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
|
||||
|
||||
// Gather locals in statics (because of block expressions).
|
||||
GatherLocalsVisitor::new(&fcx).visit_body(body);
|
||||
|
||||
fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
|
||||
|
||||
fcx.write_ty(id, expected_type);
|
||||
|
||||
fcx
|
||||
};
|
||||
|
||||
let fallback_has_occurred = fcx.type_inference_fallback();
|
||||
|
||||
// Even though coercion casts provide type hints, we check casts after fallback for
|
||||
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
|
||||
fcx.check_casts();
|
||||
fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
|
||||
|
||||
// Closure and generator analysis may run after fallback
|
||||
// because they don't constrain other type variables.
|
||||
// Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
|
||||
let prev_constness = fcx.param_env.constness();
|
||||
fcx.param_env = fcx.param_env.without_const();
|
||||
fcx.closure_analyze(body);
|
||||
fcx.param_env = fcx.param_env.with_constness(prev_constness);
|
||||
assert!(fcx.deferred_call_resolutions.borrow().is_empty());
|
||||
// Before the generator analysis, temporary scopes shall be marked to provide more
|
||||
// precise information on types to be captured.
|
||||
fcx.resolve_rvalue_scopes(def_id.to_def_id());
|
||||
fcx.resolve_generator_interiors(def_id.to_def_id());
|
||||
|
||||
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
|
||||
let ty = fcx.normalize_ty(span, ty);
|
||||
fcx.require_type_is_sized(ty, span, code);
|
||||
}
|
||||
|
||||
fcx.select_all_obligations_or_error();
|
||||
|
||||
if !fcx.infcx.is_tainted_by_errors() {
|
||||
fcx.check_transmutes();
|
||||
}
|
||||
|
||||
fcx.check_asms();
|
||||
|
||||
fcx.infcx.skip_region_resolution();
|
||||
|
||||
fcx.resolve_type_vars_in_body(body)
|
||||
});
|
||||
|
||||
// Consistency check our TypeckResults instance can hold all ItemLocalIds
|
||||
// it will need to hold.
|
||||
assert_eq!(typeck_results.hir_owner, id.owner);
|
||||
|
||||
typeck_results
|
||||
}
|
||||
|
||||
/// When `check_fn` is invoked on a generator (i.e., a body that
|
||||
/// includes yield), it returns back some information about the yield
|
||||
/// points.
|
||||
struct GeneratorTypes<'tcx> {
|
||||
/// Type of generator argument / values returned by `yield`.
|
||||
resume_ty: Ty<'tcx>,
|
||||
|
||||
/// Type of value that is yielded.
|
||||
yield_ty: Ty<'tcx>,
|
||||
|
||||
/// Types that are captured (see `GeneratorInterior` for more).
|
||||
interior: Ty<'tcx>,
|
||||
|
||||
/// Indicates if the generator is movable or static (immovable).
|
||||
movability: hir::Movability,
|
||||
}
|
||||
|
||||
/// Given a `DefId` for an opaque type in return position, find its parent item's return
|
||||
/// expressions.
|
||||
fn get_owner_return_paths<'tcx>(
|
||||
|
|
@ -528,9 +129,10 @@ fn get_owner_return_paths<'tcx>(
|
|||
})
|
||||
}
|
||||
|
||||
// Forbid defining intrinsics in Rust code,
|
||||
// as they must always be defined by the compiler.
|
||||
fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
|
||||
/// Forbid defining intrinsics in Rust code,
|
||||
/// as they must always be defined by the compiler.
|
||||
// FIXME: Move this to a more appropriate place.
|
||||
pub fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
|
||||
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
|
||||
tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
|
||||
}
|
||||
|
|
@ -824,6 +426,17 @@ fn fn_sig_suggestion<'tcx>(
|
|||
format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
|
||||
}
|
||||
|
||||
pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
|
||||
Some(match ty.kind() {
|
||||
ty::Bool => "true",
|
||||
ty::Char => "'a'",
|
||||
ty::Int(_) | ty::Uint(_) => "42",
|
||||
ty::Float(_) => "3.14159",
|
||||
ty::Error(_) | ty::Never => return None,
|
||||
_ => "value",
|
||||
})
|
||||
}
|
||||
|
||||
/// Return placeholder code for the given associated item.
|
||||
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
|
||||
/// structured suggestion.
|
||||
|
|
@ -845,7 +458,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
|
|||
ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
|
||||
ty::AssocKind::Const => {
|
||||
let ty = tcx.type_of(assoc.def_id);
|
||||
let val = expr::ty_kind_suggestion(ty).unwrap_or("value");
|
||||
let val = ty_kind_suggestion(ty).unwrap_or("value");
|
||||
format!("const {}: {} = {};", assoc.name, ty, val)
|
||||
}
|
||||
}
|
||||
|
|
@ -896,76 +509,7 @@ fn bad_non_zero_sized_fields<'tcx>(
|
|||
err.emit();
|
||||
}
|
||||
|
||||
fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0533,
|
||||
"expected unit struct, unit variant or constant, found {} `{}`",
|
||||
res.descr(),
|
||||
rustc_hir_pretty::qpath_to_string(qpath),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Controls whether the arguments are tupled. This is used for the call
|
||||
/// operator.
|
||||
///
|
||||
/// Tupling means that all call-side arguments are packed into a tuple and
|
||||
/// passed as a single parameter. For example, if tupling is enabled, this
|
||||
/// function:
|
||||
/// ```
|
||||
/// fn f(x: (isize, isize)) {}
|
||||
/// ```
|
||||
/// Can be called as:
|
||||
/// ```ignore UNSOLVED (can this be done in user code?)
|
||||
/// # fn f(x: (isize, isize)) {}
|
||||
/// f(1, 2);
|
||||
/// ```
|
||||
/// Instead of:
|
||||
/// ```
|
||||
/// # fn f(x: (isize, isize)) {}
|
||||
/// f((1, 2));
|
||||
/// ```
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
enum TupleArgumentsFlag {
|
||||
DontTupleArguments,
|
||||
TupleArguments,
|
||||
}
|
||||
|
||||
fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
|
||||
tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
|
||||
}
|
||||
|
||||
fn fatally_break_rust(sess: &Session) {
|
||||
let handler = sess.diagnostic();
|
||||
handler.span_bug_no_panic(
|
||||
MultiSpan::new(),
|
||||
"It looks like you're trying to break rust; would you like some ICE?",
|
||||
);
|
||||
handler.note_without_error("the compiler expectedly panicked. this is a feature.");
|
||||
handler.note_without_error(
|
||||
"we would appreciate a joke overview: \
|
||||
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
|
||||
);
|
||||
handler.note_without_error(&format!(
|
||||
"rustc {} running on {}",
|
||||
option_env!("CFG_VERSION").unwrap_or("unknown_version"),
|
||||
config::host_triple(),
|
||||
));
|
||||
}
|
||||
|
||||
fn potentially_plural_count(count: usize, word: &str) -> String {
|
||||
// FIXME: Consider moving this method to a more fitting place.
|
||||
pub fn potentially_plural_count(count: usize, word: &str) -> String {
|
||||
format!("{} {}{}", count, word, pluralize!(count))
|
||||
}
|
||||
|
||||
fn has_expected_num_generic_args<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_did: Option<DefId>,
|
||||
expected: usize,
|
||||
) -> bool {
|
||||
trait_did.map_or(true, |trait_did| {
|
||||
let generics = tcx.generics_of(trait_did);
|
||||
generics.count() == expected + if generics.has_self { 1 } else { 0 }
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1101,8 +1101,6 @@ fn check_type_defn<'tcx, F>(
|
|||
|
||||
// Explicit `enum` discriminant values must const-evaluate successfully.
|
||||
if let Some(discr_def_id) = variant.explicit_discr {
|
||||
let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
|
||||
|
||||
let cause = traits::ObligationCause::new(
|
||||
tcx.def_span(discr_def_id),
|
||||
wfcx.body_id,
|
||||
|
|
@ -1112,10 +1110,7 @@ fn check_type_defn<'tcx, F>(
|
|||
cause,
|
||||
wfcx.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
|
||||
ty::UnevaluatedConst::new(
|
||||
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
||||
discr_substs,
|
||||
),
|
||||
ty::Const::from_anon_const(tcx, discr_def_id),
|
||||
))
|
||||
.to_predicate(tcx),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -100,13 +100,12 @@ pub fn provide(providers: &mut Providers) {
|
|||
/// It's also used for the bodies of items like structs where the body (the fields)
|
||||
/// are just signatures.
|
||||
///
|
||||
/// This is in contrast to [`FnCtxt`], which is used to type-check bodies of
|
||||
/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
|
||||
/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
|
||||
///
|
||||
/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
|
||||
/// while `FnCtxt` does do inference.
|
||||
///
|
||||
/// [`FnCtxt`]: crate::check::FnCtxt
|
||||
/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
|
||||
///
|
||||
/// # Trait predicates
|
||||
|
|
|
|||
|
|
@ -318,10 +318,10 @@ fn const_evaluatable_predicates_of<'tcx>(
|
|||
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
||||
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
||||
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
||||
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
|
||||
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
|
||||
let span = self.tcx.hir().span(c.hir_id);
|
||||
self.preds.insert((
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
|
||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
|
||||
.to_predicate(self.tcx),
|
||||
span,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -1,24 +1,13 @@
|
|||
//! Errors emitted by `hir_analysis`.
|
||||
//! Errors emitted by `rustc_hir_analysis`.
|
||||
|
||||
use rustc_errors::IntoDiagnostic;
|
||||
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::field_multiply_specified_in_initializer, code = "E0062")]
|
||||
pub struct FieldMultiplySpecifiedInInitializer {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis::previous_use_label)]
|
||||
pub prev_span: Span,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::unrecognized_atomic_operation, code = "E0092")]
|
||||
#[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")]
|
||||
pub struct UnrecognizedAtomicOperation<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -27,7 +16,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
|
||||
#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
|
||||
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -38,7 +27,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::unrecognized_intrinsic_function, code = "E0093")]
|
||||
#[diag(hir_analysis_unrecognized_intrinsic_function, code = "E0093")]
|
||||
pub struct UnrecognizedIntrinsicFunction {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -47,19 +36,19 @@ pub struct UnrecognizedIntrinsicFunction {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
|
||||
#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
|
||||
pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis::generics_label)]
|
||||
#[label(generics_label)]
|
||||
pub generics_span: Option<Span>,
|
||||
pub item_kind: &'static str,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::drop_impl_on_wrong_item, code = "E0120")]
|
||||
#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
|
||||
pub struct DropImplOnWrongItem {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -67,18 +56,18 @@ pub struct DropImplOnWrongItem {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::field_already_declared, code = "E0124")]
|
||||
#[diag(hir_analysis_field_already_declared, code = "E0124")]
|
||||
pub struct FieldAlreadyDeclared {
|
||||
pub field_name: Ident,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis::previous_decl_label)]
|
||||
#[label(previous_decl_label)]
|
||||
pub prev_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::copy_impl_on_type_with_dtor, code = "E0184")]
|
||||
#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = "E0184")]
|
||||
pub struct CopyImplOnTypeWithDtor {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -86,14 +75,14 @@ pub struct CopyImplOnTypeWithDtor {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::multiple_relaxed_default_bounds, code = "E0203")]
|
||||
#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
|
||||
pub struct MultipleRelaxedDefaultBounds {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::copy_impl_on_non_adt, code = "E0206")]
|
||||
#[diag(hir_analysis_copy_impl_on_non_adt, code = "E0206")]
|
||||
pub struct CopyImplOnNonAdt {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -101,23 +90,23 @@ pub struct CopyImplOnNonAdt {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::trait_object_declared_with_no_traits, code = "E0224")]
|
||||
#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
|
||||
pub struct TraitObjectDeclaredWithNoTraits {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis::alias_span)]
|
||||
#[label(alias_span)]
|
||||
pub trait_alias_span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::ambiguous_lifetime_bound, code = "E0227")]
|
||||
#[diag(hir_analysis_ambiguous_lifetime_bound, code = "E0227")]
|
||||
pub struct AmbiguousLifetimeBound {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::assoc_type_binding_not_allowed, code = "E0229")]
|
||||
#[diag(hir_analysis_assoc_type_binding_not_allowed, code = "E0229")]
|
||||
pub struct AssocTypeBindingNotAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
|
|
@ -125,14 +114,7 @@ pub struct AssocTypeBindingNotAllowed {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::functional_record_update_on_non_struct, code = "E0436")]
|
||||
pub struct FunctionalRecordUpdateOnNonStruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::typeof_reserved_keyword_used, code = "E0516")]
|
||||
#[diag(hir_analysis_typeof_reserved_keyword_used, code = "E0516")]
|
||||
pub struct TypeofReservedKeywordUsed<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
#[primary_span]
|
||||
|
|
@ -143,98 +125,19 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::return_stmt_outside_of_fn_body, code = "E0572")]
|
||||
pub struct ReturnStmtOutsideOfFnBody {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis::encl_body_label)]
|
||||
pub encl_body_span: Option<Span>,
|
||||
#[label(hir_analysis::encl_fn_label)]
|
||||
pub encl_fn_span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::yield_expr_outside_of_generator, code = "E0627")]
|
||||
pub struct YieldExprOutsideOfGenerator {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::struct_expr_non_exhaustive, code = "E0639")]
|
||||
pub struct StructExprNonExhaustive {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub what: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::method_call_on_unknown_type, code = "E0699")]
|
||||
pub struct MethodCallOnUnknownType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::value_of_associated_struct_already_specified, code = "E0719")]
|
||||
#[diag(hir_analysis_value_of_associated_struct_already_specified, code = "E0719")]
|
||||
pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(hir_analysis::previous_bound_label)]
|
||||
#[label(previous_bound_label)]
|
||||
pub prev_span: Span,
|
||||
pub item_name: Ident,
|
||||
pub def_path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::address_of_temporary_taken, code = "E0745")]
|
||||
pub struct AddressOfTemporaryTaken {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum AddReturnTypeSuggestion {
|
||||
#[suggestion(
|
||||
hir_analysis::add_return_type_add,
|
||||
code = "-> {found} ",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Add {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
found: String,
|
||||
},
|
||||
#[suggestion(
|
||||
hir_analysis::add_return_type_missing_here,
|
||||
code = "-> _ ",
|
||||
applicability = "has-placeholders"
|
||||
)]
|
||||
MissingHere {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum ExpectedReturnTypeLabel<'tcx> {
|
||||
#[label(hir_analysis::expected_default_return_type)]
|
||||
Unit {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(hir_analysis::expected_return_type)]
|
||||
Other {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
expected: Ty<'tcx>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::unconstrained_opaque_type)]
|
||||
#[diag(hir_analysis_unconstrained_opaque_type)]
|
||||
#[note]
|
||||
pub struct UnconstrainedOpaqueType {
|
||||
#[primary_span]
|
||||
|
|
@ -255,7 +158,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
|
|||
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut err = handler.struct_span_err_with_code(
|
||||
self.span,
|
||||
rustc_errors::fluent::hir_analysis::missing_type_params,
|
||||
rustc_errors::fluent::hir_analysis_missing_type_params,
|
||||
error_code!(E0393),
|
||||
);
|
||||
err.set_arg("parameterCount", self.missing_type_params.len());
|
||||
|
|
@ -268,7 +171,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
|
|||
.join(", "),
|
||||
);
|
||||
|
||||
err.span_label(self.def_span, rustc_errors::fluent::hir_analysis::label);
|
||||
err.span_label(self.def_span, rustc_errors::fluent::label);
|
||||
|
||||
let mut suggested = false;
|
||||
// Don't suggest setting the type params if there are some already: the order is
|
||||
|
|
@ -283,7 +186,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
|
|||
// least we can clue them to the correct syntax `Iterator<Type>`.
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
rustc_errors::fluent::hir_analysis::suggestion,
|
||||
rustc_errors::fluent::suggestion,
|
||||
format!(
|
||||
"{}<{}>",
|
||||
snippet,
|
||||
|
|
@ -299,16 +202,16 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
|
|||
}
|
||||
}
|
||||
if !suggested {
|
||||
err.span_label(self.span, rustc_errors::fluent::hir_analysis::no_suggestion_label);
|
||||
err.span_label(self.span, rustc_errors::fluent::no_suggestion_label);
|
||||
}
|
||||
|
||||
err.note(rustc_errors::fluent::hir_analysis::note);
|
||||
err.note(rustc_errors::fluent::note);
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::manual_implementation, code = "E0183")]
|
||||
#[diag(hir_analysis_manual_implementation, code = "E0183")]
|
||||
#[help]
|
||||
pub struct ManualImplementation {
|
||||
#[primary_span]
|
||||
|
|
@ -318,21 +221,21 @@ pub struct ManualImplementation {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::substs_on_overridden_impl)]
|
||||
#[diag(hir_analysis_substs_on_overridden_impl)]
|
||||
pub struct SubstsOnOverriddenImpl {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_analysis::unused_extern_crate)]
|
||||
#[diag(hir_analysis_unused_extern_crate)]
|
||||
pub struct UnusedExternCrate {
|
||||
#[suggestion(applicability = "machine-applicable", code = "")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_analysis::extern_crate_not_idiomatic)]
|
||||
#[diag(hir_analysis_extern_crate_not_idiomatic)]
|
||||
pub struct ExternCrateNotIdiomatic {
|
||||
#[suggestion_short(applicability = "machine-applicable", code = "{suggestion_code}")]
|
||||
pub span: Span,
|
||||
|
|
@ -341,34 +244,8 @@ pub struct ExternCrateNotIdiomatic {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::expected_used_symbol)]
|
||||
#[diag(hir_analysis_expected_used_symbol)]
|
||||
pub struct ExpectedUsedSymbol {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis::missing_parentheses_in_range, code = "E0689")]
|
||||
pub struct MissingParentheseInRange {
|
||||
#[primary_span]
|
||||
#[label(hir_analysis::missing_parentheses_in_range)]
|
||||
pub span: Span,
|
||||
pub ty_str: String,
|
||||
pub method_name: String,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion_verbose(
|
||||
hir_analysis::add_missing_parentheses_in_range,
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub struct AddMissingParenthesesInRange {
|
||||
pub func_name: String,
|
||||
#[suggestion_part(code = "(")]
|
||||
pub left: Span,
|
||||
#[suggestion_part(code = ")")]
|
||||
pub right: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,20 +82,19 @@ extern crate rustc_middle;
|
|||
|
||||
// These are used by Clippy.
|
||||
pub mod check;
|
||||
pub mod expr_use_visitor;
|
||||
|
||||
mod astconv;
|
||||
pub mod astconv;
|
||||
mod bounds;
|
||||
mod check_unused;
|
||||
mod coherence;
|
||||
mod collect;
|
||||
// FIXME: This module shouldn't be public.
|
||||
pub mod collect;
|
||||
mod constrained_generic_params;
|
||||
mod errors;
|
||||
pub mod hir_wf_check;
|
||||
mod impl_wf_check;
|
||||
mod mem_categorization;
|
||||
mod outlives;
|
||||
mod structured_errors;
|
||||
pub mod structured_errors;
|
||||
mod variance;
|
||||
|
||||
use rustc_errors::{struct_span_err, ErrorGuaranteed};
|
||||
|
|
|
|||
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