diff options
| author | bors <bors@rust-lang.org> | 2024-07-12 22:59:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-07-12 22:59:30 +0000 |
| commit | 336e89bd1518f2cd81574384037b3cffe03c63a8 (patch) | |
| tree | c4b4a19cf261aa4d458f68142c34f9fd8f2720f5 /compiler | |
| parent | c6727fc9b5c64cefa7263486497ee95e529bd0f8 (diff) | |
| parent | 8f8734c67a6df655667ad5e008ad42f2edabba87 (diff) | |
Auto merge of #127665 - workingjubilee:rollup-g90yr21, r=workingjubilee
Rollup of 11 pull requests Successful merges: - #126502 (Ignore allocation bytes in some mir-opt tests) - #126922 (add lint for inline asm labels that look like binary) - #127209 (Added the `xop` target-feature and the `xop_target_feature` feature gate) - #127310 (Fix import suggestion ice) - #127338 (Migrate `extra-filename-with-temp-outputs` and `issue-85019-moved-src-dir` `run-make` tests to rmake) - #127381 (Migrate `issue-83045`, `rustc-macro-dep-files` and `env-dep-info` `run-make` tests to rmake) - #127535 (Fire unsafe_code lint on unsafe extern blocks) - #127619 (Suggest using precise capturing for hidden type that captures region) - #127631 (Remove `fully_normalize`) - #127632 (Implement `precise_capturing` support for rustdoc) - #127660 (Rename the internal `const_strlen` to just `strlen`) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
20 files changed, 353 insertions, 129 deletions
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 22006c0b471..cea164df617 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -81,6 +81,7 @@ pub fn from_target_feature( Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature, Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature, Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics, + Some(sym::xop_target_feature) => rust_features.xop_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index dfbe270822c..5673101dc24 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -642,6 +642,8 @@ declare_features! ( (unstable, used_with_arg, "1.60.0", Some(93798)), /// Allows use of x86 `AMX` target-feature attributes and intrinsics (unstable, x86_amx_intrinsics, "CURRENT_RUSTC_VERSION", Some(126622)), + /// Allows use of the `xop` target-feature + (unstable, xop_target_feature, "CURRENT_RUSTC_VERSION", Some(127208)), /// Allows `do yeet` expressions (unstable, yeet_expr, "1.62.0", Some(96373)), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d57fad6ba4c..4561f9d9b49 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2708,6 +2708,13 @@ impl PreciseCapturingArg<'_> { PreciseCapturingArg::Param(param) => param.hir_id, } } + + pub fn name(self) -> Symbol { + match self { + PreciseCapturingArg::Lifetime(lt) => lt.ident.name, + PreciseCapturingArg::Param(param) => param.ident.name, + } + } } /// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index fbe8d31370c..7a5e7159920 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -221,6 +221,10 @@ infer_opaque_hidden_type = infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type infer_outlives_content = lifetime of reference outlives lifetime of borrowed content... + +infer_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it +infer_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}` + infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here... infer_prlf_defined_without_sub = the lifetime defined here... infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index a801001eaf9..ce1b0f86d03 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1581,3 +1581,32 @@ pub enum ObligationCauseFailureCode { subdiags: Vec<TypeErrorAdditionalDiags>, }, } + +#[derive(Subdiagnostic)] +pub enum AddPreciseCapturing { + #[suggestion( + infer_precise_capturing_new, + style = "verbose", + code = " + use<{concatenated_bounds}>", + applicability = "machine-applicable" + )] + New { + #[primary_span] + span: Span, + new_lifetime: Symbol, + concatenated_bounds: String, + }, + #[suggestion( + infer_precise_capturing_existing, + style = "verbose", + code = "{pre}{new_lifetime}{post}", + applicability = "machine-applicable" + )] + Existing { + #[primary_span] + span: Span, + new_lifetime: Symbol, + pre: &'static str, + post: &'static str, + }, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/region.rs b/compiler/rustc_infer/src/infer/error_reporting/region.rs index 5a465f46e47..191cb23184d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/region.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/region.rs @@ -1,5 +1,6 @@ use std::iter; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ struct_span_code_err, Applicability, Diag, Subdiagnostic, E0309, E0310, E0311, E0495, }; @@ -12,7 +13,7 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_span::symbol::kw; -use rustc_span::{ErrorGuaranteed, Span}; +use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol}; use rustc_type_ir::Upcast as _; use super::nice_region_error::find_anon_type; @@ -1201,17 +1202,21 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>( "", ); if let Some(reg_info) = tcx.is_suitable_region(generic_param_scope, hidden_region) { - let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id); - nice_region_error::suggest_new_region_bound( - tcx, - &mut err, - fn_returns, - hidden_region.to_string(), - None, - format!("captures `{hidden_region}`"), - None, - Some(reg_info.def_id), - ) + if infcx.tcx.features().precise_capturing { + suggest_precise_capturing(tcx, opaque_ty_key.def_id, hidden_region, &mut err); + } else { + let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id); + nice_region_error::suggest_new_region_bound( + tcx, + &mut err, + fn_returns, + hidden_region.to_string(), + None, + format!("captures `{hidden_region}`"), + None, + Some(reg_info.def_id), + ) + } } } ty::RePlaceholder(_) => { @@ -1257,3 +1262,95 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>( err } + +fn suggest_precise_capturing<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: LocalDefId, + captured_lifetime: ty::Region<'tcx>, + diag: &mut Diag<'_>, +) { + let hir::OpaqueTy { bounds, .. } = + tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty(); + + let new_lifetime = Symbol::intern(&captured_lifetime.to_string()); + + if let Some((args, span)) = bounds.iter().find_map(|bound| match bound { + hir::GenericBound::Use(args, span) => Some((args, span)), + _ => None, + }) { + let last_lifetime_span = args.iter().rev().find_map(|arg| match arg { + hir::PreciseCapturingArg::Lifetime(lt) => Some(lt.ident.span), + _ => None, + }); + + let first_param_span = args.iter().find_map(|arg| match arg { + hir::PreciseCapturingArg::Param(p) => Some(p.ident.span), + _ => None, + }); + + let (span, pre, post) = if let Some(last_lifetime_span) = last_lifetime_span { + (last_lifetime_span.shrink_to_hi(), ", ", "") + } else if let Some(first_param_span) = first_param_span { + (first_param_span.shrink_to_lo(), "", ", ") + } else { + // If we have no args, then have `use<>` and need to fall back to using + // span math. This sucks, but should be reliable due to the construction + // of the `use<>` span. + (span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), "", "") + }; + + diag.subdiagnostic(errors::AddPreciseCapturing::Existing { span, new_lifetime, pre, post }); + } else { + let mut captured_lifetimes = FxIndexSet::default(); + let mut captured_non_lifetimes = FxIndexSet::default(); + + let variances = tcx.variances_of(opaque_def_id); + let mut generics = tcx.generics_of(opaque_def_id); + loop { + for param in &generics.own_params { + if variances[param.index as usize] == ty::Bivariant { + continue; + } + + match param.kind { + ty::GenericParamDefKind::Lifetime => { + captured_lifetimes.insert(param.name); + } + ty::GenericParamDefKind::Type { synthetic: true, .. } => { + // FIXME: We can't provide a good suggestion for + // `use<...>` if we have an APIT. Bail for now. + return; + } + ty::GenericParamDefKind::Type { .. } + | ty::GenericParamDefKind::Const { .. } => { + captured_non_lifetimes.insert(param.name); + } + } + } + + if let Some(parent) = generics.parent { + generics = tcx.generics_of(parent); + } else { + break; + } + } + + if !captured_lifetimes.insert(new_lifetime) { + // Uh, strange. This lifetime appears to already be captured... + return; + } + + let concatenated_bounds = captured_lifetimes + .into_iter() + .chain(captured_non_lifetimes) + .map(|sym| sym.to_string()) + .collect::<Vec<_>>() + .join(", "); + + diag.subdiagnostic(errors::AddPreciseCapturing::New { + span: tcx.def_span(opaque_def_id).shrink_to_hi(), + new_lifetime, + concatenated_bounds, + }); + } +} diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index e2ba75dfd19..7d7a6a08bee 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -691,6 +691,7 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir, Some(String::from("abc"))); untracked!(dump_mir_dataflow, true); untracked!(dump_mir_dir, String::from("abc")); + untracked!(dump_mir_exclude_alloc_bytes, true); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 4f2d59b4c66..de04d882f51 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -52,10 +52,6 @@ lint_builtin_allow_internal_unsafe = lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition .suggestion = try naming the parameter or explicitly ignoring it -lint_builtin_asm_labels = avoid using named labels in inline assembly - .help = only local labels of the form `<number>:` should be used in inline asm - .note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information - lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature .previous_decl_label = `{$orig}` previously declared here .mismatch_label = this signature doesn't match the previous declaration @@ -163,6 +159,8 @@ lint_builtin_unreachable_pub = unreachable `pub` {$what} lint_builtin_unsafe_block = usage of an `unsafe` block +lint_builtin_unsafe_extern_block = usage of an `unsafe extern` block + lint_builtin_unsafe_impl = implementation of an `unsafe` trait lint_builtin_unsafe_trait = declaration of an `unsafe` trait @@ -403,6 +401,19 @@ lint_incomplete_include = lint_inner_macro_attribute_unstable = inner macro attributes are unstable +lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly + .label = use a different label that doesn't start with `0` or `1` + .note = an LLVM bug makes these labels ambiguous with a binary literal number + .note = see <https://bugs.llvm.org/show_bug.cgi?id=36144> for more information + +lint_invalid_asm_label_format_arg = avoid using named labels in inline assembly + .help = only local labels of the form `<number>:` should be used in inline asm + .note1 = format arguments may expand to a non-numeric value + .note2 = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information +lint_invalid_asm_label_named = avoid using named labels in inline assembly + .help = only local labels of the form `<number>:` should be used in inline asm + .note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information +lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro lint_invalid_crate_type_value = invalid `crate_type` value .suggestion = did you mean diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 79c8046f9b7..485c214ac9d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -30,13 +30,13 @@ use crate::{ BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, - BuiltinMutablesTransmutes, BuiltinNamedAsmLabel, BuiltinNoMangleGeneric, - BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, - BuiltinTypeAliasGenericBounds, BuiltinTypeAliasGenericBoundsSuggestion, - BuiltinTypeAliasWhereClause, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, + BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, + BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds, + BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause, + BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, SuggestChangingAssocTypes, + BuiltinWhileTrue, InvalidAsmLabel, SuggestChangingAssocTypes, }, EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, }; @@ -45,7 +45,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::{self, expr_to_string}; -use rustc_errors::{Applicability, LintDiagnostic, MultiSpan}; +use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -69,7 +69,6 @@ use rustc_target::abi::Abi; use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy}; -use tracing::debug; use crate::nonstandard_style::{method_context, MethodLateContext}; @@ -326,6 +325,12 @@ impl EarlyLintPass for UnsafeCode { self.report_unsafe(cx, it.span, BuiltinUnsafe::GlobalAsm); } + ast::ItemKind::ForeignMod(ForeignMod { safety, .. }) => { + if let Safety::Unsafe(_) = safety { + self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeExternBlock); + } + } + _ => {} } } @@ -2728,10 +2733,52 @@ declare_lint! { "named labels in inline assembly", } -declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]); +declare_lint! { + /// The `binary_asm_labels` lint detects the use of numeric labels containing only binary + /// digits in the inline `asm!` macro. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # #![feature(asm_experimental_arch)] + /// use std::arch::asm; + /// + /// fn main() { + /// unsafe { + /// asm!("0: jmp 0b"); + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A [LLVM bug] causes this code to fail to compile because it interprets the `0b` as a binary + /// literal instead of a reference to the previous local label `0`. Note that even though the + /// bug is marked as fixed, it only fixes a specific usage of intel syntax within standalone + /// files, not inline assembly. To work around this bug, don't use labels that could be + /// confused with a binary literal. + /// + /// See the explanation in [Rust By Example] for more details. + /// + /// [LLVM bug]: https://bugs.llvm.org/show_bug.cgi?id=36144 + /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels + pub BINARY_ASM_LABELS, + Deny, + "labels in inline assembly containing only 0 or 1 digits", +} + +declare_lint_pass!(AsmLabels => [NAMED_ASM_LABELS, BINARY_ASM_LABELS]); + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum AsmLabelKind { + Named, + FormatArg, + Binary, +} -impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { - #[allow(rustc::diagnostic_outside_of_impl)] +impl<'tcx> LateLintPass<'tcx> for AsmLabels { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::Expr { kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }), @@ -2759,7 +2806,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { None }; - let mut found_labels = Vec::new(); + // diagnostics are emitted per-template, so this is created here as opposed to the outer loop + let mut spans = Vec::new(); // A semicolon might not actually be specified as a separator for all targets, but // it seems like LLVM accepts it always. @@ -2782,16 +2830,21 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { // Whether a { bracket has been seen and its } hasn't been found yet. let mut in_bracket = false; + let mut label_kind = AsmLabelKind::Named; - // A label starts with an ASCII alphabetic character or . or _ // A label can also start with a format arg, if it's not a raw asm block. if !raw && start == '{' { in_bracket = true; + label_kind = AsmLabelKind::FormatArg; + } else if matches!(start, '0' | '1') { + // Binary labels have only the characters `0` or `1`. + label_kind = AsmLabelKind::Binary; } else if !(start.is_ascii_alphabetic() || matches!(start, '.' | '_')) { + // Named labels start with ASCII letters, `.` or `_`. + // anything else is not a label break 'label_loop; } - // Labels continue with ASCII alphanumeric characters, _, or $ for c in chars { // Inside a template format arg, any character is permitted for the // puproses of label detection because we assume that it can be @@ -2812,8 +2865,18 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { } else if !raw && c == '{' { // Start of a format arg. in_bracket = true; + label_kind = AsmLabelKind::FormatArg; } else { - if !(c.is_ascii_alphanumeric() || matches!(c, '_' | '$')) { + let can_continue = match label_kind { + // Format arg labels are considered to be named labels for the purposes + // of continuing outside of their {} pair. + AsmLabelKind::Named | AsmLabelKind::FormatArg => { + c.is_ascii_alphanumeric() || matches!(c, '_' | '$') + } + AsmLabelKind::Binary => matches!(c, '0' | '1'), + }; + + if !can_continue { // The potential label had an invalid character inside it, it // cannot be a label. break 'label_loop; @@ -2821,25 +2884,41 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { } } - // If all characters passed the label checks, this is likely a label. - found_labels.push(possible_label); + // If all characters passed the label checks, this is a label. + spans.push((find_label_span(possible_label), label_kind)); start_idx = idx + 1; } } - debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels); - - if found_labels.len() > 0 { - let spans = found_labels - .into_iter() - .filter_map(|label| find_label_span(label)) - .collect::<Vec<Span>>(); - // If there were labels but we couldn't find a span, combine the warnings and - // use the template span. - let target_spans: MultiSpan = - if spans.len() > 0 { spans.into() } else { (*template_span).into() }; - - cx.emit_span_lint(NAMED_ASM_LABELS, target_spans, BuiltinNamedAsmLabel); + for (span, label_kind) in spans { + let missing_precise_span = span.is_none(); + let span = span.unwrap_or(*template_span); + match label_kind { + AsmLabelKind::Named => { + cx.emit_span_lint( + NAMED_ASM_LABELS, + span, + InvalidAsmLabel::Named { missing_precise_span }, + ); + } + AsmLabelKind::FormatArg => { + cx.emit_span_lint( + NAMED_ASM_LABELS, + span, + InvalidAsmLabel::FormatArg { missing_precise_span }, + ); + } + AsmLabelKind::Binary => { + // the binary asm issue only occurs when using intel syntax + if !options.contains(InlineAsmOptions::ATT_SYNTAX) { + cx.emit_span_lint( + BINARY_ASM_LABELS, + span, + InvalidAsmLabel::Binary { missing_precise_span, span }, + ) + } + } + }; } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b6927cf60b6..8be8996e4c8 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -225,7 +225,7 @@ late_lint_methods!( NoopMethodCall: NoopMethodCall, EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, InvalidAtomicOrdering: InvalidAtomicOrdering, - NamedAsmLabels: NamedAsmLabels, + AsmLabels: AsmLabels, OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, MultipleSupertraitUpcastable: MultipleSupertraitUpcastable, MapUnitFn: MapUnitFn, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 54c73710eca..308bb73f4ce 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -81,6 +81,8 @@ pub enum BuiltinUnsafe { AllowInternalUnsafe, #[diag(lint_builtin_unsafe_block)] UnsafeBlock, + #[diag(lint_builtin_unsafe_extern_block)] + UnsafeExternBlock, #[diag(lint_builtin_unsafe_trait)] UnsafeTrait, #[diag(lint_builtin_unsafe_impl)] @@ -2047,10 +2049,32 @@ pub struct UnitBindingsDiag { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_asm_labels)] -#[help] -#[note] -pub struct BuiltinNamedAsmLabel; +pub enum InvalidAsmLabel { + #[diag(lint_invalid_asm_label_named)] + #[help] + #[note] + Named { + #[note(lint_invalid_asm_label_no_span)] + missing_precise_span: bool, + }, + #[diag(lint_invalid_asm_label_format_arg)] + #[help] + #[note(lint_note1)] + #[note(lint_note2)] + FormatArg { + #[note(lint_invalid_asm_label_no_span)] + missing_precise_span: bool, + }, + #[diag(lint_invalid_asm_label_binary)] + #[note] + Binary { + #[note(lint_invalid_asm_label_no_span)] + missing_precise_span: bool, + // hack to get a label on the whole span, must match the emitted span + #[label] + span: Span, + }, +} #[derive(Subdiagnostic)] pub enum UnexpectedCfgCargoHelp { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 5ee73dbfdc6..fdb71ad41a7 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -5,8 +5,7 @@ use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifie use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{symbol::kw, Span}; -use rustc_trait_selection::traits; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::{LateContext, LateLintPass, LintContext}; @@ -130,24 +129,26 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { .iter_instantiated_copied(cx.tcx, proj.projection_term.args) { let assoc_pred = assoc_pred.fold_with(proj_replacer); - let Ok(assoc_pred) = traits::fully_normalize( - infcx, + + let ocx = ObligationCtxt::new(infcx); + let assoc_pred = + ocx.normalize(&traits::ObligationCause::dummy(), cx.param_env, assoc_pred); + if !ocx.select_all_or_error().is_empty() { + // Can't normalize for some reason...? + continue; + } + + ocx.register_obligation(traits::Obligation::new( + cx.tcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred, - ) else { - continue; - }; + )); // If that predicate doesn't hold modulo regions (but passed during type-check), // then we must've taken advantage of the hack in `project_and_unify_types` where // we replace opaques with inference vars. Emit a warning! - if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( - cx.tcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - )) { + if !ocx.select_all_or_error().is_empty() { // If it's a trait bound and an opaque that doesn't satisfy it, // then we can emit a suggestion to add the bound. let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 82625ae3d47..223249952dc 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1545,6 +1545,9 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display // We are done. return write!(w, " {{}}"); } + if tcx.sess.opts.unstable_opts.dump_mir_exclude_alloc_bytes { + return write!(w, " {{ .. }}"); + } // Write allocation bytes. writeln!(w, " {{")?; write_allocation_bytes(tcx, alloc, w, " ")?; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 09221041031..e3917acce65 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1992,12 +1992,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(candidate) = candidates.get(0) { let path = { // remove the possible common prefix of the path - let start_index = (0..failed_segment_idx) - .find(|&i| path[i].ident != candidate.path.segments[i].ident) + let len = candidate.path.segments.len(); + let start_index = (0..=failed_segment_idx.min(len - 1)) + .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name) .unwrap_or_default(); - let segments = (start_index..=failed_segment_idx) - .map(|s| candidate.path.segments[s].clone()) - .collect(); + let segments = + (start_index..len).map(|s| candidate.path.segments[s].clone()).collect(); Path { segments, span: Span::default(), tokens: None } }; ( diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7421cae65e4..68f3ff13d2e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1687,6 +1687,8 @@ options! { (default: no)"), dump_mir_dir: String = ("mir_dump".to_string(), parse_string, [UNTRACKED], "the directory the MIR is dumped into (default: `mir_dump`)"), + dump_mir_exclude_alloc_bytes: bool = (false, parse_bool, [UNTRACKED], + "exclude the raw bytes of allocations when dumping MIR (used in tests) (default: no)"), dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED], "exclude the pass number when dumping MIR (used in tests) (default: no)"), dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 827b9062d83..2fe7c951793 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2076,6 +2076,7 @@ symbols! { x87_reg, xer, xmm_reg, + xop_target_feature, yeet_desugar_details, yeet_expr, yes, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index aec2828181b..6667efb14e2 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -246,6 +246,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("tbm", Unstable(sym::tbm_target_feature)), ("vaes", Unstable(sym::avx512_target_feature)), ("vpclmulqdq", Unstable(sym::avx512_target_feature)), + ("xop", Unstable(sym::xop_target_feature)), ("xsave", Stable), ("xsavec", Stable), ("xsaveopt", Stable), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 703ff2f7f16..d28982ed849 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -271,13 +271,14 @@ fn do_normalize_predicates<'tcx>( // them here too, and we will remove this function when // we move over to lazy normalization *anyway*. let infcx = tcx.infer_ctxt().ignoring_regions().build(); - let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) { - Ok(predicates) => predicates, - Err(errors) => { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); - } - }; + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + let predicates = ocx.normalize(&cause, elaborated_env, predicates); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(reported); + } debug!("do_normalize_predicates: normalized predicates = {:?}", predicates); @@ -465,37 +466,6 @@ pub fn normalize_param_env_or_error<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal()) } -/// Normalize a type and process all resulting obligations, returning any errors. -/// -/// FIXME(-Znext-solver): This should be replaced by `At::deeply_normalize` -/// which has the same behavior with the new solver. Because using a separate -/// fulfillment context worsens caching in the old solver, `At::deeply_normalize` -/// is still lazy with the old solver as it otherwise negatively impacts perf. -#[instrument(skip_all)] -pub fn fully_normalize<'tcx, T>( - infcx: &InferCtxt<'tcx>, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: T, -) -> Result<T, Vec<FulfillmentError<'tcx>>> -where - T: TypeFoldable<TyCtxt<'tcx>>, -{ - let ocx = ObligationCtxt::new_with_diagnostics(infcx); - debug!(?value); - let normalized_value = ocx.normalize(&cause, param_env, value); - debug!(?normalized_value); - debug!("select_all_or_error start"); - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - return Err(errors); - } - debug!("select_all_or_error complete"); - let resolved_value = infcx.resolve_vars_if_possible(normalized_value); - debug!(?resolved_value); - Ok(resolved_value) -} - /// Normalizes the predicates and checks whether they hold in an empty environment. If this /// returns true, then either normalize encountered an error or one of the predicates did not /// hold. Used when creating vtables to check for unsatisfiable methods. diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 3a7481acbaf..01ba8c02ea6 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -42,11 +42,9 @@ impl<'tcx> At<'_, 'tcx> { /// same goals in both a temporary and the shared context which negatively impacts /// performance as these don't share caching. /// - /// FIXME(-Znext-solver): This has the same behavior as `traits::fully_normalize` - /// in the new solver, but because of performance reasons, we currently reuse an - /// existing fulfillment context in the old solver. Once we also eagerly prove goals with - /// the old solver or have removed the old solver, remove `traits::fully_normalize` and - /// rename this function to `At::fully_normalize`. + /// FIXME(-Znext-solver): For performance reasons, we currently reuse an existing + /// fulfillment context in the old solver. Once we have removed the old solver, we + /// can remove the `fulfill_cx` parameter on this function. fn deeply_normalize<T, E>( self, value: T, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 6a904ef487e..3c33d13567d 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -18,9 +18,7 @@ use crate::error_reporting::traits::to_pretty_impl_header; use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::{ - self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt, -}; +use crate::traits::{coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, Diag, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -219,19 +217,17 @@ fn fulfill_implication<'tcx>( param_env, source_trait_ref, target_impl ); - let source_trait_ref = - match traits::fully_normalize(infcx, ObligationCause::dummy(), param_env, source_trait_ref) - { - Ok(source_trait_ref) => source_trait_ref, - Err(_errors) => { - infcx.dcx().span_delayed_bug( - infcx.tcx.def_span(source_impl), - format!("failed to fully normalize {source_trait_ref}"), - ); - source_trait_ref - } - }; + let ocx = ObligationCtxt::new(infcx); + let source_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, source_trait_ref); + if !ocx.select_all_or_error().is_empty() { + infcx.dcx().span_delayed_bug( + infcx.tcx.def_span(source_impl), + format!("failed to fully normalize {source_trait_ref}"), + ); + } + + let source_trait_ref = infcx.resolve_vars_if_possible(source_trait_ref); let source_trait = ImplSubject::Trait(source_trait_ref); let selcx = SelectionContext::new(infcx); @@ -253,9 +249,6 @@ fn fulfill_implication<'tcx>( return Err(()); }; - // Needs to be `in_snapshot` because this function is used to rebase - // generic parameters, which may happen inside of a select within a probe. - let ocx = ObligationCtxt::new(infcx); // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) ocx.register_obligations(obligations.chain(more_obligations)); |
