From ef0ba1d2cead709f11fe7912e0d2bd8c3f5e1b28 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Feb 2022 13:39:07 -0800 Subject: [PATCH 01/11] type parameters have unit metadata if they are sized --- compiler/rustc_middle/src/ty/sty.rs | 22 ++++++++------- .../src/traits/project.rs | 27 +++++++++++++++---- src/test/ui/traits/pointee-tail-is-generic.rs | 12 +++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/traits/pointee-tail-is-generic.rs diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a1e906140e0e8..061520189e980 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2244,12 +2244,13 @@ impl<'tcx> Ty<'tcx> { } } - /// Returns the type of metadata for (potentially fat) pointers to this type. + /// Returns the type of metadata for (potentially fat) pointers to this type, + /// and a boolean signifying if this is conditional on this type being `Sized`. pub fn ptr_metadata_ty( self, tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - ) -> Ty<'tcx> { + ) -> (Ty<'tcx>, bool) { let tail = tcx.struct_tail_with_normalize(self, normalize); match tail.kind() { // Sized types @@ -2269,28 +2270,31 @@ impl<'tcx> Ty<'tcx> { | ty::Closure(..) | ty::Never | ty::Error(_) + // Extern types have metadata = (). | ty::Foreign(..) // If returned by `struct_tail_without_normalization` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) // If returned by `struct_tail_without_normalization` this is the empty tuple, // a.k.a. unit type, which is Sized - | ty::Tuple(..) => tcx.types.unit, + | ty::Tuple(..) => (tcx.types.unit, false), - ty::Str | ty::Slice(_) => tcx.types.usize, + ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(..) => { let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap(); - tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]) + (tcx.type_of(dyn_metadata).subst(tcx, &[self.into()]), false) }, - ty::Projection(_) - | ty::Param(_) - | ty::Opaque(..) + // type parameters only have unit metadata if they're sized, so return true + // to make sure we double check this during confirmation + ty::Param(_) | ty::Projection(_) => (tcx.types.unit, true), + + ty::Opaque(..) | ty::Infer(ty::TyVar(_)) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`ptr_metadata_ty` applied to unexpected type: {:?}", tail) + bug!("`ptr_metadata_ty` applied to unexpected type: {:?}", self) } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c32c73c638412..823b03eab950d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1399,6 +1399,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); let tail = selcx.tcx().struct_tail_with_normalize(self_ty, |ty| { + // We throw away any obligations we get from this, since we normalize + // and confirm these obligations once again during confirmation normalize_with_depth( selcx, obligation.param_env, @@ -1415,7 +1417,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Int(_) | ty::Uint(_) | ty::Float(_) - | ty::Foreign(_) | ty::Str | ty::Array(..) | ty::Slice(_) @@ -1428,6 +1429,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Never + // Extern types have unit metadata, according to RFC 2850 + | ty::Foreign(_) // If returned by `struct_tail_without_normalization` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) @@ -1436,9 +1439,10 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats are always Sized, and so have unit type metadata. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - ty::Projection(..) - | ty::Opaque(..) - | ty::Param(..) + // type parameters and unnormalized projections have pointer metadata if they're still known to be sized + ty::Param(_) | ty::Projection(..) => tail.is_sized(selcx.tcx().at(obligation.cause.span), obligation.param_env), + + ty::Opaque(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) @@ -1657,7 +1661,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); let mut obligations = vec![]; - let metadata_ty = self_ty.ptr_metadata_ty(tcx, |ty| { + let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| { normalize_with_depth_to( selcx, obligation.param_env, @@ -1667,6 +1671,19 @@ fn confirm_pointee_candidate<'cx, 'tcx>( &mut obligations, ) }); + if check_is_sized { + let sized_predicate = ty::Binder::dummy(ty::TraitRef::new( + tcx.require_lang_item(LangItem::Sized, None), + tcx.mk_substs_trait(self_ty, &[]), + )) + .without_const() + .to_predicate(tcx); + obligations.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env, + sized_predicate, + )); + } let substs = tcx.mk_substs([self_ty.into()].iter()); let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); diff --git a/src/test/ui/traits/pointee-tail-is-generic.rs b/src/test/ui/traits/pointee-tail-is-generic.rs new file mode 100644 index 0000000000000..097881256ba8d --- /dev/null +++ b/src/test/ui/traits/pointee-tail-is-generic.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(ptr_metadata)] + +fn a() { + b::(); + b::>(); +} + +fn b>() {} + +fn main() {} From 1d834cb657d4911535a01af38e974d11d081e9f4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Feb 2022 19:57:23 -0800 Subject: [PATCH 02/11] opaque types may also be sized --- compiler/rustc_middle/src/ty/sty.rs | 9 ++++---- .../src/traits/project.rs | 16 +++++++++---- src/test/ui/traits/pointee-tail-is-generic.rs | 23 ++++++++++++++++--- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 061520189e980..f64d1e06f6c4b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2282,19 +2282,18 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(..) => { let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap(); - (tcx.type_of(dyn_metadata).subst(tcx, &[self.into()]), false) + (tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false) }, // type parameters only have unit metadata if they're sized, so return true // to make sure we double check this during confirmation - ty::Param(_) | ty::Projection(_) => (tcx.types.unit, true), + ty::Param(_) | ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true), - ty::Opaque(..) - | ty::Infer(ty::TyVar(_)) + ty::Infer(ty::TyVar(_)) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`ptr_metadata_ty` applied to unexpected type: {:?}", self) + bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail) } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 823b03eab950d..26f7d0782c283 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1439,10 +1439,18 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats are always Sized, and so have unit type metadata. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - // type parameters and unnormalized projections have pointer metadata if they're still known to be sized - ty::Param(_) | ty::Projection(..) => tail.is_sized(selcx.tcx().at(obligation.cause.span), obligation.param_env), + // type parameters, opaques, and unnormalized projections have pointer + // metadata if they're known (e.g. by the param_env) to be sized + ty::Param(_) | ty::Projection(..) | ty::Opaque(..) + if tail.is_sized(selcx.tcx().at(obligation.cause.span), obligation.param_env) => + { + true + } - ty::Opaque(..) + // FIXME(compiler-errors): are Bound and Placeholder types ever known sized? + ty::Param(_) + | ty::Projection(..) + | ty::Opaque(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) @@ -1451,7 +1459,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( candidate_set.mark_ambiguous(); } false - }, + } } } super::ImplSource::Param(..) => { diff --git a/src/test/ui/traits/pointee-tail-is-generic.rs b/src/test/ui/traits/pointee-tail-is-generic.rs index 097881256ba8d..e0da0fc38613d 100644 --- a/src/test/ui/traits/pointee-tail-is-generic.rs +++ b/src/test/ui/traits/pointee-tail-is-generic.rs @@ -1,12 +1,29 @@ // check-pass +// edition:2018 #![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] + +type Opaque = impl std::future::Future; + +fn opaque() -> Opaque { + async {} +} fn a() { - b::(); - b::>(); + // type parameter T is known to be sized + is_thin::(); + // tail of ADT (which is a type param) is known to be sized + is_thin::>(); + // opaque type is known to be sized + is_thin::(); +} + +fn a2() { + // associated type is known to be sized + is_thin::(); } -fn b>() {} +fn is_thin>() {} fn main() {} From 210e829010022d2a8e49a2519aec8ac6bee20ed1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 3 Mar 2022 22:04:23 -0800 Subject: [PATCH 03/11] add tests for metadata for unsized generics and opaques --- .../traits/pointee-tail-is-generic-errors.rs | 22 ++++++++++ .../pointee-tail-is-generic-errors.stderr | 40 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/test/ui/traits/pointee-tail-is-generic-errors.rs create mode 100644 src/test/ui/traits/pointee-tail-is-generic-errors.stderr diff --git a/src/test/ui/traits/pointee-tail-is-generic-errors.rs b/src/test/ui/traits/pointee-tail-is-generic-errors.rs new file mode 100644 index 0000000000000..d081721aca275 --- /dev/null +++ b/src/test/ui/traits/pointee-tail-is-generic-errors.rs @@ -0,0 +1,22 @@ +// edition:2018 + +#![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] + +type Opaque = impl std::fmt::Debug + ?Sized; + +fn opaque() -> &'static Opaque { + &[1] as &[i32] +} + +fn a() { + is_thin::(); + //~^ ERROR type mismatch resolving `::Metadata == ()` + + is_thin::(); + //~^ ERROR type mismatch resolving `::Metadata == ()` +} + +fn is_thin + ?Sized>() {} + +fn main() {} diff --git a/src/test/ui/traits/pointee-tail-is-generic-errors.stderr b/src/test/ui/traits/pointee-tail-is-generic-errors.stderr new file mode 100644 index 0000000000000..fa5fe67e53cb6 --- /dev/null +++ b/src/test/ui/traits/pointee-tail-is-generic-errors.stderr @@ -0,0 +1,40 @@ +error[E0271]: type mismatch resolving `::Metadata == ()` + --> $DIR/pointee-tail-is-generic-errors.rs:13:5 + | +LL | is_thin::(); + | ^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Metadata` + = help: consider constraining the associated type `::Metadata` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `is_thin` + --> $DIR/pointee-tail-is-generic-errors.rs:20:33 + | +LL | fn is_thin + ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `is_thin` + +error[E0271]: type mismatch resolving `::Metadata == ()` + --> $DIR/pointee-tail-is-generic-errors.rs:16:5 + | +LL | type Opaque = impl std::fmt::Debug + ?Sized; + | ----------------------------- the found opaque type +... +LL | is_thin::(); + | ^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Metadata` +note: required by a bound in `is_thin` + --> $DIR/pointee-tail-is-generic-errors.rs:20:33 + | +LL | fn is_thin + ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `is_thin` +help: consider constraining the associated type `::Metadata` to `()` + | +LL | type Opaque = impl std::fmt::Debug + ?Sized; + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. From 47f3f66240eb20da1cd7583115a6ea1a2d25e388 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 5 Mar 2022 21:54:49 +0100 Subject: [PATCH 04/11] Update unstable `ExpectationId`s in stored diagnostics --- compiler/rustc_errors/src/diagnostic.rs | 25 ++++++++++++++++++++- compiler/rustc_errors/src/lib.rs | 29 +++++++++++++++---------- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a59d91ea78900..aa9c7829d8e72 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -5,7 +5,8 @@ use crate::Substitution; use crate::SubstitutionPart; use crate::SuggestionStyle; use crate::ToolMetadata; -use rustc_lint_defs::Applicability; +use rustc_data_structures::stable_map::FxHashMap; +use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_serialize::json::Json; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; @@ -137,6 +138,28 @@ impl Diagnostic { } } + pub fn update_unstable_expectation_id( + &mut self, + unstable_to_stable: &FxHashMap, + ) { + if let Level::Expect(expectation_id) = &mut self.level { + if expectation_id.is_stable() { + return; + } + + // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index. + // The lint index inside the attribute is manually transferred here. + let lint_index = expectation_id.get_lint_index(); + expectation_id.set_lint_index(None); + let mut stable_id = *unstable_to_stable + .get(&expectation_id) + .expect("each unstable `LintExpectationId` must have a matching stable id"); + + stable_id.set_lint_index(lint_index); + *expectation_id = stable_id; + } + } + pub fn has_future_breakage(&self) -> bool { match self.code { Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 217d3ec2c247a..cba06448c4a6e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -522,6 +522,11 @@ impl Drop for HandlerInner { "no warnings or errors encountered even though `delayed_good_path_bugs` issued", ); } + + assert!( + self.unstable_expect_diagnostics.is_empty(), + "all diagnostics with unstable expectations should have been converted", + ); } } @@ -942,25 +947,25 @@ impl Handler { let mut inner = self.inner.borrow_mut(); for mut diag in diags.into_iter() { - let mut unstable_id = diag + diag.update_unstable_expectation_id(unstable_to_stable); + + let stable_id = diag .level .get_expectation_id() .expect("all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`"); - - // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index. - // The lint index inside the attribute is manually transferred here. - let lint_index = unstable_id.get_lint_index(); - unstable_id.set_lint_index(None); - let mut stable_id = *unstable_to_stable - .get(&unstable_id) - .expect("each unstable `LintExpectationId` must have a matching stable id"); - - stable_id.set_lint_index(lint_index); - diag.level = Level::Expect(stable_id); inner.fulfilled_expectations.insert(stable_id); (*TRACK_DIAGNOSTICS)(&diag); } + + inner + .stashed_diagnostics + .values_mut() + .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); + inner + .future_breakage_diagnostics + .iter_mut() + .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); } /// This methods steals all [`LintExpectationId`]s that are stored inside From 165b5583e56ad6d54922a7b5117a37c2ca2c89a1 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sun, 6 Mar 2022 11:47:08 +0100 Subject: [PATCH 05/11] Fix typos in `LintExpectationId` docs --- compiler/rustc_lint_defs/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c78428765bb89..af41e9c06d933 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -54,7 +54,7 @@ pub enum Applicability { /// Expected `Diagnostic`s get the lint level `Expect` which stores the `LintExpectationId` /// to match it with the actual expectation later on. /// -/// The `LintExpectationId` has to be has stable between compilations, as diagnostic +/// The `LintExpectationId` has to be stable between compilations, as diagnostic /// instances might be loaded from cache. Lint messages can be emitted during an /// `EarlyLintPass` operating on the AST and during a `LateLintPass` traversing the /// HIR tree. The AST doesn't have enough information to create a stable id. The @@ -71,7 +71,7 @@ pub enum Applicability { #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, Encodable, Decodable)] pub enum LintExpectationId { /// Used for lints emitted during the `EarlyLintPass`. This id is not - /// has stable and should not be cached. + /// hash stable and should not be cached. Unstable { attr_id: AttrId, lint_index: Option }, /// The [`HirId`] that the lint expectation is attached to. This id is /// stable and can be cached. The additional index ensures that nodes with @@ -113,7 +113,9 @@ impl HashStable for LintExpectationId { lint_index.hash_stable(hcx, hasher); } _ => { - unreachable!("HashStable should only be called for a filled `LintExpectationId`") + unreachable!( + "HashStable should only be called for filled and stable `LintExpectationId`" + ) } } } From d39d60971bafe34f626585e4887e7eec726fe972 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sun, 6 Mar 2022 14:18:28 +0100 Subject: [PATCH 06/11] Handle `#[expect(unfulfilled_lint_expectations)]` with a lint message --- compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_lint/src/expect.rs | 9 +++-- compiler/rustc_lint/src/levels.rs | 34 ++++++++++++---- compiler/rustc_middle/src/lint.rs | 12 +++++- .../expect_unfulfilled_expectation.rs | 39 +++++++++++++++++++ .../expect_unfulfilled_expectation.stderr | 38 ++++++++++++++++++ 6 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs create mode 100644 src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index cba06448c4a6e..5ba1fe9b4786f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -970,6 +970,7 @@ impl Handler { /// This methods steals all [`LintExpectationId`]s that are stored inside /// [`HandlerInner`] and indicate that the linked expectation has been fulfilled. + #[must_use] pub fn steal_fulfilled_expectation_ids(&self) -> FxHashSet { assert!( self.inner.borrow().unstable_expect_diagnostics.is_empty(), diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index e6c9d0b0ab000..74fef0be9e98c 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -30,10 +30,6 @@ fn emit_unfulfilled_expectation_lint( hir_id: HirId, expectation: &LintExpectation, ) { - // FIXME: The current implementation doesn't cover cases where the - // `unfulfilled_lint_expectations` is actually expected by another lint - // expectation. This can be added here by checking the lint level and - // retrieving the `LintExpectationId` if it was expected. tcx.struct_span_lint_hir( builtin::UNFULFILLED_LINT_EXPECTATIONS, hir_id, @@ -43,6 +39,11 @@ fn emit_unfulfilled_expectation_lint( if let Some(rationale) = expectation.reason { diag.note(&rationale.as_str()); } + + if expectation.is_unfulfilled_lint_expectations { + diag.note("the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message"); + } + diag.emit(); }, ); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index f46f74fa45fb0..468aacc9bcaaa 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -14,7 +14,7 @@ use rustc_middle::lint::{ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::lint::{ - builtin::{self, FORBIDDEN_LINT_GROUPS}, + builtin::{self, FORBIDDEN_LINT_GROUPS, UNFULFILLED_LINT_EXPECTATIONS}, Level, Lint, LintExpectationId, LintId, }; use rustc_session::parse::feature_err; @@ -212,6 +212,14 @@ impl<'s> LintLevelsBuilder<'s> { } } } + + // The lint `unfulfilled_lint_expectations` can't be expected, as it would suppress itself. + // Handling expectations of this lint would add additional complexity with little to no + // benefit. The expect level for this lint will therefore be ignored. + if let Level::Expect(_) = level && id == LintId::of(UNFULFILLED_LINT_EXPECTATIONS) { + return; + } + if let Level::ForceWarn = old_level { specs.insert(id, (old_level, old_src)); } else { @@ -344,6 +352,20 @@ impl<'s> LintLevelsBuilder<'s> { self.store.check_lint_name(&name, tool_name, self.registered_tools); match &lint_result { CheckLintNameResult::Ok(ids) => { + // This checks for instances where the user writes `#[expect(unfulfilled_lint_expectations)]` + // in that case we want to avoid overriding the lint level but instead add an expectation that + // can't be fulfilled. The lint message will include an explanation, that the + // `unfulfilled_lint_expectations` lint can't be expected. + if let Level::Expect(expect_id) = level { + let is_unfulfilled_lint_expectations = match ids { + [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), + _ => false, + }; + self.lint_expectations.push(( + expect_id, + LintExpectation::new(reason, sp, is_unfulfilled_lint_expectations), + )); + } let src = LintLevelSource::Node( meta_item.path.segments.last().expect("empty lint name").ident.name, sp, @@ -353,10 +375,6 @@ impl<'s> LintLevelsBuilder<'s> { self.check_gated_lint(id, attr.span); self.insert_spec(&mut specs, id, (level, src)); } - if let Level::Expect(expect_id) = level { - self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp))); - } } CheckLintNameResult::Tool(result) => { @@ -374,7 +392,7 @@ impl<'s> LintLevelsBuilder<'s> { } if let Level::Expect(expect_id) = level { self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp))); + .push((expect_id, LintExpectation::new(reason, sp, false))); } } Err((Some(ids), ref new_lint_name)) => { @@ -414,7 +432,7 @@ impl<'s> LintLevelsBuilder<'s> { } if let Level::Expect(expect_id) = level { self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp))); + .push((expect_id, LintExpectation::new(reason, sp, false))); } } Err((None, _)) => { @@ -511,7 +529,7 @@ impl<'s> LintLevelsBuilder<'s> { } if let Level::Expect(expect_id) = level { self.lint_expectations - .push((expect_id, LintExpectation::new(reason, sp))); + .push((expect_id, LintExpectation::new(reason, sp, false))); } } else { panic!("renamed lint does not exist: {}", new_name); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 894947fa70d96..1b301629b9c73 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -204,11 +204,19 @@ pub struct LintExpectation { pub reason: Option, /// The [`Span`] of the attribute that this expectation originated from. pub emission_span: Span, + /// Lint messages for the `unfulfilled_lint_expectations` lint will be + /// adjusted to include an additional note. Therefore, we have to track if + /// the expectation is for the lint. + pub is_unfulfilled_lint_expectations: bool, } impl LintExpectation { - pub fn new(reason: Option, attr_span: Span) -> Self { - Self { reason, emission_span: attr_span } + pub fn new( + reason: Option, + emission_span: Span, + is_unfulfilled_lint_expectations: bool, + ) -> Self { + Self { reason, emission_span, is_unfulfilled_lint_expectations } } } diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs new file mode 100644 index 0000000000000..d38e65533869a --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs @@ -0,0 +1,39 @@ +// check-pass +// ignore-tidy-linelength + +#![feature(lint_reasons)] +#![warn(unused_mut)] + +#![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] +//~^ WARNING this lint expectation is unfulfilled +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| NOTE idk why you would expect this +//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +#[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] +//~^ WARNING this lint expectation is unfulfilled +//~| NOTE a local: idk why you would expect this +//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message +pub fn normal_test_fn() { + #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + //~^ WARNING this lint expectation is unfulfilled + //~| NOTE this expectation will create a diagnostic with the default lint level + let mut v = vec![1, 1, 2, 3, 5]; + v.sort(); + + // Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly + #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + //~^ WARNING this lint expectation is unfulfilled + //~| NOTE the expectation for `unused` should be fulfilled + //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + let value = "I'm unused"; +} + +#[expect(warnings, reason = "this suppresses all warnings and also suppresses itself. No warning will be issued")] +pub fn expect_warnings() { + // This lint trigger will be suppressed + #[warn(unused_mut)] + let mut v = vec![1, 1, 2, 3, 5]; +} + +fn main() {} diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr new file mode 100644 index 0000000000000..9bfee79b03d70 --- /dev/null +++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr @@ -0,0 +1,38 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:7:11 + | +LL | #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + = note: idk why you would expect this + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:13:10 + | +LL | #[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a local: idk why you would expect this + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:18:14 + | +LL | #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + | ^^^^^^^^^^ + | + = note: this expectation will create a diagnostic with the default lint level + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:25:22 + | +LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the expectation for `unused` should be fulfilled + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: 4 warnings emitted + From be84049570d5be6d6e76e471ef88a11ae46292ad Mon Sep 17 00:00:00 2001 From: xFrednet Date: Wed, 9 Mar 2022 21:58:13 +0100 Subject: [PATCH 07/11] Add comment about `unfulfilled_lint_expectation` not being in a group (RFC 2383) --- compiler/rustc_lint/src/levels.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 468aacc9bcaaa..99bbe01566a94 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -357,6 +357,8 @@ impl<'s> LintLevelsBuilder<'s> { // can't be fulfilled. The lint message will include an explanation, that the // `unfulfilled_lint_expectations` lint can't be expected. if let Level::Expect(expect_id) = level { + // The `unfulfilled_lint_expectations` lint is not part of any lint groups. Therefore. we + // only need to check the slice if it contains a single lint. let is_unfulfilled_lint_expectations = match ids { [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), _ => false, From 39961390ad7b99f5f63d47144c03a7ef7f406483 Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Thu, 10 Mar 2022 17:50:46 +0000 Subject: [PATCH 08/11] Tie `fp` and `neon` --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 17 ++++++++++++++--- src/test/run-make-fulldeps/simd-ffi/Makefile | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 4b324740a1f83..3ce594b945ac1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -188,8 +188,6 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2] ("x86", "avx512gfni") => smallvec!["gfni"], ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"], ("aarch64", "fp") => smallvec!["fp-armv8"], - ("aarch64", "fp16") => smallvec!["fullfp16"], - ("aarch64", "fhm") => smallvec!["fp16fml"], ("aarch64", "rcpc2") => smallvec!["rcpc-immo"], ("aarch64", "dpb") => smallvec!["ccpp"], ("aarch64", "dpb2") => smallvec!["ccdp"], @@ -198,6 +196,19 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2] ("aarch64", "pmuv3") => smallvec!["perfmon"], ("aarch64", "paca") => smallvec!["pauth"], ("aarch64", "pacg") => smallvec!["pauth"], + // Rust ties fp and neon together. In LLVM neon implicitly enables fp, + // but we manually enable neon when a feature only implicitly enables fp + ("aarch64", "f32mm") => smallvec!["f32mm", "neon"], + ("aarch64", "f64mm") => smallvec!["f64mm", "neon"], + ("aarch64", "fhm") => smallvec!["fp16fml", "neon"], + ("aarch64", "fp16") => smallvec!["fullfp16", "neon"], + ("aarch64", "jsconv") => smallvec!["jsconv", "neon"], + ("aarch64", "sve") => smallvec!["sve", "neon"], + ("aarch64", "sve2") => smallvec!["sve2", "neon"], + ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"], + ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"], + ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"], + ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"], (_, s) => smallvec![s], } } @@ -490,7 +501,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec::new(); } - // ... otherwise though we run through `to_llvm_feature when + // ... otherwise though we run through `to_llvm_features` when // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. diff --git a/src/test/run-make-fulldeps/simd-ffi/Makefile b/src/test/run-make-fulldeps/simd-ffi/Makefile index e9c974a013732..38f2fcd18c5e4 100644 --- a/src/test/run-make-fulldeps/simd-ffi/Makefile +++ b/src/test/run-make-fulldeps/simd-ffi/Makefile @@ -41,7 +41,7 @@ define MK_TARGETS # now. $(1): simd.rs $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \ - -C target-feature='+neon,+sse2' -C extra-filename=-$(1) + -C target-feature='+fp,+neon,+sse2' -C extra-filename=-$(1) endef $(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx)))) From 5a5621791f3fc6e27c692747ddd37672f83c7360 Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Thu, 10 Feb 2022 16:43:45 +0000 Subject: [PATCH 09/11] Stabilise `aarch64_target_feature` --- .../rustc_codegen_ssa/src/target_features.rs | 109 +++++++++--------- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_typeck/src/collect.rs | 2 +- library/core/src/lib.rs | 2 +- src/test/ui/target-feature/gate.rs | 2 +- src/test/ui/target-feature/tied-features.rs | 2 +- 8 files changed, 64 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index df011d6ca5fab..f37c675138177 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -44,105 +44,108 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ // FEAT_AdvSimd - ("neon", Some(sym::aarch64_target_feature)), + ("neon", None), // FEAT_FP - ("fp", Some(sym::aarch64_target_feature)), + ("fp", None), // FEAT_FP16 - ("fp16", Some(sym::aarch64_target_feature)), + ("fp16", None), // FEAT_SVE - ("sve", Some(sym::aarch64_target_feature)), + ("sve", None), // FEAT_CRC - ("crc", Some(sym::aarch64_target_feature)), + ("crc", None), // FEAT_RAS - ("ras", Some(sym::aarch64_target_feature)), + ("ras", None), // FEAT_LSE - ("lse", Some(sym::aarch64_target_feature)), + ("lse", None), // FEAT_RDM - ("rdm", Some(sym::aarch64_target_feature)), + ("rdm", None), // FEAT_RCPC - ("rcpc", Some(sym::aarch64_target_feature)), + ("rcpc", None), // FEAT_RCPC2 - ("rcpc2", Some(sym::aarch64_target_feature)), + ("rcpc2", None), // FEAT_DotProd - ("dotprod", Some(sym::aarch64_target_feature)), + ("dotprod", None), // FEAT_TME - ("tme", Some(sym::aarch64_target_feature)), + ("tme", None), // FEAT_FHM - ("fhm", Some(sym::aarch64_target_feature)), + ("fhm", None), // FEAT_DIT - ("dit", Some(sym::aarch64_target_feature)), + ("dit", None), // FEAT_FLAGM - ("flagm", Some(sym::aarch64_target_feature)), + ("flagm", None), // FEAT_SSBS - ("ssbs", Some(sym::aarch64_target_feature)), + ("ssbs", None), // FEAT_SB - ("sb", Some(sym::aarch64_target_feature)), + ("sb", None), // FEAT_PAUTH (address authentication) - ("paca", Some(sym::aarch64_target_feature)), + ("paca", None), // FEAT_PAUTH (generic authentication) - ("pacg", Some(sym::aarch64_target_feature)), + ("pacg", None), // FEAT_DPB - ("dpb", Some(sym::aarch64_target_feature)), + ("dpb", None), // FEAT_DPB2 - ("dpb2", Some(sym::aarch64_target_feature)), + ("dpb2", None), // FEAT_SVE2 - ("sve2", Some(sym::aarch64_target_feature)), + ("sve2", None), // FEAT_SVE2_AES - ("sve2-aes", Some(sym::aarch64_target_feature)), + ("sve2-aes", None), // FEAT_SVE2_SM4 - ("sve2-sm4", Some(sym::aarch64_target_feature)), + ("sve2-sm4", None), // FEAT_SVE2_SHA3 - ("sve2-sha3", Some(sym::aarch64_target_feature)), + ("sve2-sha3", None), // FEAT_SVE2_BitPerm - ("sve2-bitperm", Some(sym::aarch64_target_feature)), + ("sve2-bitperm", None), // FEAT_FRINTTS - ("frintts", Some(sym::aarch64_target_feature)), + ("frintts", None), // FEAT_I8MM - ("i8mm", Some(sym::aarch64_target_feature)), + ("i8mm", None), // FEAT_F32MM - ("f32mm", Some(sym::aarch64_target_feature)), + ("f32mm", None), // FEAT_F64MM - ("f64mm", Some(sym::aarch64_target_feature)), + ("f64mm", None), // FEAT_BF16 - ("bf16", Some(sym::aarch64_target_feature)), + ("bf16", None), // FEAT_RAND - ("rand", Some(sym::aarch64_target_feature)), + ("rand", None), // FEAT_BTI - ("bti", Some(sym::aarch64_target_feature)), + ("bti", None), // FEAT_MTE - ("mte", Some(sym::aarch64_target_feature)), + ("mte", None), // FEAT_JSCVT - ("jsconv", Some(sym::aarch64_target_feature)), + ("jsconv", None), // FEAT_FCMA - ("fcma", Some(sym::aarch64_target_feature)), + ("fcma", None), // FEAT_AES - ("aes", Some(sym::aarch64_target_feature)), + ("aes", None), // FEAT_SHA1 & FEAT_SHA256 - ("sha2", Some(sym::aarch64_target_feature)), + ("sha2", None), // FEAT_SHA512 & FEAT_SHA3 - ("sha3", Some(sym::aarch64_target_feature)), + ("sha3", None), // FEAT_SM3 & FEAT_SM4 - ("sm4", Some(sym::aarch64_target_feature)), + ("sm4", None), // FEAT_PAN - ("pan", Some(sym::aarch64_target_feature)), + ("pan", None), // FEAT_LOR - ("lor", Some(sym::aarch64_target_feature)), + ("lor", None), // FEAT_VHE - ("vh", Some(sym::aarch64_target_feature)), + ("vh", None), // FEAT_PMUv3 - ("pmuv3", Some(sym::aarch64_target_feature)), + ("pmuv3", None), // FEAT_SPE - ("spe", Some(sym::aarch64_target_feature)), - ("v8.1a", Some(sym::aarch64_target_feature)), - ("v8.2a", Some(sym::aarch64_target_feature)), - ("v8.3a", Some(sym::aarch64_target_feature)), - ("v8.4a", Some(sym::aarch64_target_feature)), - ("v8.5a", Some(sym::aarch64_target_feature)), - ("v8.6a", Some(sym::aarch64_target_feature)), - ("v8.7a", Some(sym::aarch64_target_feature)), + ("spe", None), + ("v8.1a", Some(sym::aarch64_ver_target_feature)), + ("v8.2a", Some(sym::aarch64_ver_target_feature)), + ("v8.3a", Some(sym::aarch64_ver_target_feature)), + ("v8.4a", Some(sym::aarch64_ver_target_feature)), + ("v8.5a", Some(sym::aarch64_ver_target_feature)), + ("v8.6a", Some(sym::aarch64_ver_target_feature)), + ("v8.7a", Some(sym::aarch64_ver_target_feature)), ]; -const AARCH64_TIED_FEATURES: &[&[&str]] = &[&["paca", "pacg"]]; +const AARCH64_TIED_FEATURES: &[&[&str]] = &[ + &["fp", "neon"], // Silicon always has both, so avoid needless complications + &["paca", "pacg"], // Together these represent `pauth` in LLVM +]; const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("adx", Some(sym::adx_target_feature)), diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index fc2ac75d60967..e49f40ff1a184 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -46,6 +46,8 @@ declare_features! ( // feature-group-start: accepted features // ------------------------------------------------------------------------- + /// Allows `#[target_feature(...)]` on aarch64 platforms + (accepted, aarch64_target_feature, "1.61.0", Some(44839), None), /// Allows the sysV64 ABI to be specified on all platforms /// instead of just the platforms on which it is the C ABI. (accepted, abi_sysv64, "1.24.0", Some(36167), None), diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1899e837eeabe..0f9127c453727 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -241,7 +241,7 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. - (active, aarch64_target_feature, "1.27.0", Some(44839), None), + (active, aarch64_ver_target_feature, "1.27.0", Some(44839), None), (active, adx_target_feature, "1.32.0", Some(44839), None), (active, arm_target_feature, "1.27.0", Some(44839), None), (active, avx512_target_feature, "1.27.0", Some(44839), None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6b5dcacd12bd3..c603f21de9948 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -278,6 +278,7 @@ symbols! { _task_context, a32, aarch64_target_feature, + aarch64_ver_target_feature, abi, abi_amdgpu_kernel, abi_avr_interrupt, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 8229f4a80e10c..d5c6ceb48c25e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2680,7 +2680,6 @@ fn from_target_feature( // Only allow features whose feature gates have been enabled. let allowed = match feature_gate.as_ref().copied() { Some(sym::arm_target_feature) => rust_features.arm_target_feature, - Some(sym::aarch64_target_feature) => rust_features.aarch64_target_feature, Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature, Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature, Some(sym::mips_target_feature) => rust_features.mips_target_feature, @@ -2696,6 +2695,7 @@ fn from_target_feature( Some(sym::f16c_target_feature) => rust_features.f16c_target_feature, Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature, Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, + Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 97add8f2c6a74..1f10e0e2792f4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -206,7 +206,7 @@ #![feature(asm_const)] // // Target features: -#![feature(aarch64_target_feature)] +#![cfg_attr(bootstrap, feature(aarch64_target_feature))] #![feature(adx_target_feature)] #![feature(arm_target_feature)] #![feature(avx512_target_feature)] diff --git a/src/test/ui/target-feature/gate.rs b/src/test/ui/target-feature/gate.rs index 7cdf404242d5e..2382c98f8f128 100644 --- a/src/test/ui/target-feature/gate.rs +++ b/src/test/ui/target-feature/gate.rs @@ -16,7 +16,6 @@ // gate-test-avx512_target_feature // gate-test-tbm_target_feature // gate-test-arm_target_feature -// gate-test-aarch64_target_feature // gate-test-hexagon_target_feature // gate-test-mips_target_feature // gate-test-wasm_target_feature @@ -28,6 +27,7 @@ // gate-test-riscv_target_feature // gate-test-ermsb_target_feature // gate-test-bpf_target_feature +// gate-test-aarch64_ver_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/src/test/ui/target-feature/tied-features.rs b/src/test/ui/target-feature/tied-features.rs index 01353e9f70c59..048777cb3ba26 100644 --- a/src/test/ui/target-feature/tied-features.rs +++ b/src/test/ui/target-feature/tied-features.rs @@ -1,7 +1,7 @@ // build-fail // compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu // needs-llvm-components: aarch64 -#![feature(aarch64_target_feature, target_feature_11)] +#![cfg_attr(bootstrap, feature(aarch64_target_feature))] #![feature(no_core, lang_items)] #![no_core] From 5d333c155e01e303da1e1b5704a0d4d6032c92a6 Mon Sep 17 00:00:00 2001 From: Caio Date: Mon, 14 Mar 2022 08:29:20 -0300 Subject: [PATCH 10/11] Fix remaining meta-variable expression TODOs --- compiler/rustc_expand/src/mbe/macro_check.rs | 8 ++++++-- compiler/rustc_expand/src/mbe/macro_parser.rs | 7 +++++-- compiler/rustc_expand/src/mbe/metavar_expr.rs | 6 +++--- compiler/rustc_expand/src/mbe/transcribe.rs | 4 ++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 88e1169322093..f18cf95a2bf11 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -337,8 +337,12 @@ fn check_occurrences( let name = MacroRulesNormalizedIdent::new(name); check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name); } - // FIXME(c410-f3r) Check token (https://github.com/rust-lang/rust/issues/93902) - TokenTree::MetaVarExpr(..) => {} + TokenTree::MetaVarExpr(dl, ref mve) => { + let Some(name) = mve.ident().map(MacroRulesNormalizedIdent::new) else { + return; + }; + check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name); + } TokenTree::Delimited(_, ref del) => { check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid); } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index dedfd779bb416..07081c75d46f0 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -324,8 +324,11 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize { TokenTree::Delimited(_, ref delim) => count_names(&delim.tts), TokenTree::MetaVar(..) => 0, TokenTree::MetaVarDecl(..) => 1, - // FIXME(c410-f3r) MetaVarExpr should be handled instead of being ignored - // https://github.com/rust-lang/rust/issues/9390 + // Panicking here would abort execution because `parse_tree` makes use of this + // function. In other words, RHS meta-variable expressions eventually end-up here. + // + // `0` is still returned to inform that no meta-variable was found. `Meta-variables + // != Meta-variable expressions` TokenTree::MetaVarExpr(..) => 0, TokenTree::Sequence(_, ref seq) => seq.num_captures, TokenTree::Token(..) => 0, diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 6c5a755da6f40..2949ca716b230 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -62,9 +62,9 @@ impl MetaVarExpr { Ok(rslt) } - crate fn ident(&self) -> Option<&Ident> { - match self { - MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(&ident), + crate fn ident(&self) -> Option { + match *self { + MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident), MetaVarExpr::Index(..) | MetaVarExpr::Length(..) => None, } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 387d5895e24d7..5ec63739cf574 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -399,7 +399,7 @@ fn lockstep_iter_size( TokenTree::MetaVarExpr(_, ref expr) => { let default_rslt = LockstepIterSize::Unconstrained; let Some(ident) = expr.ident() else { return default_rslt; }; - let name = MacroRulesNormalizedIdent::new(ident.clone()); + let name = MacroRulesNormalizedIdent::new(ident); match lookup_cur_matched(name, interpolations, repeats) { Some(MatchedSeq(ref ads)) => { default_rslt.with(LockstepIterSize::Constraint(ads.len(), name)) @@ -479,7 +479,7 @@ fn count_repetitions<'a>( count(cx, 0, depth_opt, matched, sp) } -/// Returns a `NamedMatch` item declared on the RHS given an arbitrary [Ident] +/// Returns a `NamedMatch` item declared on the LHS given an arbitrary [Ident] fn matched_from_ident<'ctx, 'interp, 'rslt>( cx: &ExtCtxt<'ctx>, ident: Ident, From 7d42b9dba6aba35548453908d30270104e47fbee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Mar 2022 09:52:47 -0400 Subject: [PATCH 11/11] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index a12a48bf723e0..7bc0c98621762 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit a12a48bf723e0e13f043979a7f79861d975e7187 +Subproject commit 7bc0c986217629e6c831edcb133532023a5aec63