Auto merge of #2618 - RalfJung:rustup, r=RalfJung

Rustup
This commit is contained in:
bors 2022-10-25 18:02:23 +00:00
commit a46ccba167
802 changed files with 20840 additions and 10369 deletions

View file

@ -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]]

View file

@ -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()
}

View file

@ -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,

View file

@ -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),
}

View file

@ -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,
);

View file

@ -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,

View file

@ -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
}
})
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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(

View file

@ -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

View file

@ -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

View file

@ -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": [],

View file

@ -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",

View file

@ -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"

View file

@ -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",

View 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);
}

View file

@ -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);
}

View file

@ -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"))
}

View file

@ -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");

View file

@ -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")

View file

@ -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,
);

View file

@ -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);
}
}

View file

@ -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));
}
}

View file

@ -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();

View file

@ -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/

View file

@ -49,4 +49,4 @@ test.regex-shootout-regex-dna
test.regex
test.portable-simd
testsuite.abi-checker
testsuite.abi-cafe

View file

@ -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;

View file

@ -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);
}

View file

@ -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); }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2022-08-24"
channel = "nightly-2022-10-23"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -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"

View file

@ -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

View file

@ -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(_, _)));

View file

@ -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);

View file

@ -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: {}",

View file

@ -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_),
}
}

View file

@ -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");
}
}
}

View file

@ -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

View file

@ -106,7 +106,7 @@ impl OngoingCodegen {
}
}
drop(self.concurrency_limiter);
self.concurrency_limiter.finished();
(
CodegenResults {

View file

@ -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>(

View file

@ -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!(),

View file

@ -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 {

View file

@ -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![],
});

View file

@ -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
_ => {

View file

@ -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() {

View file

@ -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);

View file

@ -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,

View file

@ -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>(

View file

@ -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>,

View file

@ -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();

View file

@ -47,6 +47,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
_lib_name: &str,
_dll_imports: &[DllImport],
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
unimplemented!();
}

View file

@ -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

View file

@ -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{}",

View file

@ -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");

View file

@ -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);

View file

@ -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);

View file

@ -25,6 +25,7 @@ pub trait ArchiveBuilderBuilder {
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &Path,
is_direct_dependency: bool,
) -> PathBuf;
fn extract_bundled_libs(

View file

@ -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,
));
}

View file

@ -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,
};

View file

@ -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() {

View file

@ -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 wont be doing codegen, create target machines without optimisation.

View file

@ -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
}

View file

@ -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();

View file

@ -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) {

View file

@ -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
}

View file

@ -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
}
}

View file

@ -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) {

View file

@ -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,

View file

@ -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(

View file

@ -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:?}"
),
);
}

View file

@ -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)]

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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
}

View file

@ -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) {}

View file

@ -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;
}
}
}
}
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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)
}

View file

@ -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";

View file

@ -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(&param.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);

View file

@ -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[&region.into()].expect_region().kind()
else { bug!("expected ReFree to map to ReEarlyBound"); };
let Some(ty::ReEarlyBound(e)) = map.get(&region.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);

View file

@ -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)),

View file

@ -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>,

View file

@ -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 }
})
}

View file

@ -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),
));

View file

@ -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

View file

@ -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,
));

View file

@ -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,
}

View file

@ -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