diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index aee5afdfd3b04..af412ef525c95 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -365,7 +365,7 @@ pub trait Emitter { let Some(source_map) = self.source_map() else { return }; let should_hide = |span| { source_map.is_imported(span) || { - let expn = span.data().ctxt.outer_expn_data(); + let expn = span.ctxt().outer_expn_data(); expn.diagnostic_opaque && matches!(expn.kind, ExpnKind::Macro(MacroKind::Bang, _)) } }; diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index e2dca4b988a47..c17faea67b94e 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -527,24 +527,24 @@ impl server::Server for Rustc<'_, '_> { .map_err(|_| String::from("failed to parse to literal"))? .map_err(cancel_diags_into_string)?; - let first_span = parser.token.span.data(); + let (first_span_lo, first_span_hi) = parser.token.span.lo_hi(); let minus_present = parser.eat(exp!(Minus)); - let lit_span = parser.token.span.data(); + let (lit_span_lo, lit_span_hi) = parser.token.span.lo_hi(); let tk::Literal(mut lit) = parser.token.kind else { return Err("not a literal".to_string()); }; // Check no comment or whitespace surrounding the (possibly negative) // literal, or more tokens after it. - if (lit_span.hi.0 - first_span.lo.0) as usize != s.len() { + if (lit_span_hi.0 - first_span_lo.0) as usize != s.len() { return Err("comment or whitespace around literal".to_string()); } if minus_present { // If minus is present, check no comment or whitespace in between it // and the literal token. - if first_span.hi.0 != lit_span.lo.0 { + if first_span_hi.0 != lit_span_lo.0 { return Err("comment or whitespace after minus".to_string()); } diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 8eabbc0dcb06f..0dfadda1f3958 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -171,7 +171,7 @@ impl<'tcx> InferCtxt<'tcx> { /// If possible, prefer the wrapper methods on `ObligationCtxt`, /// `FnCtxt`, or `TypeChecker`. pub fn sub_raw( - self, + &self, cause: &ObligationCause<'tcx>, param_env: ParamEnv<'tcx>, define_opaque_types: DefineOpaqueTypes, @@ -181,7 +181,20 @@ impl<'tcx> InferCtxt<'tcx> { where T: ToTrace<'tcx>, { - self.at(cause, param_env).sub(define_opaque_types, expected, actual) + if self.next_trait_solver { + NextSolverRelate::relate(self, param_env, expected, ty::Covariant, actual, cause.span) + .map(|goals| self.goals_to_obligations(cause, goals)) + } else { + let mut op = TypeRelating::new( + self, + ToTrace::to_trace(cause, expected, actual), + param_env, + define_opaque_types, + ty::Covariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } /// Makes `expected == actual`. @@ -288,41 +301,6 @@ pub trait ToTrace<'tcx>: Relate> + Copy { } impl<'a, 'tcx> At<'a, 'tcx> { - /// Makes `expected <: actual`. - /// - /// FIXME: To be removed in favor of the [`InferCtxt::sub_raw`] method instead. - pub fn sub( - self, - define_opaque_types: DefineOpaqueTypes, - expected: T, - actual: T, - ) -> InferResult<'tcx, ()> - where - T: ToTrace<'tcx>, - { - if self.infcx.next_trait_solver { - NextSolverRelate::relate( - self.infcx, - self.param_env, - expected, - ty::Covariant, - actual, - self.cause.span, - ) - .map(|goals| self.goals_to_obligations(goals)) - } else { - let mut op = TypeRelating::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - define_opaque_types, - ty::Covariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) - } - } - /// Makes `expected == actual`. /// /// FIXME: To be removed in favor of the [`InferCtxt::eq_raw`] method instead. @@ -391,7 +369,13 @@ impl<'a, 'tcx> At<'a, 'tcx> { T: ToTrace<'tcx>, { match variance { - ty::Covariant => self.sub(define_opaque_types, expected, actual), + ty::Covariant => self.infcx.sub_raw( + self.cause, + self.param_env, + define_opaque_types, + expected, + actual, + ), ty::Invariant => self.eq(define_opaque_types, expected, actual), ty::Contravariant => self.infcx.sup_raw( self.cause, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index d3ed447e5201f..09020656226e5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -883,7 +883,7 @@ impl<'tcx> InferCtxt<'tcx> { self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { if a_is_expected { - Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) + Ok(self.sub_raw(cause, param_env, DefineOpaqueTypes::Yes, a, b)) } else { Ok(self.sup_raw(cause, param_env, DefineOpaqueTypes::Yes, b, a)) } diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 648bccbb618bc..875631eef1f65 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -255,15 +255,30 @@ impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { // relates `v` to `a` first, which may help us to avoid unnecessary // type variable obligations. See caller for details. fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { - let at = self.infcx.at(&self.trace.cause, self.param_env); match self.kind { LatticeOpKind::Glb => { - self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, a)?.into_obligations()); - self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, b)?.into_obligations()); + self.obligations.extend( + self.infcx + .sub_raw(&self.trace.cause, self.param_env, DefineOpaqueTypes::Yes, v, a)? + .into_obligations(), + ); + self.obligations.extend( + self.infcx + .sub_raw(&self.trace.cause, self.param_env, DefineOpaqueTypes::Yes, v, b)? + .into_obligations(), + ); } LatticeOpKind::Lub => { - self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, a, v)?.into_obligations()); - self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, b, v)?.into_obligations()); + self.obligations.extend( + self.infcx + .sub_raw(&self.trace.cause, self.param_env, DefineOpaqueTypes::Yes, a, v)? + .into_obligations(), + ); + self.obligations.extend( + self.infcx + .sub_raw(&self.trace.cause, self.param_env, DefineOpaqueTypes::Yes, b, v)? + .into_obligations(), + ); } } Ok(()) diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 2b9170c80de21..9f1b08ce5b079 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -30,7 +30,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { if tracks_deps { let _span = icx.tcx.source_span(def_id); // Sanity check: relative span's parent must be an absolute span. - debug_assert_eq!(_span.data_untracked().parent, None); + debug_assert_eq!(_span.parent(), None); } } }) diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index c340d82d0a80b..61c2a3c337807 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -172,15 +172,9 @@ fn find_noop_landing_pads<'tcx>( // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. - let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); - for bb in postorder { - let is_nop_landing_pad = RemoveNoopLandingPads.is_nop_landing_pad( - tcx, - &body.basic_blocks[bb], - body, - &nop_landing_pads, - extra, - ); + for (bb, bb_data) in traversal::postorder(body) { + let is_nop_landing_pad = + RemoveNoopLandingPads.is_nop_landing_pad(tcx, bb_data, body, &nop_landing_pads, extra); if is_nop_landing_pad { nop_landing_pads.insert(bb); } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index 8a4d3fba99a39..84fb63d6311ac 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -7,7 +7,7 @@ use rustc_type_ir::outlives::{Component, push_outlives_components}; #[cfg(not(feature = "nightly"))] use rustc_type_ir::region_constraint::TransitiveRelationBuilder; use rustc_type_ir::region_constraint::{ - And, Assumptions, LeafRegionConstraint, Or, eagerly_handle_placeholders_in_universe, + And, Assumptions, LeafRegionConstraint, NoSpan, Or, eagerly_handle_placeholders_in_universe, }; use rustc_type_ir::{ AliasTy, Binder, ClauseKind, Const, InferCtxtLike, Interner, Region, TypeVisitable, @@ -168,9 +168,9 @@ where use Component::*; use LeafRegionConstraint::*; match c { - Region(c_r) => Or::new_leaf(RegionOutlives(*c_r, r, ())), + Region(c_r) => Or::new_leaf(RegionOutlives(*c_r, r, NoSpan)), Placeholder(p) => { - Or::new_leaf(PlaceholderTyOutlives(Ty::new_placeholder(self.cx(), *p), r, ())) + Or::new_leaf(PlaceholderTyOutlives(Ty::new_placeholder(self.cx(), *p), r, NoSpan)) } Alias(_, alias) => self.destructure_alias_outlives(*alias, r), UnresolvedInferenceVariable(_) => { @@ -194,11 +194,11 @@ where let item_bounds = rustc_type_ir::outlives::declared_bounds_from_definition(self.cx(), alias) - .map(|bound| And::new([RegionOutlives(bound, r, ())])); + .map(|bound| And::new([RegionOutlives(bound, r, NoSpan)])); let item_bound_outlives = Or::new(item_bounds); let where_clause_outlives = - Or::new_leaf(AliasTyOutlivesViaEnv(Binder::dummy((alias, r)), ())); + Or::new_leaf(AliasTyOutlivesViaEnv(Binder::dummy((alias, r)), NoSpan)); let mut components = Default::default(); rustc_type_ir::outlives::compute_alias_components_recursive( diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 3da905741c03b..d944ae765c4f4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -155,10 +155,12 @@ where let ty::OutlivesClause(a, b) = goal.predicate; if self.cx().assumptions_on_binders() { - use rustc_type_ir::region_constraint::{LeafRegionConstraint, RegionConstraint}; + use rustc_type_ir::region_constraint::{ + LeafRegionConstraint, NoSpan, RegionConstraint, + }; let constraint = - RegionConstraint::new_leaf(LeafRegionConstraint::RegionOutlives(a, b, ())); + RegionConstraint::new_leaf(LeafRegionConstraint::RegionOutlives(a, b, NoSpan)); self.register_solver_region_constraint(constraint); } else { self.register_region_outlives(a, b, VisibleForLeakCheck::Yes); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f4cda91af4556..6c6d0efa0487c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2370,7 +2370,7 @@ impl<'a> Parser<'a> { let move_kw_span = self.prev_token.span; // Check for `move async` and recover if self.check_keyword(exp!(Async)) { - let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); + let move_async_span = self.token.span.with_lo(self.prev_token.span.lo()); Err(self.dcx().create_err(crate::diagnostics::AsyncMoveOrderIncorrect { span: move_async_span, })) @@ -2382,7 +2382,7 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::ergonomic_clones, use_kw_span); // Check for `use async` and recover if self.check_keyword(exp!(Async)) { - let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); + let use_async_span = self.token.span.with_lo(self.prev_token.span.lo()); Err(self.dcx().create_err(crate::diagnostics::AsyncUseOrderIncorrect { span: use_async_span, })) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2011f8646346e..45bae73deda8d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -109,7 +109,7 @@ impl<'a> Parser<'a> { } } - let inject_use_span = post_attr_lo.data().with_hi(post_attr_lo.lo()); + let inject_use_span = post_attr_lo.with_hi(post_attr_lo.lo()); let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span }; Ok((attrs, items, mod_spans)) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7a7078deaadc4..58d6b8005c787 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1745,7 +1745,7 @@ impl<'tcx> Resolver<'_, 'tcx> { } // A relative span's parent must be an absolute span. - debug_assert_eq!(span.data_untracked().parent, None); + debug_assert_eq!(span.parent(), None); let _id = self.tcx.untracked().source_span.push(span); debug_assert_eq!(_id, def_id); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 914cb6f02b577..1e6f938ad2820 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -733,12 +733,6 @@ impl SpanData { } } -impl Default for SpanData { - fn default() -> Self { - Self { lo: BytePos(0), hi: BytePos(0), ctxt: SyntaxContext::root(), parent: None } - } -} - impl Span { #[inline] pub fn lo(self) -> BytePos { @@ -1279,7 +1273,7 @@ impl Span { // Don't return something if it's marked with `#[diagnostic::opaque]`. // This already accounts for `-Zmacro-backtrace`. - if within.data().ctxt.outer_expn_data().diagnostic_opaque { + if within.ctxt().outer_expn_data().diagnostic_opaque { return None; } @@ -1420,9 +1414,9 @@ pub trait SpanEncoder: Encoder { impl SpanEncoder for FileEncoder<'_> { fn encode_span(&mut self, span: Span) { - let span = span.data(); - span.lo.encode(self); - span.hi.encode(self); + let (lo, hi) = span.lo_hi(); + lo.encode(self); + hi.encode(self); } fn encode_symbol(&mut self, sym: Symbol) { @@ -1457,9 +1451,9 @@ impl SpanEncoder for FileEncoder<'_> { impl SpanEncoder for MemEncoder { fn encode_span(&mut self, span: Span) { - let span = span.data(); - span.lo.encode(self); - span.hi.encode(self); + let (lo, hi) = span.lo_hi(); + lo.encode(self); + hi.encode(self); } fn encode_symbol(&mut self, sym: Symbol) { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f394765ab9f8e..caad0da329261 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -943,8 +943,7 @@ impl SourceMap { /// Returns a new span representing just the first character of the given span. pub fn start_point(&self, sp: Span) -> Span { let width = { - let sp = sp.data(); - let local_begin = self.lookup_byte_offset(sp.lo); + let local_begin = self.lookup_byte_offset(sp.lo()); let start_index = local_begin.pos.to_usize(); let src = local_begin.sf.external_src.read(); diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 8f57c3c222d6a..a2afa9faea97f 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -255,8 +255,7 @@ where actual: T, ) -> Result<(), TypeError<'tcx>> { self.infcx - .at(cause, param_env) - .sub(DefineOpaqueTypes::Yes, expected, actual) + .sub_raw(cause, param_env, DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 096f43f81e608..2fdbdec7ceb81 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -75,6 +75,7 @@ TrivialTypeTraversalImpls! { crate::UintTy, crate::UniverseIndex, crate::Variance, + crate::region_constraint::NoSpan, crate::solve::BuiltinImplSource, crate::solve::Certainty, crate::solve::GoalSource, diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 445d9b09ba04d..890a1ddaead78 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -168,10 +168,28 @@ impl Assumptions { } } +/// The span stored in a [`RegionConstraint`] and friends. +/// +/// Constraints are created with spans during type checking, but are also stored +/// without any span, e.g. in query responses, in which case [`NoSpan`] is used. +/// This trait exists so that code which is generic over the span only needs a +/// single bound instead of repeating all of the supertrait bounds. +pub trait ConstraintSpan: Clone + std::fmt::Debug + Eq + std::hash::Hash {} + +/// Placeholder for constraints which do not carry a span, see [`ConstraintSpan`]. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)] +#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] +pub struct NoSpan; + +impl ConstraintSpan for NoSpan {} + +#[cfg(feature = "nightly")] +impl ConstraintSpan for rustc_span::Span {} + #[derive_where(Clone, Hash, PartialEq, Eq; I: Interner, S)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] -pub enum LeafRegionConstraint { +pub enum LeafRegionConstraint { Ambiguity(S), RegionOutlives(Region, Region, S), /// Requirement that a (potentially higher ranked) alias outlives some (potentially higher ranked) @@ -224,32 +242,31 @@ impl std::fmt::Debug for LeafRegionConstraint { } impl LeafRegionConstraint { - pub fn with_span( - self, - span: S, - ) -> LeafRegionConstraint { + pub fn with_span(self, span: S) -> LeafRegionConstraint { use LeafRegionConstraint::*; match self { - Ambiguity(()) => Ambiguity(span), - RegionOutlives(r1, r2, ()) => RegionOutlives(r1, r2, span), - AliasTyOutlivesViaEnv(bound_outlives, ()) => { + Ambiguity(NoSpan) => Ambiguity(span), + RegionOutlives(r1, r2, NoSpan) => RegionOutlives(r1, r2, span), + AliasTyOutlivesViaEnv(bound_outlives, NoSpan) => { AliasTyOutlivesViaEnv(bound_outlives, span) } - PlaceholderTyOutlives(ty, r, ()) => PlaceholderTyOutlives(ty, r, span), + PlaceholderTyOutlives(ty, r, NoSpan) => PlaceholderTyOutlives(ty, r, span), } } } -impl LeafRegionConstraint { +impl LeafRegionConstraint { pub fn without_span(self) -> LeafRegionConstraint { use LeafRegionConstraint::*; match self { - Ambiguity(_) => Ambiguity(()), - RegionOutlives(r1, r2, _) => RegionOutlives(r1, r2, ()), - AliasTyOutlivesViaEnv(bound_outlives, _) => AliasTyOutlivesViaEnv(bound_outlives, ()), - PlaceholderTyOutlives(ty, r, _) => PlaceholderTyOutlives(ty, r, ()), + Ambiguity(_) => Ambiguity(NoSpan), + RegionOutlives(r1, r2, _) => RegionOutlives(r1, r2, NoSpan), + AliasTyOutlivesViaEnv(bound_outlives, _) => { + AliasTyOutlivesViaEnv(bound_outlives, NoSpan) + } + PlaceholderTyOutlives(ty, r, _) => PlaceholderTyOutlives(ty, r, NoSpan), } } @@ -277,16 +294,13 @@ impl LeafRegionC /// than proving the subset, so it can never be the candidate which makes the OR hold. E.g. /// `OR(AND('a: 'b), AND('a: 'b, 'b: 'c))` really ought to just be `OR(AND('a: 'b))`. Only keeping /// an empty AND is the degenerate case of that rule. -pub struct Or(pub SmallVec<[And; 1]>); +pub struct Or(pub SmallVec<[And; 1]>); impl Or { - pub fn with_spans( - self, - span: S, - ) -> Or { + pub fn with_spans(self, span: S) -> Or { Or(self.0.into_iter().map(|and| and.with_spans(span.clone())).collect()) } } -impl Or { +impl Or { pub fn new_true() -> Self { Self(SmallVec::from_buf([And::new_true()])) } @@ -385,18 +399,15 @@ impl std::fmt::Debug for Or { /// An AND of leaf constraints. Always in "canonical form", meaning: /// - No leaf constraints are present twice in this AND /// - No leaf constraint is trivially true, i.e. a reflexive `'a: 'a` -pub struct And( +pub struct And( pub SmallVec<[LeafRegionConstraint; 1]>, ); impl And { - pub fn with_spans( - self, - span: S, - ) -> And { + pub fn with_spans(self, span: S) -> And { And(self.0.into_iter().map(|leaf| leaf.with_span(span.clone())).collect()) } } -impl And { +impl And { pub fn new_true() -> Self { Self(SmallVec::new()) } @@ -466,23 +477,20 @@ impl std::fmt::Debug for And { /// /// This should be thought of as an AND consisting of a set of LEAF constraints as well /// as a single OR constraint. -pub struct RegionConstraint { +pub struct RegionConstraint { pub and_constraint: And, pub or_constraint: Or, } impl RegionConstraint { - pub fn with_spans( - self, - span: S, - ) -> RegionConstraint { + pub fn with_spans(self, span: S) -> RegionConstraint { RegionConstraint { and_constraint: self.and_constraint.with_spans(span.clone()), or_constraint: self.or_constraint.with_spans(span.clone()), } } } -impl RegionConstraint { +impl RegionConstraint { pub fn new_from_or(or: Or) -> Self { let Some(fst) = or.0.get(0).clone() else { return RegionConstraint::new_false(); @@ -666,10 +674,10 @@ fn compute_new_region_constraints, I: Interne and: &And| { for c in &and.0 { match c { - Ambiguity(()) | PlaceholderTyOutlives(..) | AliasTyOutlivesViaEnv(..) => { + Ambiguity(NoSpan) | PlaceholderTyOutlives(..) | AliasTyOutlivesViaEnv(..) => { constraints.push(c.clone()) } - RegionOutlives(r1, r2, ()) => { + RegionOutlives(r1, r2, NoSpan) => { regions.insert(*r1); regions.insert(*r2); builder.add(*r2, *r1); @@ -711,7 +719,7 @@ fn compute_new_region_constraints, I: Interne }; if is_placeholder_like(r) && is_placeholder_like(ub) { - constraints.push(RegionOutlives(ub, r, ())); + constraints.push(RegionOutlives(ub, r, NoSpan)); } } } @@ -770,11 +778,11 @@ fn pull_region_outlives_constraints_out_of_universe< let mut pulled_constraints = Vec::new(); for c in and.0 { match c { - Ambiguity(()) | PlaceholderTyOutlives(..) | AliasTyOutlivesViaEnv(..) => { + Ambiguity(NoSpan) | PlaceholderTyOutlives(..) | AliasTyOutlivesViaEnv(..) => { assert!(max_universe(infcx, c.clone()) < u); pulled_constraints.push(Or::new_leaf(c.clone())); } - RegionOutlives(region_1, region_2, ()) => { + RegionOutlives(region_1, region_2, NoSpan) => { let region_1_u = max_universe(infcx, region_1); let region_2_u = max_universe(infcx, region_2); @@ -805,7 +813,7 @@ fn pull_region_outlives_constraints_out_of_universe< // As long as any region outlived by `region_1` outlives any region region which // `region_2` outlives, we know that `region_1: region_2` holds. In other words, // there exists some set of 4 regions for which `'r1: 'i1` `'i1: 'i2` `'i2: 'r2` - candidates.push(RegionOutlives(ub, lb, ())); + candidates.push(RegionOutlives(ub, lb, NoSpan)); } } @@ -834,7 +842,7 @@ fn pull_region_outlives_constraints_out_of_universe< pub fn destructure_type_outlives_constraints_in_root< Infcx: InferCtxtLike, I: Interner, - S: Clone + std::fmt::Debug + Eq + std::hash::Hash, + S: ConstraintSpan, >( infcx: &Infcx, constraint: RegionConstraint, @@ -920,11 +928,13 @@ fn rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling< let mut rewritten_constraints = Vec::new(); for c in and.0 { match c { - Ambiguity(()) | RegionOutlives(..) => rewritten_constraints.push(Or::new_leaf(c)), - PlaceholderTyOutlives(ty, region, ()) => { + Ambiguity(NoSpan) | RegionOutlives(..) => { + rewritten_constraints.push(Or::new_leaf(c)) + } + PlaceholderTyOutlives(ty, region, NoSpan) => { rewritten_constraints.push(rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder_handling(infcx, ty, region, u, assumptions)); } - AliasTyOutlivesViaEnv(bound_outlives, ()) => { + AliasTyOutlivesViaEnv(bound_outlives, NoSpan) => { rewritten_constraints.push(rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handling(infcx, bound_outlives, u, assumptions)); } } @@ -959,7 +969,7 @@ fn rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder let region_u = max_universe(infcx, region); if region_u != u && ty_u != u { - return Or::new_leaf(PlaceholderTyOutlives(ty, region, ())); + return Or::new_leaf(PlaceholderTyOutlives(ty, region, NoSpan)); } let mut candidates = vec![]; @@ -968,7 +978,7 @@ fn rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder // smaller universe candidates.extend( regions_outlived_by_placeholder(ty, assumptions, infcx.cx()) - .map(move |assumption_r| RegionOutlives(assumption_r, region, ())), + .map(move |assumption_r| RegionOutlives(assumption_r, region, NoSpan)), ); // We can express `!T: 'region` as `!T: 'r` where `'r: 'region`. This is only necessary @@ -978,7 +988,7 @@ fn rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder candidates.extend( regions_outliving::(region, assumptions, infcx.cx()) .filter(|r| max_universe(infcx, *r) < u) - .map(|r| PlaceholderTyOutlives(ty, r, ())), + .map(|r| PlaceholderTyOutlives(ty, r, NoSpan)), ); } @@ -998,7 +1008,7 @@ fn rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handl use LeafRegionConstraint::*; if max_universe(infcx, bound_outlives) != u { - return Or::new_leaf(AliasTyOutlivesViaEnv(bound_outlives, ())); + return Or::new_leaf(AliasTyOutlivesViaEnv(bound_outlives, NoSpan)); } let mut candidates = Vec::new(); @@ -1040,11 +1050,11 @@ fn rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handl // a placeholder type in `u`, so this type-outlives constraint cannot be // handled by the region-outlives-only eager placeholder machinery. if max_universe(infcx, bound_outlives) == u { - return Or::new_ambig(()); + return Or::new_ambig(NoSpan); } debug!("higher ranked candidate: {bound_outlives:?}"); - Or::new_leaf(AliasTyOutlivesViaEnv(bound_outlives, ())) + Or::new_leaf(AliasTyOutlivesViaEnv(bound_outlives, NoSpan)) }; // We elaborate something like `Alias<'a_u2>: 'b_u2` into alias outlives involving each @@ -1076,7 +1086,7 @@ fn rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handl // let's be conservative and not let alias outlives' cause NoSolution // in coherence match infcx.typing_mode_raw() { - TypingMode::Coherence => candidates.push(Or::new_ambig(())), + TypingMode::Coherence => candidates.push(Or::new_ambig(NoSpan)), TypingMode::Typeck { .. } | TypingMode::Reflection | TypingMode::ErasedNotCoherence { .. } @@ -1211,7 +1221,7 @@ fn alias_outlives_candidates_from_assumptions let mut relation = HigherRankedAliasMatcher { infcx, - region_constraints: vec![LeafRegionConstraint::RegionOutlives(r2, r, ())], + region_constraints: vec![LeafRegionConstraint::RegionOutlives(r2, r, NoSpan)], }; // FIXME(#155345): Both sides should be rigid in the future. @@ -1283,8 +1293,8 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> TypeRelation fn regions(&mut self, a: Region, b: Region) -> RelateResult> { if a != b { - self.region_constraints.push(LeafRegionConstraint::RegionOutlives(a, b, ())); - self.region_constraints.push(LeafRegionConstraint::RegionOutlives(b, a, ())); + self.region_constraints.push(LeafRegionConstraint::RegionOutlives(a, b, NoSpan)); + self.region_constraints.push(LeafRegionConstraint::RegionOutlives(b, a, NoSpan)); } Ok(a) } diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 9db72db606779..35ef6166fd8c6 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -81,7 +81,7 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result { // This is safe because the call will succeed only if buf_len >= required length. // Also, on success, the `buf_len` is updated with the size of bufferv (in bytes) written - unsafe { buf.set_len(num_of_handles) }; + unsafe { buf.set_len(buf_len / size_of::()) }; Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect()) } Err(e) => Err(e), diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs index 8c233a0d2024e..2c7b5882f234b 100644 --- a/library/std/src/sys/process/uefi.rs +++ b/library/std/src/sys/process/uefi.rs @@ -195,9 +195,9 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec, Vec } } - let stat = cmd.start_image()?; + let stat = cmd.start_image(); - // Rollback any env changes + // Rollback any env changes, even if the image failed to start if let Some(e) = env { for (k, (v, _)) in e { match v { @@ -207,6 +207,8 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec, Vec } } + let stat = stat?; + let stdout = cmd.stdout()?; let stderr = cmd.stderr()?; diff --git a/library/std/src/sys/thread_local/guard/key.rs b/library/std/src/sys/thread_local/guard/key.rs index 1d4e4c76a47a8..d9666cb08a05e 100644 --- a/library/std/src/sys/thread_local/guard/key.rs +++ b/library/std/src/sys/thread_local/guard/key.rs @@ -1,6 +1,6 @@ -//! A lot of UNIX platforms don't have a specialized way to register TLS -//! destructors for native TLS. Instead, we use one TLS key with a destructor -//! that will run all native TLS destructors in the destructor list. +//! A lot of UNIX platforms don't have a specialized way to register TLS destructors for native TLS +//! (i.e., `#[thread_local] static`). Instead, we use one TLS key with a destructor that will run +//! all native TLS destructors in the destructor list. It also runs `rt::thread_cleanup`. #[cfg(target_thread_local)] pub fn enable() { @@ -18,12 +18,13 @@ pub fn enable() { unsafe extern "C" fn run(_: *mut u8) { unsafe { + // Rust thread-local destructors should run *before* `rt::thread_cleanup`. destructors::run(); - // On platforms with `__cxa_thread_atexit_impl`, `destructors::run` - // does nothing on newer systems as the TLS destructors are - // registered with the system. But because all of those platforms - // call the destructors of TLS keys after the registered ones, this - // function will still be run last (at the time of writing). + // On platforms with `__cxa_thread_atexit_impl`, `destructors::run` does nothing as the + // TLS destructors are registered with the system. But because all of those platforms + // call the destructors of TLS keys *after* the registered "atexit" ones, this function + // will still be run last (at the time of writing). The `thread_current_in_dtor` test + // confirms this. crate::rt::thread_cleanup(); } } @@ -42,9 +43,10 @@ mod key_based { static CLEANUP: LazyKey = LazyKey::new(Some(run)); - /// On platforms with key-based TLS, the system runs the destructors for us. - /// We still have to make sure that [`crate::rt::thread_cleanup`] is called, - /// however. This is done by deferring the execution of a TLS destructor to + /// On platforms with key-based TLS, the system runs the destructors for us, so we don't have to + /// call `destructors::run`. We still have to make sure that [`crate::rt::thread_cleanup`] is + /// called, however. And we should make sure that it is called *last*, after dropping all + /// regular Rust thread-locals. This is done by deferring the execution of a TLS destructor to /// the next round of destruction inside the TLS destructors. pub fn enable() { unsafe { set(CLEANUP.force(), DEFER) } diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs index 4deea3e1b786b..8d35bc8e632fa 100644 --- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs @@ -9,7 +9,7 @@ use rustc_ast::{AssocItemKind, AttrKind, AttrStyle, Attribute, Crate, Item, Item use rustc_errors::{Applicability, Diag, SuggestionStyle}; use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext as _, impl_lint_pass}; -use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw, sym}; +use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, Symbol, kw, sym}; declare_clippy_lint! { /// ### What it does @@ -244,7 +244,7 @@ impl Stop { } fn from_attr(cx: &EarlyContext<'_>, attr: &Attribute) -> Option { - let SpanData { lo, hi, .. } = attr.span.data(); + let (lo, hi) = attr.span.lo_hi(); let file = cx.sess().source_map().lookup_source_file(lo); Some(Self { diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 994d4e8937273..71456bfdd941c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -1252,8 +1252,8 @@ fn walk_intra_arm_text( mut f: impl FnMut(&str), ) -> bool { if let Some(src) = match_sp.get_source_range(cx) - && let scrutinee_sp = scrutinee_sp.source_callsite().data() - && let block_start = (scrutinee_sp.hi.0 - src.sf.start_pos.0) as usize + && let scrutinee_sp_hi = scrutinee_sp.source_callsite().hi() + && let block_start = (scrutinee_sp_hi.0 - src.sf.start_pos.0) as usize && let Some(src_text) = src.sf.src.as_ref().map(|x| &***x) && let Some(block_text) = src_text.get(block_start..src.range.end) && let Some(stripped_text) = block_text.trim_start_matches(is_whitespace).strip_prefix('{') @@ -1263,8 +1263,8 @@ fn walk_intra_arm_text( .strip_suffix('}') .map(|s| src.range.end - (stripped_text.len() - s.len())) && let Some(range) = arms.iter().try_fold(arms_start..arms_end, |range, arm| { - let arm_sp: rustc_span::SpanData = arm.span.source_callsite().data(); - let arm_range = (arm_sp.lo.0 - src.sf.start_pos.0) as usize..(arm_sp.hi.0 - src.sf.start_pos.0) as usize; + let (arm_sp_lo, arm_sp_hi) = arm.span.source_callsite().lo_hi(); + let arm_range = (arm_sp_lo.0 - src.sf.start_pos.0) as usize..(arm_sp_hi.0 - src.sf.start_pos.0) as usize; if range.start <= arm_range.start && arm_range.end <= range.end && let Some(src) = src_text.get(range.start..arm_range.start) diff --git a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs index 1ee87f3f4f2fa..3dc578b7aaada 100644 --- a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs +++ b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs @@ -55,7 +55,9 @@ fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) { } if let ExprKind::Lit(literal) = e.kind // the indicator that parenthesis surround the literal is that the span of the expression and the literal differ - && (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo) + && let (literal_span_lo, literal_span_hi) = literal.span.lo_hi() + && let (e_span_lo, e_span_hi) = e.span.lo_hi() + && literal_span_hi - literal_span_lo != e_span_hi - e_span_lo // inspect the source code of the expression for parenthesis && snippet_enclosed_in_parenthesis(&snippet(cx, e.span, "")) { diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs index f5e07cc5c1d88..277ec25137b13 100644 --- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs @@ -109,9 +109,10 @@ impl FormatArgsCollector { .explicit_args() .iter() .try_fold(src.range.end, |start, arg| { - let expr_sp = walk_span_to_context(arg.expr.span, fmt_sp.ctxt)?.data(); - let expr_start = (expr_sp.lo.0 - src.sf.start_pos.0) as usize; - let expr_end = (expr_sp.hi.0 - src.sf.start_pos.0) as usize; + let (expr_sp_lo, expr_sp_hi) = + walk_span_to_context(arg.expr.span, fmt_sp.ctxt)?.lo_hi(); + let expr_start = (expr_sp_lo.0 - src.sf.start_pos.0) as usize; + let expr_end = (expr_sp_hi.0 - src.sf.start_pos.0) as usize; let mut tks = tokenize(src_text.get(start..expr_start)?, FrontmatterAllowed::No) .map(|x| x.kind) .filter(|x| { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 3075589deb803..8957968e9decb 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -425,26 +425,26 @@ impl HirEqInterExpr<'_, '_, '_> { let Some(rstmt_span) = walk_span_to_context(right.span, rspan.ctxt) else { return false; }; - let lstmt_span = lstmt_span.data(); - let rstmt_span = rstmt_span.data(); + let (lstmt_span_lo, lstmt_span_hi) = lstmt_span.lo_hi(); + let (rstmt_span_lo, rstmt_span_hi) = rstmt_span.lo_hi(); - if lstmt_span.lo < lstart && rstmt_span.lo < rstart { + if lstmt_span_lo < lstart && rstmt_span_lo < rstart { // Can happen when macros expand to multiple statements, or rearrange statements. // Nothing in between the statements to check in this case. continue; } - if lstmt_span.lo < lstart || rstmt_span.lo < rstart { + if lstmt_span_lo < lstart || rstmt_span_lo < rstart { // Only one of the blocks had a weird macro. return false; } - if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| { + if !eq_span_tokens(self.inner.cx, lstart..lstmt_span_lo, rstart..rstmt_span_lo, |t| { !matches!(t, Whitespace | Semi) }) { return false; } - lstart = lstmt_span.hi; - rstart = rstmt_span.hi; + lstart = lstmt_span_hi; + rstart = rstmt_span_hi; } let (lend, rend) = match (left.expr, right.expr) { diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 80c38904ea54a..69d679bba09b6 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -63,8 +63,8 @@ pub trait SpanRange: Sized { } impl SpanRange for Span { fn into_range(self) -> Range { - let data = self.data(); - data.lo..data.hi + let (lo, hi) = self.lo_hi(); + lo..hi } } impl SpanRange for SpanData { diff --git a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml b/src/tools/rust-analyzer/.github/workflows/update-generated.yml similarity index 76% rename from src/tools/rust-analyzer/.github/workflows/gen-lints.yml rename to src/tools/rust-analyzer/.github/workflows/update-generated.yml index 4fd7bb6200622..611d7d40bc6a2 100644 --- a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml +++ b/src/tools/rust-analyzer/.github/workflows/update-generated.yml @@ -1,4 +1,4 @@ -name: Generate lints and feature flags +name: Update generated code on: workflow_dispatch: @@ -26,6 +26,9 @@ jobs: - name: Generate lints/feature flags run: cargo codegen lint-definitions + - name: Generate target feature implications + run: cargo codegen target-features + - uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0 id: app-token with: @@ -36,10 +39,10 @@ jobs: uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: token: ${{ steps.app-token.outputs.token }} - commit-message: "internal: update generated lints" - branch: "ci/gen-lints" + commit-message: "internal: update generated lints and target features" + branch: "ci/gen-sync" delete-branch: true sign-commits: true - title: "Update generated lints" - body: "Weekly lint updates for `crates/ide-db/src/generated/lints.rs`." + title: "Update generated lints and target features" + body: "Weekly lint updates for `crates/ide-db/src/generated/lints.rs` and `crates/hir-ty/src/generated/target_features.rs`." labels: "A-infra" diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index aaf1c30505ac8..89c76b20feee3 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -873,7 +873,6 @@ dependencies = [ "tracing", "triomphe", "tt", - "unicode-ident", ] [[package]] @@ -2649,25 +2648,25 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smol_str" version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" dependencies = [ - "arbitrary", "borsh", - "criterion", - "proptest", - "rand", - "serde", "serde_core", - "serde_json", ] [[package]] name = "smol_str" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" +version = "0.3.7" dependencies = [ + "arbitrary", "borsh", + "criterion", + "proptest", + "rand", + "serde", "serde_core", + "serde_json", ] [[package]] @@ -2759,11 +2758,12 @@ dependencies = [ "rustc-literal-escaper", "rustc_apfloat", "smallvec", - "smol_str 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smol_str 0.3.6", "stdx", "test-utils", "tracing", "triomphe", + "unicode-ident", ] [[package]] diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index eb2d47b7b8261..eb1e774b8f41b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -9,9 +9,6 @@ edition.workspace = true license.workspace = true rust-version.workspace = true -[package.metadata.cargo-machete] -ignored = ["unicode-ident"] - [lib] doctest = false @@ -47,10 +44,6 @@ span.workspace = true thin-vec.workspace = true syntax-bridge.workspace = true -# This is a transitive dep, but we need to specify this -# for the workspace-wide pinning -unicode-ident.workspace = true - [dev-dependencies] expect-test.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index 0a2d0bf12e7d4..fee7275b06311 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -1737,9 +1737,6 @@ macro_rules! m { ($k:expr) => { fn f() { K::$k; } } } /* parse error: expected identifier, `self`, `super`, `crate`, or `Self` */ -/* parse error: expected SEMICOLON */ -/* parse error: expected SEMICOLON */ -/* parse error: expected expression, item or let statement */ fn f() { K::(C("0")); } @@ -1754,32 +1751,30 @@ fn f() { // BLOCK_EXPR@5..19 // STMT_LIST@5..19 // L_CURLY@5..6 "{" -// EXPR_STMT@6..10 -// PATH_EXPR@6..10 -// PATH@6..10 -// PATH@6..7 -// PATH_SEGMENT@6..7 -// NAME_REF@6..7 -// IDENT@6..7 "K" -// COLON2@7..9 "::" -// PATH_SEGMENT@9..10 -// ERROR@9..10 -// L_PAREN@9..10 "(" -// EXPR_STMT@10..16 -// CALL_EXPR@10..16 -// PATH_EXPR@10..11 -// PATH@10..11 -// PATH_SEGMENT@10..11 -// NAME_REF@10..11 -// IDENT@10..11 "C" -// ARG_LIST@11..16 -// L_PAREN@11..12 "(" -// LITERAL@12..15 -// STRING@12..15 "\"0\"" -// R_PAREN@15..16 ")" -// ERROR@16..17 -// R_PAREN@16..17 ")" -// SEMICOLON@17..18 ";" +// EXPR_STMT@6..18 +// CALL_EXPR@6..17 +// PATH_EXPR@6..9 +// PATH@6..9 +// PATH@6..7 +// PATH_SEGMENT@6..7 +// NAME_REF@6..7 +// IDENT@6..7 "K" +// COLON2@7..9 "::" +// ARG_LIST@9..17 +// L_PAREN@9..10 "(" +// CALL_EXPR@10..16 +// PATH_EXPR@10..11 +// PATH@10..11 +// PATH_SEGMENT@10..11 +// NAME_REF@10..11 +// IDENT@10..11 "C" +// ARG_LIST@11..16 +// L_PAREN@11..12 "(" +// LITERAL@12..15 +// STRING@12..15 "\"0\"" +// R_PAREN@15..16 ")" +// R_PAREN@16..17 ")" +// SEMICOLON@17..18 ";" // R_CURLY@18..19 "}" "#]], diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index 24617c512966d..96d9404250030 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -868,7 +868,7 @@ impl<'db> InferenceContext<'db> { expected, ); if !(ty.is_numeric() || ty.is_char() || ty.references_error()) { - // FIXME: Emit an error. + self.push_diagnostic(InferenceDiagnostic::InvalidRangePatType { pat }); return self.types.types.error; } ty diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs index 92ffa472548da..8206a1f8c436c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs @@ -9,6 +9,9 @@ use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; use crate::db::HirDatabase; +use generated::TARGET_FEATURE_IMPLICATIONS_RAW; + +mod generated; #[derive(Debug, Default, Clone)] pub struct TargetFeatures<'db> { @@ -68,988 +71,3 @@ static TARGET_FEATURE_IMPLICATIONS: LazyLock>> = result.shrink_to_fit(); result }); - -#[expect(dead_code, reason = "stubs for rustc_target")] -enum Stability { - Stable, - Unstable(()), - InternalOnly { reason: &'static str, hard_error: bool }, -} -use Stability::*; - -type ImpliedFeatures = &'static [&'static str]; - -// spellchecker:off - -#[expect(non_upper_case_globals, reason = "stubs for rustc_target")] -mod sym { - // ARM - pub(super) const arm_target_feature: () = (); - // AArch64 - pub(super) const aarch64_unstable_target_feature: () = (); - pub(super) const aarch64_ver_target_feature: () = (); - // x86 - pub(super) const x86_amx_intrinsics: () = (); - pub(super) const apx_target_feature: () = (); - pub(super) const avx10_target_feature: () = (); - pub(super) const clflushopt_target_feature: () = (); - pub(super) const fma4_target_feature: () = (); - pub(super) const ermsb_target_feature: () = (); - pub(super) const lahfsahf_target_feature: () = (); - pub(super) const movrs_target_feature: () = (); - pub(super) const prfchw_target_feature: () = (); - pub(super) const rtm_target_feature: () = (); - pub(super) const x87_target_feature: () = (); - pub(super) const xop_target_feature: () = (); - pub(super) const movdir64b_target_feature: () = (); - pub(super) const movdiri_target_feature: () = (); - // Hexagon - pub(super) const hexagon_target_feature: () = (); - // PowerPC - pub(super) const powerpc_target_feature: () = (); - // MIPS - pub(super) const mips_target_feature: () = (); - // NVPTX - pub(super) const nvptx_target_feature: () = (); - // RISC-V - pub(super) const riscv_target_feature: () = (); - // WASM - pub(super) const wasm_target_feature: () = (); - // BPF - pub(super) const bpf_target_feature: () = (); - // CSKY - pub(super) const csky_target_feature: () = (); - // LoongArch - pub(super) const loongarch_target_feature: () = (); - // s390x - pub(super) const s390x_target_feature: () = (); - // SPARC - pub(super) const sparc_target_feature: () = (); - // m68k - pub(super) const m68k_target_feature: () = (); - // AVR - pub(super) const avr_target_feature: () = (); - // Xtensa - pub(super) const xtensa_target_feature: () = (); -} - -// The following code is copied verbatim from compiler/rustc_target/src/target_features.rs. - -static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("aclass", Unstable(sym::arm_target_feature), &[]), - ("acquire-release", Unstable(sym::arm_target_feature), &[]), - ("aes", Unstable(sym::arm_target_feature), &["neon"]), - ( - "atomics-32", - // Not implied by any CPU model or other feature. - Stability::InternalOnly { - reason: "unsound because it changes the ABI of atomic operations", - hard_error: false, - }, - &[], - ), - ("crc", Unstable(sym::arm_target_feature), &[]), - ("d32", Unstable(sym::arm_target_feature), &[]), - ("dotprod", Unstable(sym::arm_target_feature), &["neon"]), - ("dsp", Unstable(sym::arm_target_feature), &[]), - ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]), - ("fp16", Unstable(sym::arm_target_feature), &["neon"]), - ("fp64", Unstable(sym::arm_target_feature), &[]), - ("fpregs", Unstable(sym::arm_target_feature), &[]), - ("i8mm", Unstable(sym::arm_target_feature), &["neon"]), - ("mclass", Unstable(sym::arm_target_feature), &[]), - ("mve", Unstable(sym::arm_target_feature), &["v8.1m.main", "dsp", "fpregs"]), - ("mve.fp", Unstable(sym::arm_target_feature), &["mve"]), - ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), - ("rclass", Unstable(sym::arm_target_feature), &[]), - ("sha2", Unstable(sym::arm_target_feature), &["neon"]), - // This can be *disabled* on non-`hf` targets to enable the use - // of hardfloats while keeping the softfloat ABI. - // FIXME before stabilization: Should we expose this as a `hard-float` target feature instead of - // matching the odd negative feature LLVM uses? - ("soft-float", Unstable(sym::arm_target_feature), &[]), - // This is needed for inline assembly, but shouldn't be stabilized as-is - // since it should be enabled per-function using #[instruction_set], not - // #[target_feature]. - ("thumb-mode", Unstable(sym::arm_target_feature), &[]), - ("thumb2", Unstable(sym::arm_target_feature), &[]), - ("trustzone", Unstable(sym::arm_target_feature), &[]), - ("v5te", Unstable(sym::arm_target_feature), &[]), - ("v6", Unstable(sym::arm_target_feature), &["v5te"]), - ("v6k", Unstable(sym::arm_target_feature), &["v6"]), - ("v6m", Unstable(sym::arm_target_feature), &["v6"]), - ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "v8m", "thumb2"]), - ("v7", Unstable(sym::arm_target_feature), &["v6t2"]), - ("v8", Unstable(sym::arm_target_feature), &["v7", "acquire-release"]), - ("v8.1m.main", Unstable(sym::arm_target_feature), &["v8m.main"]), - ("v8m", Unstable(sym::arm_target_feature), &["v6m"]), - ("v8m.main", Unstable(sym::arm_target_feature), &["v7"]), - ("vfp2", Unstable(sym::arm_target_feature), &["vfp2sp", "fp64"]), - ("vfp2sp", Unstable(sym::arm_target_feature), &["fpregs"]), - ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]), - ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]), - ("virtualization", Unstable(sym::arm_target_feature), &[]), - // tidy-alphabetical-end -]; - -static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - // FEAT_AES & FEAT_PMULL - ("aes", Stable, &["neon"]), - // FEAT_BF16 - ("bf16", Stable, &[]), - // FEAT_BTI - ("bti", Stable, &[]), - // FEAT_CRC - ("crc", Stable, &[]), - // FEAT_CSSC - ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_DIT - ("dit", Stable, &[]), - // FEAT_DotProd - ("dotprod", Stable, &["neon"]), - // FEAT_DPB - ("dpb", Stable, &[]), - // FEAT_DPB2 - ("dpb2", Stable, &["dpb"]), - // FEAT_ECV - ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_F32MM - ("f32mm", Stable, &["sve"]), - // FEAT_F64MM - ("f64mm", Stable, &["sve"]), - // FEAT_FAMINMAX - ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_FCMA - ("fcma", Stable, &["neon"]), - // FEAT_FHM - ("fhm", Stable, &["fp16"]), - // FEAT_FLAGM - ("flagm", Stable, &[]), - // FEAT_FLAGM2 - ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), - // We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`. - ( - "fp-armv8", - // Pinned down by [`Target::abi_required_features`] when needed. - Stability::InternalOnly { reason: "Rust ties `fp-armv8` to `neon`", hard_error: false }, - &[], - ), - // FEAT_FP8 - ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), - // FEAT_FP8DOT2 - ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), - // FEAT_FP8DOT4 - ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), - // FEAT_FP8FMA - ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), - // FEAT_FP16 - // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 - ("fp16", Stable, &["neon"]), - // FEAT_FRINTTS - ("frintts", Stable, &[]), - // FEAT_HBC - ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_I8MM - ("i8mm", Stable, &[]), - // FEAT_JSCVT - // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 - ("jsconv", Stable, &["neon"]), - // FEAT_LOR - ("lor", Stable, &[]), - // FEAT_LSE - ("lse", Stable, &[]), - // FEAT_LSE2 - ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_LSE128 - ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), - // FEAT_LUT - ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_MOPS - ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_MTE & FEAT_MTE2 - ("mte", Stable, &[]), - // FEAT_AdvSimd & FEAT_FP - ("neon", Stable, &[]), - // Backend option to turn atomic operations into an intrinsic call when `lse` is not known to be - // available, so the intrinsic can do runtime LSE feature detection rather than unconditionally - // using slower non-LSE operations. Unstable since it doesn't need to user-togglable. - ("outline-atomics", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_PAUTH (address authentication) - ("paca", Stable, &[]), - // FEAT_PAUTH (generic authentication) - ("pacg", Stable, &[]), - // FEAT_PAN - ("pan", Stable, &[]), - // FEAT_PAuth_LR - ("pauth-lr", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_PMUv3 - ("pmuv3", Stable, &[]), - // FEAT_RNG - ("rand", Stable, &[]), - // FEAT_RAS & FEAT_RASv1p1 - ("ras", Stable, &[]), - // FEAT_LRCPC - ("rcpc", Stable, &[]), - // FEAT_LRCPC2 - ("rcpc2", Stable, &["rcpc"]), - // FEAT_LRCPC3 - ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), - // FEAT_RDM - ("rdm", Stable, &["neon"]), - ( - "reserve-x18", - // Not implied by any CPU model or other feature; the compiler flag is a target modifier. - InternalOnly { reason: "use `-Zfixed-x18` compiler flag instead", hard_error: false }, - &[], - ), - // FEAT_SB - ("sb", Stable, &[]), - // FEAT_SHA1 & FEAT_SHA256 - ("sha2", Stable, &["neon"]), - // FEAT_SHA512 & FEAT_SHA3 - ("sha3", Stable, &["sha2"]), - // FEAT_SM3 & FEAT_SM4 - ("sm4", Stable, &["neon"]), - // FEAT_SME - ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), - // FEAT_SME_B16B16 - ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), - // FEAT_SME_F8F16 - ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), - // FEAT_SME_F8F32 - ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), - // FEAT_SME_F16F16 - ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), - // FEAT_SME_F64F64 - ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), - // FEAT_SME_FA64 - ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), - // FEAT_SME_I16I64 - ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), - // FEAT_SME_LUTv2 - ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), - // FEAT_SME2 - ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), - // FEAT_SME2p1 - ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), - // FEAT_SPE - ("spe", Stable, &[]), - // FEAT_SSBS & FEAT_SSBS2 - ("ssbs", Stable, &[]), - // FEAT_SSVE_FP8FDOT2 - ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), - // FEAT_SSVE_FP8FDOT4 - ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), - // FEAT_SSVE_FP8FMA - ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), - // FEAT_SVE - // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 - // - // LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always - // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2 - // - // "For backwards compatibility, Neon and VFP are required in the latest architectures." - ("sve", Stable, &["neon", "fp16"]), - // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions) - ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), - // FEAT_SVE2 - ("sve2", Stable, &["sve"]), - // FEAT_SVE_AES & FEAT_SVE_PMULL128 - ("sve2-aes", Stable, &["sve2", "aes"]), - // FEAT_SVE2_BitPerm - ("sve2-bitperm", Stable, &["sve2"]), - // FEAT_SVE2_SHA3 - ("sve2-sha3", Stable, &["sve2", "sha3"]), - // FEAT_SVE2_SM4 - ("sve2-sm4", Stable, &["sve2", "sm4"]), - // FEAT_SVE2p1 - ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), - // FEAT_TME - ("tme", Stable, &[]), - ( - "v8.1a", - Unstable(sym::aarch64_ver_target_feature), - &["crc", "lse", "rdm", "pan", "lor", "vh"], - ), - ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]), - ( - "v8.3a", - Unstable(sym::aarch64_ver_target_feature), - &["v8.2a", "rcpc", "paca", "pacg", "jsconv"], - ), - ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), - ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), - ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), - ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), - ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), - ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), - ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), - ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), - ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), - ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), - ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), - ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a"]), - // FEAT_VHE - ("vh", Stable, &[]), - // FEAT_WFxT - ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), - // tidy-alphabetical-end -]; - -static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("adx", Stable, &[]), - ("aes", Stable, &["sse2"]), - ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), - ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]), - ("apxf", Unstable(sym::apx_target_feature), &[]), - ("avx", Stable, &["sse4.2"]), - ("avx2", Stable, &["avx"]), - ( - "avx10.1", - Unstable(sym::avx10_target_feature), - &[ - "avx512bf16", - "avx512bitalg", - "avx512bw", - "avx512cd", - "avx512dq", - "avx512f", - "avx512fp16", - "avx512ifma", - "avx512vbmi", - "avx512vbmi2", - "avx512vl", - "avx512vnni", - "avx512vpopcntdq", - ], - ), - ( - "avx10.2", - Unstable(sym::avx10_target_feature), - &["avx10.1", "avxvnni", "avxvnniint8", "avxvnniint16"], - ), - ("avx512bf16", Stable, &["avx512bw"]), - ("avx512bitalg", Stable, &["avx512bw"]), - ("avx512bw", Stable, &["avx512f"]), - ("avx512cd", Stable, &["avx512f"]), - ("avx512dq", Stable, &["avx512f"]), - ("avx512f", Stable, &["avx2", "fma", "f16c"]), - ("avx512fp16", Stable, &["avx512bw"]), - ("avx512ifma", Stable, &["avx512f"]), - ("avx512vbmi", Stable, &["avx512bw"]), - ("avx512vbmi2", Stable, &["avx512bw"]), - ("avx512vl", Stable, &["avx512f"]), - ("avx512vnni", Stable, &["avx512f"]), - ("avx512vp2intersect", Stable, &["avx512f"]), - ("avx512vpopcntdq", Stable, &["avx512f"]), - ("avxifma", Stable, &["avx2"]), - ("avxneconvert", Stable, &["avx2"]), - ("avxvnni", Stable, &["avx2"]), - ("avxvnniint8", Stable, &["avx2"]), - ("avxvnniint16", Stable, &["avx2"]), - ("bmi1", Stable, &[]), - ("bmi2", Stable, &[]), - ("clflushopt", Unstable(sym::clflushopt_target_feature), &[]), - ("cmpxchg16b", Stable, &[]), - ("ermsb", Unstable(sym::ermsb_target_feature), &[]), - ("f16c", Stable, &["avx"]), - ("fma", Stable, &["avx"]), - ("fma4", Unstable(sym::fma4_target_feature), &["avx", "sse4a"]), - ("fxsr", Stable, &[]), - ("gfni", Stable, &["sse2"]), - ("kl", Stable, &["sse2"]), - ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), - ("lzcnt", Stable, &[]), - ("movbe", Stable, &[]), - ("movdir64b", Unstable(sym::movdir64b_target_feature), &[]), - ("movdiri", Unstable(sym::movdiri_target_feature), &[]), - ("movrs", Unstable(sym::movrs_target_feature), &[]), - ("pclmulqdq", Stable, &["sse2"]), - ("popcnt", Stable, &[]), - ("prfchw", Unstable(sym::prfchw_target_feature), &[]), - ("rdrand", Stable, &[]), - ("rdseed", Stable, &[]), - ( - "retpoline-external-thunk", - // Not implied by any CPU model or other feature; the compiler flag is a target modifier. - Stability::InternalOnly { - reason: "use `-Zretpoline-external-thunk` compiler flag instead", - hard_error: false, - }, - &[], - ), - ( - "retpoline-indirect-branches", - // Not implied by any CPU model or other feature; the compiler flag is a target modifier. - Stability::InternalOnly { - reason: "use `-Zretpoline` compiler flag instead", - hard_error: false, - }, - &[], - ), - ( - "retpoline-indirect-calls", - // Not implied by any CPU model or other feature; the compiler flag is a target modifier. - Stability::InternalOnly { - reason: "use `-Zretpoline` compiler flag instead", - hard_error: false, - }, - &[], - ), - ("rtm", Unstable(sym::rtm_target_feature), &[]), - ("sha", Stable, &["sse2"]), - ("sha512", Stable, &["avx2"]), - ("sm3", Stable, &["avx"]), - ("sm4", Stable, &["avx2"]), - ( - "soft-float", - // Pinned down by [`Target::abi_required_features`]. - Stability::InternalOnly { reason: "use a soft-float target instead", hard_error: false }, - &[], - ), - ("sse", Stable, &[]), - ("sse2", Stable, &["sse"]), - ("sse3", Stable, &["sse2"]), - ("sse4.1", Stable, &["ssse3"]), - ("sse4.2", Stable, &["sse4.1"]), - ("sse4a", Stable, &["sse3"]), - ("ssse3", Stable, &["sse3"]), - ("tbm", Stable, &[]), - ("vaes", Stable, &["avx2", "aes"]), - ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]), - ("widekl", Stable, &["kl"]), - ("x87", Unstable(sym::x87_target_feature), &[]), - ("xop", Unstable(sym::xop_target_feature), &["fma4", "avx", "sse4a"]), - ("xsave", Stable, &[]), - ("xsavec", Stable, &["xsave"]), - ("xsaveopt", Stable, &["xsave"]), - ("xsaves", Stable, &["xsave"]), - // tidy-alphabetical-end -]; - -const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("audio", Unstable(sym::hexagon_target_feature), &[]), - ("hvx", Unstable(sym::hexagon_target_feature), &[]), - ("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]), - ("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]), - ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]), - ("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]), - ("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]), - ("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]), - ("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]), - ("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]), - ("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]), - ("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]), - ("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]), - ("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]), - ("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]), - ("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]), - ("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]), - ("v60", Unstable(sym::hexagon_target_feature), &[]), - ("v62", Unstable(sym::hexagon_target_feature), &["v60"]), - ("v65", Unstable(sym::hexagon_target_feature), &["v62"]), - ("v66", Unstable(sym::hexagon_target_feature), &["v65"]), - ("v67", Unstable(sym::hexagon_target_feature), &["v66"]), - ("v68", Unstable(sym::hexagon_target_feature), &["v67"]), - ("v69", Unstable(sym::hexagon_target_feature), &["v68"]), - ("v71", Unstable(sym::hexagon_target_feature), &["v69"]), - ("v73", Unstable(sym::hexagon_target_feature), &["v71"]), - ("v75", Unstable(sym::hexagon_target_feature), &["v73"]), - ("v79", Unstable(sym::hexagon_target_feature), &["v75"]), - ("zreg", Unstable(sym::hexagon_target_feature), &[]), - // tidy-alphabetical-end -]; - -static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // If you are thinking of adding "efpu2" here, please double-check that it really does not - // affect the ABI. - // tidy-alphabetical-start - ("altivec", Unstable(sym::powerpc_target_feature), &[]), - ( - "hard-float", - // Pinned down by [`Target::abi_required_features`]. - InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, - &[], - ), - ("msync", Unstable(sym::powerpc_target_feature), &[]), - ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]), - ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]), - ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]), - ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]), - ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]), - ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]), - ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]), - ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]), - ( - "spe", - // Pinned down by [`Target::abi_required_features`]. - InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, - &[], - ), - ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]), - // tidy-alphabetical-end -]; - -const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("fp64", Unstable(sym::mips_target_feature), &[]), - // FIXME(#150253): msa requires either fp64 or no hard float support at all: LLVM requires fp64 - // FIXME(#150253): msa requires revision 5 or greater (mips32r5/mips64r5 in LLVM) - ("msa", Unstable(sym::mips_target_feature), &[]), - ("virt", Unstable(sym::mips_target_feature), &[]), - // tidy-alphabetical-end -]; - -const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("sm_70", Unstable(sym::nvptx_target_feature), &[]), - ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]), - ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]), - ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]), - ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]), - ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]), - ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]), - ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]), - ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]), - // tidy-alphabetical-end - // tidy-alphabetical-start - ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]), - ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]), - ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]), - ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]), - ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]), - ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]), - // tidy-alphabetical-end - // tidy-alphabetical-start - ("ptx70", Unstable(sym::nvptx_target_feature), &[]), - ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]), - ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]), - ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]), - ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]), - ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]), - ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]), - ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]), - ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]), - ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]), - ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]), - ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]), - ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]), - ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]), - ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]), - ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]), - ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]), - // tidy-alphabetical-end -]; - -static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("a", Stable, &["zaamo", "zalrsc"]), - ("b", Stable, &["zba", "zbb", "zbs"]), - ("c", Stable, &["zca"]), - ("d", Stable, &["f"]), - ("e", Unstable(sym::riscv_target_feature), &[]), // negative feature! needs special care. - ("f", Stable, &["zicsr"]), - ( - "forced-atomics", - // Not implied by any CPU model or other feature. - Stability::InternalOnly { - reason: "unsound because it changes the ABI of atomic operations", - hard_error: false, - }, - &[], - ), - // According to the RISC-V spec, the M ISA extension (integer multiplication/division) is supported only when the M bit - // of the misa register is 1, while Zmmul means integer multiplication is always supported. - // - // The Rust/LLVM "m" target feature means something slightly different: with "m" enabled, it is assumed that integer - // multiplication and division will always be available (M bit will be 1 in misa), so "m" implies "zmmul". - // - // See discussion in the PR adding Zmmul: https://github.com/rust-lang/rust/pull/162552 - ("m", Stable, &["zmmul"]), - ("relax", Unstable(sym::riscv_target_feature), &[]), - ( - "rva23u64", - Unstable(sym::riscv_target_feature), - &[ - "m", - "a", - "f", - "d", - "c", - "b", - "v", - "zicsr", - "zicntr", - "zihpm", - "ziccif", - "ziccrse", - "ziccamoa", - "zicclsm", - "zic64b", - "za64rs", - "zihintpause", - "zba", - "zbb", - "zbs", - "zicbom", - "zicbop", - "zicboz", - "zfhmin", - "zkt", - "zvfhmin", - "zvbb", - "zvkt", - "zihintntl", - "zicond", - "zimop", - "zcmop", - "zcb", - "zfa", - "zawrs", - "supm", - ], - ), - ("supm", Unstable(sym::riscv_target_feature), &[]), - ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]), - ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]), - ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]), - ("za64rs", Stable, &["za128rs"]), // Za64rs ⊃ Za128rs - ("za128rs", Stable, &[]), - ("zaamo", Stable, &[]), - ("zabha", Stable, &["zaamo"]), - ("zacas", Stable, &["zaamo"]), - ("zalrsc", Stable, &[]), - ("zama16b", Stable, &[]), - ("zawrs", Stable, &[]), - ("zba", Stable, &[]), - ("zbb", Stable, &[]), - ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc - ("zbkb", Stable, &[]), - ("zbkc", Stable, &[]), - ("zbkx", Stable, &[]), - ("zbs", Stable, &[]), - ("zca", Stable, &[]), - ("zcb", Stable, &["zca"]), - ("zcmop", Stable, &["zca"]), - ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]), - ("zfa", Unstable(sym::riscv_target_feature), &["f"]), - ("zfbfmin", Unstable(sym::riscv_target_feature), &["f"]), // and a subset of Zfhmin - ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]), - ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]), - ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]), - ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]), - ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]), - ("zic64b", Stable, &[]), - ("zicbom", Stable, &[]), - ("zicbop", Stable, &[]), - ("zicboz", Stable, &[]), - ("ziccamoa", Stable, &[]), - ("ziccif", Stable, &[]), - ("zicclsm", Stable, &[]), - ("ziccrse", Stable, &[]), - ("zicntr", Stable, &["zicsr"]), - ("zicond", Stable, &[]), - ("zicsr", Stable, &[]), - ("zifencei", Stable, &[]), - ("zihintntl", Stable, &[]), - ("zihintpause", Stable, &[]), - ("zihpm", Stable, &["zicsr"]), - ("zimop", Stable, &[]), - ("zk", Stable, &["zkn", "zkr", "zkt"]), - ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), - ("zknd", Stable, &["zkne_or_zknd"]), - ("zkne", Stable, &["zkne_or_zknd"]), - ("zkne_or_zknd", Unstable(sym::riscv_target_feature), &[]), // Not an extension - ("zknh", Stable, &[]), - ("zkr", Stable, &[]), - ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]), - ("zksed", Stable, &[]), - ("zksh", Stable, &[]), - ("zkt", Stable, &[]), - ("zmmul", Unstable(sym::riscv_target_feature), &[]), - ("ztso", Stable, &[]), - ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb - ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]), - ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]), - ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]), - ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]), - ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]), - ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]), - ("zvfbfmin", Unstable(sym::riscv_target_feature), &["zve32f"]), - ("zvfbfwma", Unstable(sym::riscv_target_feature), &["zfbfmin", "zvfbfmin"]), - ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin - ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]), - ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]), - ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]), - ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]), - ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]), - ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]), - ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]), - ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]), - ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha - ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]), - ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]), - ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]), - ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]), - ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]), - ("zvkt", Unstable(sym::riscv_target_feature), &[]), - ("zvl32b", Unstable(sym::riscv_target_feature), &[]), - ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]), - ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]), - ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]), - ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]), - ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]), - ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]), - ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]), - ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]), - ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]), - ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]), - ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]), - // tidy-alphabetical-end -]; - -static WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("atomics", Unstable(sym::wasm_target_feature), &[]), - ("bulk-memory", Stable, &[]), - ("exception-handling", Unstable(sym::wasm_target_feature), &[]), - ("extended-const", Stable, &[]), - ("gc", Unstable(sym::wasm_target_feature), &["reference-types"]), - ("multivalue", Stable, &[]), - ("mutable-globals", Stable, &[]), - ("nontrapping-fptoint", Stable, &[]), - ("reference-types", Stable, &[]), - ("relaxed-simd", Stable, &["simd128"]), - ("sign-ext", Stable, &[]), - ("simd128", Stable, &[]), - ("tail-call", Stable, &[]), - ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]), - // tidy-alphabetical-end -]; - -const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - ("alu32", Unstable(sym::bpf_target_feature), &[]), - ("allows-misaligned-mem-access", Unstable(sym::bpf_target_feature), &[]), -]; - -static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("2e3", Unstable(sym::csky_target_feature), &["e2"]), - ("3e3r1", Unstable(sym::csky_target_feature), &[]), - ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]), - ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]), - ("3e7", Unstable(sym::csky_target_feature), &["2e3"]), - ("7e10", Unstable(sym::csky_target_feature), &["3e7"]), - ("10e60", Unstable(sym::csky_target_feature), &["7e10"]), - ("cache", Unstable(sym::csky_target_feature), &[]), - ("doloop", Unstable(sym::csky_target_feature), &[]), - ("dsp1e2", Unstable(sym::csky_target_feature), &[]), - ("dspe60", Unstable(sym::csky_target_feature), &[]), - ("e1", Unstable(sym::csky_target_feature), &["elrw"]), - ("e2", Unstable(sym::csky_target_feature), &["e2"]), - ("edsp", Unstable(sym::csky_target_feature), &[]), - ("elrw", Unstable(sym::csky_target_feature), &[]), - ("float1e2", Unstable(sym::csky_target_feature), &[]), - ("float1e3", Unstable(sym::csky_target_feature), &[]), - ("float3e4", Unstable(sym::csky_target_feature), &[]), - ("float7e60", Unstable(sym::csky_target_feature), &[]), - ("floate1", Unstable(sym::csky_target_feature), &[]), - ("hard-tp", Unstable(sym::csky_target_feature), &[]), - ("high-registers", Unstable(sym::csky_target_feature), &[]), - ("hwdiv", Unstable(sym::csky_target_feature), &[]), - ("mp", Unstable(sym::csky_target_feature), &["2e3"]), - ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]), - ("nvic", Unstable(sym::csky_target_feature), &[]), - ("trust", Unstable(sym::csky_target_feature), &[]), - ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]), - ("vdspv1", Unstable(sym::csky_target_feature), &[]), - ("vdspv2", Unstable(sym::csky_target_feature), &[]), - // tidy-alphabetical-end - //fpu - // tidy-alphabetical-start - ("fdivdu", Unstable(sym::csky_target_feature), &[]), - ("fpuv2_df", Unstable(sym::csky_target_feature), &[]), - ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_df", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]), - ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]), - ("hard-float", Unstable(sym::csky_target_feature), &[]), - ("hard-float-abi", Unstable(sym::csky_target_feature), &[]), - // tidy-alphabetical-end -]; - -static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("32s", Unstable(sym::loongarch_target_feature), &[]), - ("d", Stable, &["f"]), - ("div32", Stable, &[]), - ("f", Stable, &[]), - ("frecipe", Stable, &[]), - ("lam-bh", Stable, &[]), - ("lamcas", Stable, &[]), - ("lasx", Stable, &["lsx"]), - ("lbt", Stable, &[]), - ("ld-seq-sa", Stable, &[]), - ("lsx", Stable, &["d"]), - ("lvz", Stable, &[]), - ("relax", Unstable(sym::loongarch_target_feature), &[]), - ("scq", Stable, &[]), - ("ual", Unstable(sym::loongarch_target_feature), &[]), - // tidy-alphabetical-end -]; - -#[rustfmt::skip] -const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - // For "backchain", https://github.com/rust-lang/rust/issues/142412 is a stabilization blocker - ("backchain", Unstable(sym::s390x_target_feature), &[]), - ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]), - ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]), - ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]), - ("guarded-storage", Unstable(sym::s390x_target_feature), &[]), - ("high-word", Unstable(sym::s390x_target_feature), &[]), - // LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11. - ("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]), - ("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]), - ("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]), - ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]), - ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]), - ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]), - ("miscellaneous-extensions-2", Stable, &[]), - ("miscellaneous-extensions-3", Stable, &[]), - ("miscellaneous-extensions-4", Stable, &[]), - ("nnp-assist", Stable, &["vector"]), - // Pinned down by [`Target::abi_required_features`]. - ("soft-float", InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, &[]), - ("transactional-execution", Unstable(sym::s390x_target_feature), &[]), - ("vector", Stable, &[]), - ("vector-enhancements-1", Stable, &["vector"]), - ("vector-enhancements-2", Stable, &["vector-enhancements-1"]), - ("vector-enhancements-3", Stable, &["vector-enhancements-2"]), - ("vector-packed-decimal", Stable, &["vector"]), - ("vector-packed-decimal-enhancement", Stable, &["vector-packed-decimal"]), - ("vector-packed-decimal-enhancement-2", Stable, &["vector-packed-decimal-enhancement"]), - ("vector-packed-decimal-enhancement-3", Stable, &["vector-packed-decimal-enhancement-2"]), - // tidy-alphabetical-end -]; - -const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("leoncasa", Unstable(sym::sparc_target_feature), &[]), - ( - "soft-float", - InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, - &[], - ), - ("v8plus", Unstable(sym::sparc_target_feature), &[]), - // FIXME: It's unclear what this feature means when `v8plus` is disabled on 32-bit SPARC. See - // the discussion around https://github.com/rust-lang/rust/pull/160949#discussion_r3806194355. - ("v9", Unstable(sym::sparc_target_feature), &[]), - // tidy-alphabetical-end -]; - -static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("isa-68000", Unstable(sym::m68k_target_feature), &[]), - ("isa-68010", Unstable(sym::m68k_target_feature), &["isa-68000"]), - ("isa-68020", Unstable(sym::m68k_target_feature), &["isa-68010"]), - ("isa-68030", Unstable(sym::m68k_target_feature), &["isa-68020"]), - ("isa-68040", Unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]), - ("isa-68060", Unstable(sym::m68k_target_feature), &["isa-68040"]), - // FPU - ("isa-68881", Unstable(sym::m68k_target_feature), &[]), - ("isa-68882", Unstable(sym::m68k_target_feature), &["isa-68881"]), - // tidy-alphabetical-end -]; - -static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - // tidy-alphabetical-start - ("addsubiw", Unstable(sym::avr_target_feature), &[]), - ("break", Unstable(sym::avr_target_feature), &[]), - ("eijmpcall", Unstable(sym::avr_target_feature), &[]), - ("elpm", Unstable(sym::avr_target_feature), &[]), - ("elpmx", Unstable(sym::avr_target_feature), &[]), - ("ijmpcall", Unstable(sym::avr_target_feature), &[]), - ("jmpcall", Unstable(sym::avr_target_feature), &[]), - ("lowbytefirst", Unstable(sym::avr_target_feature), &[]), - ("lpm", Unstable(sym::avr_target_feature), &[]), - ("lpmx", Unstable(sym::avr_target_feature), &[]), - ("movw", Unstable(sym::avr_target_feature), &[]), - ("mul", Unstable(sym::avr_target_feature), &[]), - ("rmw", Unstable(sym::avr_target_feature), &[]), - ("spm", Unstable(sym::avr_target_feature), &[]), - ("spmx", Unstable(sym::avr_target_feature), &[]), - ( - "sram", - // Pinned down by [`Target::abi_required_features`]. - InternalOnly { reason: "devices that have no SRAM are unsupported", hard_error: false }, - &[], - ), - ("tinyencoding", Unstable(sym::avr_target_feature), &[]), - // tidy-alphabetical-end -]; - -const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ - ("bool", Unstable(sym::xtensa_target_feature), &[]), - ("fp", Unstable(sym::xtensa_target_feature), &["bool", "coprocessor"]), - ("coprocessor", Unstable(sym::xtensa_target_feature), &[]), - ("highpriinterrupts", Unstable(sym::xtensa_target_feature), &["interrupt"]), - ("interrupt", Unstable(sym::xtensa_target_feature), &["exception"]), - ( - "windowed", - // Pinned down by [`Target::abi_required_features`]. - InternalOnly { - reason: "windowed changes the Xtensa calling convention", - hard_error: false, - }, - &["exception"], - ), - ("loop", Unstable(sym::xtensa_target_feature), &[]), - ("sext", Unstable(sym::xtensa_target_feature), &[]), - ("nsa", Unstable(sym::xtensa_target_feature), &[]), - ("mul32", Unstable(sym::xtensa_target_feature), &[]), - ("mul32high", Unstable(sym::xtensa_target_feature), &["mul32"]), - ("div32", Unstable(sym::xtensa_target_feature), &[]), - ("mac16", Unstable(sym::xtensa_target_feature), &[]), - ("s32c1i", Unstable(sym::xtensa_target_feature), &[]), - ("threadptr", Unstable(sym::xtensa_target_feature), &[]), - ("extendedl32r", Unstable(sym::xtensa_target_feature), &[]), - ("debug", Unstable(sym::xtensa_target_feature), &["exception"]), - ("exception", Unstable(sym::xtensa_target_feature), &[]), - ("rvector", Unstable(sym::xtensa_target_feature), &["exception"]), - ("prid", Unstable(sym::xtensa_target_feature), &[]), - ("regprotect", Unstable(sym::xtensa_target_feature), &[]), - ("miscsr", Unstable(sym::xtensa_target_feature), &[]), -]; - -static TARGET_FEATURE_IMPLICATIONS_RAW: &[&[(&str, Stability, ImpliedFeatures)]] = &[ - ARM_FEATURES, - AARCH64_FEATURES, - X86_FEATURES, - HEXAGON_FEATURES, - POWERPC_FEATURES, - MIPS_FEATURES, - NVPTX_FEATURES, - RISCV_FEATURES, - WASM_FEATURES, - BPF_FEATURES, - XTENSA_FEATURES, - CSKY_FEATURES, - LOONGARCH_FEATURES, - IBMZ_FEATURES, - SPARC_FEATURES, - M68K_FEATURES, - AVR_FEATURES, -]; -// spellchecker:on diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature/generated.rs b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature/generated.rs new file mode 100644 index 0000000000000..41916d0b08c5c --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature/generated.rs @@ -0,0 +1,961 @@ +//! Generated by `cargo xtask codegen target-features`, do not edit by hand. + +// spellchecker:off + +#[expect(dead_code, reason = "stubs for rustc_target")] +pub(super) enum Stability { + Stable, + Unstable(()), + InternalOnly { reason: &'static str, hard_error: bool }, +} +use Stability::*; + +type ImpliedFeatures = &'static [&'static str]; +static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("aclass", Unstable(sym::arm_target_feature), &[]), + ("acquire-release", Unstable(sym::arm_target_feature), &[]), + ("aes", Unstable(sym::arm_target_feature), &["neon"]), + ( + "atomics-32", + // Not implied by any CPU model or other feature. + Stability::InternalOnly { + reason: "unsound because it changes the ABI of atomic operations", + hard_error: false, + }, + &[], + ), + ("bf16", Unstable(sym::arm_target_feature), &["neon"]), + ("crc", Unstable(sym::arm_target_feature), &[]), + ("d32", Unstable(sym::arm_target_feature), &[]), + ("dotprod", Unstable(sym::arm_target_feature), &["neon"]), + ("dsp", Unstable(sym::arm_target_feature), &[]), + ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]), + ("fp16", Unstable(sym::arm_target_feature), &["neon"]), + ("fp64", Unstable(sym::arm_target_feature), &[]), + ("fpregs", Unstable(sym::arm_target_feature), &[]), + ("i8mm", Unstable(sym::arm_target_feature), &["neon"]), + ("mclass", Unstable(sym::arm_target_feature), &[]), + ("mve", Unstable(sym::arm_target_feature), &["v8.1m.main", "dsp", "fpregs"]), + ("mve.fp", Unstable(sym::arm_target_feature), &["mve"]), + ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), + ("rclass", Unstable(sym::arm_target_feature), &[]), + ("sha2", Unstable(sym::arm_target_feature), &["neon"]), + // This can be *disabled* on non-`hf` targets to enable the use + // of hardfloats while keeping the softfloat ABI. + // FIXME before stabilization: Should we expose this as a `hard-float` target feature instead of + // matching the odd negative feature LLVM uses? + ("soft-float", Unstable(sym::arm_target_feature), &[]), + // This is needed for inline assembly, but shouldn't be stabilized as-is + // since it should be enabled per-function using #[instruction_set], not + // #[target_feature]. + ("thumb-mode", Unstable(sym::arm_target_feature), &[]), + ("thumb2", Unstable(sym::arm_target_feature), &[]), + ("trustzone", Unstable(sym::arm_target_feature), &[]), + ("v5te", Unstable(sym::arm_target_feature), &[]), + ("v6", Unstable(sym::arm_target_feature), &["v5te"]), + ("v6k", Unstable(sym::arm_target_feature), &["v6"]), + ("v6m", Unstable(sym::arm_target_feature), &["v6"]), + ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "v8m", "thumb2"]), + ("v7", Unstable(sym::arm_target_feature), &["v6t2"]), + ("v8", Unstable(sym::arm_target_feature), &["v7", "acquire-release"]), + ("v8.1m.main", Unstable(sym::arm_target_feature), &["v8m.main"]), + ("v8m", Unstable(sym::arm_target_feature), &["v6m"]), + ("v8m.main", Unstable(sym::arm_target_feature), &["v7"]), + ("vfp2", Unstable(sym::arm_target_feature), &["vfp2sp", "fp64"]), + ("vfp2sp", Unstable(sym::arm_target_feature), &["fpregs"]), + ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]), + ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]), + ("virtualization", Unstable(sym::arm_target_feature), &[]), + // tidy-alphabetical-end +]; +static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + // FEAT_AES & FEAT_PMULL + ("aes", Stable, &["neon"]), + // FEAT_BF16 + ("bf16", Stable, &[]), + // FEAT_BTI + ("bti", Stable, &[]), + // FEAT_CRC + ("crc", Stable, &[]), + // FEAT_CSSC + ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_DIT + ("dit", Stable, &[]), + // FEAT_DotProd + ("dotprod", Stable, &["neon"]), + // FEAT_DPB + ("dpb", Stable, &[]), + // FEAT_DPB2 + ("dpb2", Stable, &["dpb"]), + // FEAT_ECV + ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_F32MM + ("f32mm", Stable, &["sve"]), + // FEAT_F64MM + ("f64mm", Stable, &["sve"]), + // FEAT_FAMINMAX + ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_FCMA + ("fcma", Stable, &["neon"]), + // FEAT_FHM + ("fhm", Stable, &["fp16"]), + // FEAT_FLAGM + ("flagm", Stable, &[]), + // FEAT_FLAGM2 + ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`. + ( + "fp-armv8", + // Pinned down by [`Target::abi_required_features`] when needed. + Stability::InternalOnly { reason: "Rust ties `fp-armv8` to `neon`", hard_error: false }, + &[], + ), + // FEAT_FP8 + ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), + // FEAT_FP8DOT2 + ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), + // FEAT_FP8DOT4 + ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), + // FEAT_FP8FMA + ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), + // FEAT_FP16 + // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 + ("fp16", Stable, &["neon"]), + // FEAT_FRINTTS + ("frintts", Stable, &[]), + // FEAT_HBC + ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_I8MM + ("i8mm", Stable, &[]), + // FEAT_JSCVT + // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 + ("jsconv", Stable, &["neon"]), + // FEAT_LOR + ("lor", Stable, &[]), + // FEAT_LSE + ("lse", Stable, &[]), + // FEAT_LSE2 + ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_LSE128 + ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), + // FEAT_LUT + ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_MOPS + ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_MTE & FEAT_MTE2 + ("mte", Stable, &[]), + // FEAT_AdvSimd & FEAT_FP + ("neon", Stable, &[]), + // Backend option to turn atomic operations into an intrinsic call when `lse` is not known to be + // available, so the intrinsic can do runtime LSE feature detection rather than unconditionally + // using slower non-LSE operations. Unstable since it doesn't need to user-togglable. + ("outline-atomics", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_PAUTH (address authentication) + ("paca", Stable, &[]), + // FEAT_PAUTH (generic authentication) + ("pacg", Stable, &[]), + // FEAT_PAN + ("pan", Stable, &[]), + // FEAT_PAuth_LR + ("pauth-lr", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_PMUv3 + ("pmuv3", Stable, &[]), + // FEAT_RNG + ("rand", Stable, &[]), + // FEAT_RAS & FEAT_RASv1p1 + ("ras", Stable, &[]), + // FEAT_LRCPC + ("rcpc", Stable, &[]), + // FEAT_LRCPC2 + ("rcpc2", Stable, &["rcpc"]), + // FEAT_LRCPC3 + ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), + // FEAT_RDM + ("rdm", Stable, &["neon"]), + ( + "reserve-x18", + // Not implied by any CPU model or other feature; the compiler flag is a target modifier. + InternalOnly { reason: "use `-Zfixed-x18` compiler flag instead", hard_error: false }, + &[], + ), + // FEAT_SB + ("sb", Stable, &[]), + // FEAT_SHA1 & FEAT_SHA256 + ("sha2", Stable, &["neon"]), + // FEAT_SHA512 & FEAT_SHA3 + ("sha3", Stable, &["sha2"]), + // FEAT_SM3 & FEAT_SM4 + ("sm4", Stable, &["neon"]), + // FEAT_SME + ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_B16B16 + ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), + // FEAT_SME_F8F16 + ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), + // FEAT_SME_F8F32 + ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + // FEAT_SME_F16F16 + ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + // FEAT_SME_F64F64 + ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_FA64 + ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), + // FEAT_SME_I16I64 + ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_LUTv2 + ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_SME2 + ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME2p1 + ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + // FEAT_SPE + ("spe", Stable, &[]), + // FEAT_SSBS & FEAT_SSBS2 + ("ssbs", Stable, &[]), + // FEAT_SSVE_FP8FDOT2 + ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), + // FEAT_SSVE_FP8FDOT4 + ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), + // FEAT_SSVE_FP8FMA + ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + // FEAT_SVE + // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 + // + // LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always + // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2 + // + // "For backwards compatibility, Neon and VFP are required in the latest architectures." + ("sve", Stable, &["neon", "fp16"]), + // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions) + ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SVE2 + ("sve2", Stable, &["sve"]), + // FEAT_SVE_AES & FEAT_SVE_PMULL128 + ("sve2-aes", Stable, &["sve2", "aes"]), + // FEAT_SVE2_BitPerm + ("sve2-bitperm", Stable, &["sve2"]), + // FEAT_SVE2_SHA3 + ("sve2-sha3", Stable, &["sve2", "sha3"]), + // FEAT_SVE2_SM4 + ("sve2-sm4", Stable, &["sve2", "sm4"]), + // FEAT_SVE2p1 + ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), + // FEAT_TME + ("tme", Stable, &[]), + ( + "v8.1a", + Unstable(sym::aarch64_ver_target_feature), + &["crc", "lse", "rdm", "pan", "lor", "vh"], + ), + ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]), + ( + "v8.3a", + Unstable(sym::aarch64_ver_target_feature), + &["v8.2a", "rcpc", "paca", "pacg", "jsconv"], + ), + ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), + ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), + ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), + ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), + ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), + ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), + ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), + ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), + ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), + ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), + ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a"]), + // FEAT_VHE + ("vh", Stable, &[]), + // FEAT_WFxT + ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), + // tidy-alphabetical-end +]; +static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("adx", Stable, &[]), + ("aes", Stable, &["sse2"]), + ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]), + ("apxf", Unstable(sym::apx_target_feature), &[]), + ("avx", Stable, &["sse4.2"]), + ("avx2", Stable, &["avx"]), + ( + "avx10.1", + Unstable(sym::avx10_target_feature), + &[ + "avx512bf16", + "avx512bitalg", + "avx512bw", + "avx512cd", + "avx512dq", + "avx512f", + "avx512fp16", + "avx512ifma", + "avx512vbmi", + "avx512vbmi2", + "avx512vl", + "avx512vnni", + "avx512vpopcntdq", + ], + ), + ( + "avx10.2", + Unstable(sym::avx10_target_feature), + &["avx10.1", "avxvnni", "avxvnniint8", "avxvnniint16"], + ), + ("avx512bf16", Stable, &["avx512bw"]), + ("avx512bitalg", Stable, &["avx512bw"]), + ("avx512bw", Stable, &["avx512f"]), + ("avx512cd", Stable, &["avx512f"]), + ("avx512dq", Stable, &["avx512f"]), + ("avx512f", Stable, &["avx2", "fma", "f16c"]), + ("avx512fp16", Stable, &["avx512bw"]), + ("avx512ifma", Stable, &["avx512f"]), + ("avx512vbmi", Stable, &["avx512bw"]), + ("avx512vbmi2", Stable, &["avx512bw"]), + ("avx512vl", Stable, &["avx512f"]), + ("avx512vnni", Stable, &["avx512f"]), + ("avx512vp2intersect", Stable, &["avx512f"]), + ("avx512vpopcntdq", Stable, &["avx512f"]), + ("avxifma", Stable, &["avx2"]), + ("avxneconvert", Stable, &["avx2"]), + ("avxvnni", Stable, &["avx2"]), + ("avxvnniint8", Stable, &["avx2"]), + ("avxvnniint16", Stable, &["avx2"]), + ("bmi1", Stable, &[]), + ("bmi2", Stable, &[]), + ("clflushopt", Unstable(sym::clflushopt_target_feature), &[]), + ("cmpxchg16b", Stable, &[]), + ("ermsb", Unstable(sym::ermsb_target_feature), &[]), + ("f16c", Stable, &["avx"]), + ("fma", Stable, &["avx"]), + ("fma4", Unstable(sym::fma4_target_feature), &["avx", "sse4a"]), + ("fxsr", Stable, &[]), + ("gfni", Stable, &["sse2"]), + ("kl", Stable, &["sse2"]), + ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), + ("lzcnt", Stable, &[]), + ("movbe", Stable, &[]), + ("movdir64b", Unstable(sym::movdir64b_target_feature), &[]), + ("movdiri", Unstable(sym::movdiri_target_feature), &[]), + ("movrs", Unstable(sym::movrs_target_feature), &[]), + ("pclmulqdq", Stable, &["sse2"]), + ("popcnt", Stable, &[]), + ("prfchw", Unstable(sym::prfchw_target_feature), &[]), + ("rdrand", Stable, &[]), + ("rdseed", Stable, &[]), + ( + "retpoline-external-thunk", + // Not implied by any CPU model or other feature; the compiler flag is a target modifier. + Stability::InternalOnly { + reason: "use `-Zretpoline-external-thunk` compiler flag instead", + hard_error: false, + }, + &[], + ), + ( + "retpoline-indirect-branches", + // Not implied by any CPU model or other feature; the compiler flag is a target modifier. + Stability::InternalOnly { + reason: "use `-Zretpoline` compiler flag instead", + hard_error: false, + }, + &[], + ), + ( + "retpoline-indirect-calls", + // Not implied by any CPU model or other feature; the compiler flag is a target modifier. + Stability::InternalOnly { + reason: "use `-Zretpoline` compiler flag instead", + hard_error: false, + }, + &[], + ), + ("rtm", Unstable(sym::rtm_target_feature), &[]), + ("sha", Stable, &["sse2"]), + ("sha512", Stable, &["avx2"]), + ("sm3", Stable, &["avx"]), + ("sm4", Stable, &["avx2"]), + ( + "soft-float", + // Pinned down by [`Target::abi_required_features`]. + Stability::InternalOnly { reason: "use a soft-float target instead", hard_error: false }, + &[], + ), + ("sse", Stable, &[]), + ("sse2", Stable, &["sse"]), + ("sse3", Stable, &["sse2"]), + ("sse4.1", Stable, &["ssse3"]), + ("sse4.2", Stable, &["sse4.1"]), + ("sse4a", Stable, &["sse3"]), + ("ssse3", Stable, &["sse3"]), + ("tbm", Stable, &[]), + ("vaes", Stable, &["avx2", "aes"]), + ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]), + ("widekl", Stable, &["kl"]), + ("x87", Unstable(sym::x87_target_feature), &[]), + ("xop", Unstable(sym::xop_target_feature), &["fma4", "avx", "sse4a"]), + ("xsave", Stable, &[]), + ("xsavec", Stable, &["xsave"]), + ("xsaveopt", Stable, &["xsave"]), + ("xsaves", Stable, &["xsave"]), + // tidy-alphabetical-end +]; +const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("audio", Unstable(sym::hexagon_target_feature), &[]), + ("hvx", Unstable(sym::hexagon_target_feature), &[]), + ("hvx-ieee-fp", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvx-length64b", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvx-qfloat", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvxv60", Unstable(sym::hexagon_target_feature), &["hvx"]), + ("hvxv62", Unstable(sym::hexagon_target_feature), &["hvxv60"]), + ("hvxv65", Unstable(sym::hexagon_target_feature), &["hvxv62"]), + ("hvxv66", Unstable(sym::hexagon_target_feature), &["hvxv65", "zreg"]), + ("hvxv67", Unstable(sym::hexagon_target_feature), &["hvxv66"]), + ("hvxv68", Unstable(sym::hexagon_target_feature), &["hvxv67"]), + ("hvxv69", Unstable(sym::hexagon_target_feature), &["hvxv68"]), + ("hvxv71", Unstable(sym::hexagon_target_feature), &["hvxv69"]), + ("hvxv73", Unstable(sym::hexagon_target_feature), &["hvxv71"]), + ("hvxv75", Unstable(sym::hexagon_target_feature), &["hvxv73"]), + ("hvxv79", Unstable(sym::hexagon_target_feature), &["hvxv75"]), + ("v60", Unstable(sym::hexagon_target_feature), &[]), + ("v62", Unstable(sym::hexagon_target_feature), &["v60"]), + ("v65", Unstable(sym::hexagon_target_feature), &["v62"]), + ("v66", Unstable(sym::hexagon_target_feature), &["v65"]), + ("v67", Unstable(sym::hexagon_target_feature), &["v66"]), + ("v68", Unstable(sym::hexagon_target_feature), &["v67"]), + ("v69", Unstable(sym::hexagon_target_feature), &["v68"]), + ("v71", Unstable(sym::hexagon_target_feature), &["v69"]), + ("v73", Unstable(sym::hexagon_target_feature), &["v71"]), + ("v75", Unstable(sym::hexagon_target_feature), &["v73"]), + ("v79", Unstable(sym::hexagon_target_feature), &["v75"]), + ("zreg", Unstable(sym::hexagon_target_feature), &[]), + // tidy-alphabetical-end +]; +static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // If you are thinking of adding "efpu2" here, please double-check that it really does not + // affect the ABI. + // tidy-alphabetical-start + ("altivec", Unstable(sym::powerpc_target_feature), &[]), + ( + "hard-float", + // Pinned down by [`Target::abi_required_features`]. + InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, + &[], + ), + ("msync", Unstable(sym::powerpc_target_feature), &[]), + ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]), + ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]), + ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]), + ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]), + ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]), + ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]), + ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]), + ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]), + ( + "spe", + // Pinned down by [`Target::abi_required_features`]. + InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, + &[], + ), + ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]), + // tidy-alphabetical-end +]; +const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("fp64", Unstable(sym::mips_target_feature), &[]), + // FIXME(#150253): msa requires either fp64 or no hard float support at all: LLVM requires fp64 + // FIXME(#150253): msa requires revision 5 or greater (mips32r5/mips64r5 in LLVM) + ("msa", Unstable(sym::mips_target_feature), &[]), + ("virt", Unstable(sym::mips_target_feature), &[]), + // tidy-alphabetical-end +]; +const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("sm_70", Unstable(sym::nvptx_target_feature), &[]), + ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]), + ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]), + ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]), + ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]), + ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]), + ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]), + ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]), + ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]), + // tidy-alphabetical-end + // tidy-alphabetical-start + ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]), + ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]), + ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]), + ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]), + ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]), + ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]), + // tidy-alphabetical-end + // tidy-alphabetical-start + ("ptx70", Unstable(sym::nvptx_target_feature), &[]), + ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]), + ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]), + ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]), + ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]), + ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]), + ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]), + ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]), + ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]), + ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]), + ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]), + ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]), + ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]), + ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]), + ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]), + ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]), + ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]), + // tidy-alphabetical-end +]; +static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("a", Stable, &["zaamo", "zalrsc"]), + ("b", Stable, &["zba", "zbb", "zbs"]), + ("c", Stable, &["zca"]), + ("d", Stable, &["f"]), + ("e", Unstable(sym::riscv_target_feature), &[]), // negative feature! needs special care. + ("f", Stable, &["zicsr"]), + ( + "forced-atomics", + // Not implied by any CPU model or other feature. + Stability::InternalOnly { + reason: "unsound because it changes the ABI of atomic operations", + hard_error: false, + }, + &[], + ), + // According to the RISC-V spec, the M ISA extension (integer multiplication/division) is supported only when the M bit + // of the misa register is 1, while Zmmul means integer multiplication is always supported. + // + // The Rust/LLVM "m" target feature means something slightly different: with "m" enabled, it is assumed that integer + // multiplication and division will always be available (M bit will be 1 in misa), so "m" implies "zmmul". + // + // See discussion in the PR adding Zmmul: https://github.com/rust-lang/rust/pull/162552 + ("m", Stable, &["zmmul"]), + ("relax", Unstable(sym::riscv_target_feature), &[]), + ( + "rva23u64", + Unstable(sym::riscv_target_feature), + &[ + "m", + "a", + "f", + "d", + "c", + "b", + "v", + "zicsr", + "zicntr", + "zihpm", + "ziccif", + "ziccrse", + "ziccamoa", + "zicclsm", + "zic64b", + "za64rs", + "zihintpause", + "zba", + "zbb", + "zbs", + "zicbom", + "zicbop", + "zicboz", + "zfhmin", + "zkt", + "zvfhmin", + "zvbb", + "zvkt", + "zihintntl", + "zicond", + "zimop", + "zcmop", + "zcb", + "zfa", + "zawrs", + "supm", + ], + ), + ("supm", Unstable(sym::riscv_target_feature), &[]), + ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]), + ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]), + ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]), + ("za64rs", Stable, &["za128rs"]), // Za64rs ⊃ Za128rs + ("za128rs", Stable, &[]), + ("zaamo", Stable, &[]), + ("zabha", Stable, &["zaamo"]), + ("zacas", Stable, &["zaamo"]), + ("zalrsc", Stable, &[]), + ("zama16b", Stable, &[]), + ("zawrs", Stable, &[]), + ("zba", Stable, &[]), + ("zbb", Stable, &[]), + ("zbc", Stable, &["zbkc"]), // Zbc ⊃ Zbkc + ("zbkb", Stable, &[]), + ("zbkc", Stable, &[]), + ("zbkx", Stable, &[]), + ("zbs", Stable, &[]), + ("zca", Stable, &[]), + ("zcb", Stable, &["zca"]), + ("zcmop", Stable, &["zca"]), + ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]), + ("zfa", Unstable(sym::riscv_target_feature), &["f"]), + ("zfbfmin", Unstable(sym::riscv_target_feature), &["f"]), // and a subset of Zfhmin + ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]), + ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]), + ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]), + ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]), + ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]), + ("zic64b", Stable, &[]), + ("zicbom", Stable, &[]), + ("zicbop", Stable, &[]), + ("zicboz", Stable, &[]), + ("ziccamoa", Stable, &[]), + ("ziccif", Stable, &[]), + ("zicclsm", Stable, &[]), + ("ziccrse", Stable, &[]), + ("zicntr", Stable, &["zicsr"]), + ("zicond", Stable, &[]), + ("zicsr", Stable, &[]), + ("zifencei", Stable, &[]), + ("zihintntl", Stable, &[]), + ("zihintpause", Stable, &[]), + ("zihpm", Stable, &["zicsr"]), + ("zimop", Stable, &[]), + ("zk", Stable, &["zkn", "zkr", "zkt"]), + ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), + ("zknd", Stable, &["zkne_or_zknd"]), + ("zkne", Stable, &["zkne_or_zknd"]), + ("zkne_or_zknd", Unstable(sym::riscv_target_feature), &[]), // Not an extension + ("zknh", Stable, &[]), + ("zkr", Stable, &[]), + ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]), + ("zksed", Stable, &[]), + ("zksh", Stable, &[]), + ("zkt", Stable, &[]), + ("zmmul", Unstable(sym::riscv_target_feature), &[]), + ("ztso", Stable, &[]), + ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb + ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]), + ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]), + ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b", "zicsr"]), + ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]), + ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]), + ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]), + ("zvfbfmin", Unstable(sym::riscv_target_feature), &["zve32f"]), + ("zvfbfwma", Unstable(sym::riscv_target_feature), &["zfbfmin", "zvfbfmin"]), + ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zve32f", "zfhmin"]), // Zvfh ⊃ Zvfhmin + ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]), + ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]), + ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]), + ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]), + ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvknhb", Unstable(sym::riscv_target_feature), &["zvknha", "zve64x"]), // Zvknhb ⊃ Zvknha + ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]), + ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]), + ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]), + ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkt", Unstable(sym::riscv_target_feature), &[]), + ("zvl32b", Unstable(sym::riscv_target_feature), &[]), + ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]), + ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]), + ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]), + ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]), + ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]), + ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]), + ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]), + ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]), + ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]), + ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]), + ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]), + // tidy-alphabetical-end +]; +static WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("atomics", Unstable(sym::wasm_target_feature), &[]), + ("bulk-memory", Stable, &[]), + ("exception-handling", Unstable(sym::wasm_target_feature), &[]), + ("extended-const", Stable, &[]), + ("gc", Unstable(sym::wasm_target_feature), &["reference-types"]), + ("multivalue", Stable, &[]), + ("mutable-globals", Stable, &[]), + ("nontrapping-fptoint", Stable, &[]), + ("reference-types", Stable, &[]), + ("relaxed-simd", Stable, &["simd128"]), + ("sign-ext", Stable, &[]), + ("simd128", Stable, &[]), + ("tail-call", Stable, &[]), + ("wide-arithmetic", Stable, &[]), + // tidy-alphabetical-end +]; +const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + ("alu32", Unstable(sym::bpf_target_feature), &[]), + ("allows-misaligned-mem-access", Unstable(sym::bpf_target_feature), &[]), +]; +static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("2e3", Unstable(sym::csky_target_feature), &["e2"]), + ("3e3r1", Unstable(sym::csky_target_feature), &[]), + ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]), + ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]), + ("3e7", Unstable(sym::csky_target_feature), &["2e3"]), + ("7e10", Unstable(sym::csky_target_feature), &["3e7"]), + ("10e60", Unstable(sym::csky_target_feature), &["7e10"]), + ("cache", Unstable(sym::csky_target_feature), &[]), + ("doloop", Unstable(sym::csky_target_feature), &[]), + ("dsp1e2", Unstable(sym::csky_target_feature), &[]), + ("dspe60", Unstable(sym::csky_target_feature), &[]), + ("e1", Unstable(sym::csky_target_feature), &["elrw"]), + ("e2", Unstable(sym::csky_target_feature), &["e2"]), + ("edsp", Unstable(sym::csky_target_feature), &[]), + ("elrw", Unstable(sym::csky_target_feature), &[]), + ("float1e2", Unstable(sym::csky_target_feature), &[]), + ("float1e3", Unstable(sym::csky_target_feature), &[]), + ("float3e4", Unstable(sym::csky_target_feature), &[]), + ("float7e60", Unstable(sym::csky_target_feature), &[]), + ("floate1", Unstable(sym::csky_target_feature), &[]), + ("hard-tp", Unstable(sym::csky_target_feature), &[]), + ("high-registers", Unstable(sym::csky_target_feature), &[]), + ("hwdiv", Unstable(sym::csky_target_feature), &[]), + ("mp", Unstable(sym::csky_target_feature), &["2e3"]), + ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]), + ("nvic", Unstable(sym::csky_target_feature), &[]), + ("trust", Unstable(sym::csky_target_feature), &[]), + ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]), + ("vdspv1", Unstable(sym::csky_target_feature), &[]), + ("vdspv2", Unstable(sym::csky_target_feature), &[]), + // tidy-alphabetical-end + //fpu + // tidy-alphabetical-start + ("fdivdu", Unstable(sym::csky_target_feature), &[]), + ("fpuv2_df", Unstable(sym::csky_target_feature), &[]), + ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]), + ("fpuv3_df", Unstable(sym::csky_target_feature), &[]), + ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]), + ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]), + ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]), + ("hard-float", Unstable(sym::csky_target_feature), &[]), + ("hard-float-abi", Unstable(sym::csky_target_feature), &[]), + // tidy-alphabetical-end +]; +static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("32s", Unstable(sym::loongarch_target_feature), &[]), + ("d", Stable, &["f"]), + ("div32", Stable, &[]), + ("f", Stable, &[]), + ("frecipe", Stable, &[]), + ("lam-bh", Stable, &[]), + ("lamcas", Stable, &[]), + ("lasx", Stable, &["lsx"]), + ("lbt", Stable, &[]), + ("ld-seq-sa", Stable, &[]), + ("lsx", Stable, &["d"]), + ("lvz", Stable, &[]), + ("relax", Unstable(sym::loongarch_target_feature), &[]), + ("scq", Stable, &[]), + ("ual", Unstable(sym::loongarch_target_feature), &[]), + // tidy-alphabetical-end +]; +const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + // For "backchain", https://github.com/rust-lang/rust/issues/142412 is a stabilization blocker + ("backchain", Unstable(sym::s390x_target_feature), &[]), + ("concurrent-functions", Unstable(sym::s390x_target_feature), &[]), + ("deflate-conversion", Unstable(sym::s390x_target_feature), &[]), + ("enhanced-sort", Unstable(sym::s390x_target_feature), &[]), + ("guarded-storage", Unstable(sym::s390x_target_feature), &[]), + ("high-word", Unstable(sym::s390x_target_feature), &[]), + // LLVM does not define message-security-assist-extension versions 1, 2, 6, 10 and 11. + ("message-security-assist-extension3", Unstable(sym::s390x_target_feature), &[]), + ("message-security-assist-extension4", Unstable(sym::s390x_target_feature), &[]), + ("message-security-assist-extension5", Unstable(sym::s390x_target_feature), &[]), + ( + "message-security-assist-extension8", + Unstable(sym::s390x_target_feature), + &["message-security-assist-extension3"], + ), + ( + "message-security-assist-extension9", + Unstable(sym::s390x_target_feature), + &["message-security-assist-extension3", "message-security-assist-extension4"], + ), + ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]), + ("miscellaneous-extensions-2", Stable, &[]), + ("miscellaneous-extensions-3", Stable, &[]), + ("miscellaneous-extensions-4", Stable, &[]), + ("nnp-assist", Stable, &["vector"]), + // Pinned down by [`Target::abi_required_features`]. + ( + "soft-float", + InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, + &[], + ), + ("transactional-execution", Unstable(sym::s390x_target_feature), &[]), + ("vector", Stable, &[]), + ("vector-enhancements-1", Stable, &["vector"]), + ("vector-enhancements-2", Stable, &["vector-enhancements-1"]), + ("vector-enhancements-3", Stable, &["vector-enhancements-2"]), + ("vector-packed-decimal", Stable, &["vector"]), + ("vector-packed-decimal-enhancement", Stable, &["vector-packed-decimal"]), + ("vector-packed-decimal-enhancement-2", Stable, &["vector-packed-decimal-enhancement"]), + ("vector-packed-decimal-enhancement-3", Stable, &["vector-packed-decimal-enhancement-2"]), + // tidy-alphabetical-end +]; +const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("leoncasa", Unstable(sym::sparc_target_feature), &[]), + ( + "soft-float", + InternalOnly { reason: "unsupported ABI-configuration feature", hard_error: false }, + &[], + ), + ("v8plus", Unstable(sym::sparc_target_feature), &[]), + // FIXME: It's unclear what this feature means when `v8plus` is disabled on 32-bit SPARC. See + // the discussion around https://github.com/rust-lang/rust/pull/160949#discussion_r3806194355. + ("v9", Unstable(sym::sparc_target_feature), &[]), + // tidy-alphabetical-end +]; +static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("isa-68000", Unstable(sym::m68k_target_feature), &[]), + ("isa-68010", Unstable(sym::m68k_target_feature), &["isa-68000"]), + ("isa-68020", Unstable(sym::m68k_target_feature), &["isa-68010"]), + ("isa-68030", Unstable(sym::m68k_target_feature), &["isa-68020"]), + ("isa-68040", Unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]), + ("isa-68060", Unstable(sym::m68k_target_feature), &["isa-68040"]), + // FPU + ("isa-68881", Unstable(sym::m68k_target_feature), &[]), + ("isa-68882", Unstable(sym::m68k_target_feature), &["isa-68881"]), + // tidy-alphabetical-end +]; +static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("addsubiw", Unstable(sym::avr_target_feature), &[]), + ("break", Unstable(sym::avr_target_feature), &[]), + ("eijmpcall", Unstable(sym::avr_target_feature), &[]), + ("elpm", Unstable(sym::avr_target_feature), &[]), + ("elpmx", Unstable(sym::avr_target_feature), &[]), + ("ijmpcall", Unstable(sym::avr_target_feature), &[]), + ("jmpcall", Unstable(sym::avr_target_feature), &[]), + ("lowbytefirst", Unstable(sym::avr_target_feature), &[]), + ("lpm", Unstable(sym::avr_target_feature), &[]), + ("lpmx", Unstable(sym::avr_target_feature), &[]), + ("movw", Unstable(sym::avr_target_feature), &[]), + ("mul", Unstable(sym::avr_target_feature), &[]), + ("rmw", Unstable(sym::avr_target_feature), &[]), + ("spm", Unstable(sym::avr_target_feature), &[]), + ("spmx", Unstable(sym::avr_target_feature), &[]), + ( + "sram", + // Pinned down by [`Target::abi_required_features`]. + InternalOnly { reason: "devices that have no SRAM are unsupported", hard_error: false }, + &[], + ), + ("tinyencoding", Unstable(sym::avr_target_feature), &[]), + // tidy-alphabetical-end +]; +const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + ("bool", Unstable(sym::xtensa_target_feature), &[]), + ("fp", Unstable(sym::xtensa_target_feature), &["bool", "coprocessor"]), + ("coprocessor", Unstable(sym::xtensa_target_feature), &[]), + ("highpriinterrupts", Unstable(sym::xtensa_target_feature), &["interrupt"]), + ("interrupt", Unstable(sym::xtensa_target_feature), &["exception"]), + ( + "windowed", + // Pinned down by [`Target::abi_required_features`]. + InternalOnly { + reason: "windowed changes the Xtensa calling convention", + hard_error: false, + }, + &["exception"], + ), + ("loop", Unstable(sym::xtensa_target_feature), &[]), + ("sext", Unstable(sym::xtensa_target_feature), &[]), + ("nsa", Unstable(sym::xtensa_target_feature), &[]), + ("mul32", Unstable(sym::xtensa_target_feature), &[]), + ("mul32high", Unstable(sym::xtensa_target_feature), &["mul32"]), + ("div32", Unstable(sym::xtensa_target_feature), &[]), + ("mac16", Unstable(sym::xtensa_target_feature), &[]), + ("s32c1i", Unstable(sym::xtensa_target_feature), &[]), + ("threadptr", Unstable(sym::xtensa_target_feature), &[]), + ("extendedl32r", Unstable(sym::xtensa_target_feature), &[]), + ("debug", Unstable(sym::xtensa_target_feature), &["exception"]), + ("exception", Unstable(sym::xtensa_target_feature), &[]), + ("rvector", Unstable(sym::xtensa_target_feature), &["exception"]), + ("prid", Unstable(sym::xtensa_target_feature), &[]), + ("regprotect", Unstable(sym::xtensa_target_feature), &[]), + ("miscsr", Unstable(sym::xtensa_target_feature), &[]), +]; +pub(super) const TARGET_FEATURE_IMPLICATIONS_RAW: &[&[(&str, Stability, ImpliedFeatures)]] = &[ + ARM_FEATURES, + AARCH64_FEATURES, + X86_FEATURES, + HEXAGON_FEATURES, + POWERPC_FEATURES, + MIPS_FEATURES, + NVPTX_FEATURES, + RISCV_FEATURES, + WASM_FEATURES, + BPF_FEATURES, + CSKY_FEATURES, + LOONGARCH_FEATURES, + IBMZ_FEATURES, + SPARC_FEATURES, + M68K_FEATURES, + AVR_FEATURES, + XTENSA_FEATURES, +]; + +#[expect(non_upper_case_globals, reason = "stubs for rustc_target")] +mod sym { + pub(in super::super) const aarch64_unstable_target_feature: () = (); + pub(in super::super) const aarch64_ver_target_feature: () = (); + pub(in super::super) const apx_target_feature: () = (); + pub(in super::super) const arm_target_feature: () = (); + pub(in super::super) const avr_target_feature: () = (); + pub(in super::super) const avx10_target_feature: () = (); + pub(in super::super) const bpf_target_feature: () = (); + pub(in super::super) const clflushopt_target_feature: () = (); + pub(in super::super) const csky_target_feature: () = (); + pub(in super::super) const ermsb_target_feature: () = (); + pub(in super::super) const fma4_target_feature: () = (); + pub(in super::super) const hexagon_target_feature: () = (); + pub(in super::super) const lahfsahf_target_feature: () = (); + pub(in super::super) const loongarch_target_feature: () = (); + pub(in super::super) const m68k_target_feature: () = (); + pub(in super::super) const mips_target_feature: () = (); + pub(in super::super) const movdir64b_target_feature: () = (); + pub(in super::super) const movdiri_target_feature: () = (); + pub(in super::super) const movrs_target_feature: () = (); + pub(in super::super) const nvptx_target_feature: () = (); + pub(in super::super) const powerpc_target_feature: () = (); + pub(in super::super) const prfchw_target_feature: () = (); + pub(in super::super) const riscv_target_feature: () = (); + pub(in super::super) const rtm_target_feature: () = (); + pub(in super::super) const s390x_target_feature: () = (); + pub(in super::super) const sparc_target_feature: () = (); + pub(in super::super) const wasm_target_feature: () = (); + pub(in super::super) const x86_amx_intrinsics: () = (); + pub(in super::super) const x87_target_feature: () = (); + pub(in super::super) const xop_target_feature: () = (); + pub(in super::super) const xtensa_target_feature: () = (); +} +// spellchecker:on diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 06a2627bdb09e..a95b3aa5a6d3c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -13,7 +13,7 @@ use ide_db::{ }; use itertools::{Itertools, izip}; use syntax::{ - AstNode, NodeOrToken, SyntaxKind, TextRange, + AstNode, NodeOrToken, SyntaxKind, T, TextRange, ast::{ self, HasArgList, HasGenericArgs, Pat, PathExpr, edit::{AstNodeEdit, IndentLevel}, @@ -357,6 +357,7 @@ fn inline<'db>( original_indentation: IndentLevel, ) -> ast::Expr { let make = file_editor.make(); + // Do not use original range as the body may be generated by a macro without mapping let file_id = sema.hir_file_for(fn_body.syntax()); // Capture before `with_ast_node` re-roots and loses the source-relative position. @@ -365,6 +366,7 @@ fn inline<'db>( let (editor, body) = SyntaxEditor::with_ast_node(fn_body); let usages_for_locals = |local| { + let body_root = fn_body.syntax().tree_top(); Definition::Local(local) .usages(sema) .all() @@ -372,6 +374,7 @@ fn inline<'db>( .remove(&function_def_file_id) .unwrap_or_default() .into_iter() + .filter(move |it| it.name.syntax().tree_top() == body_root) }; let param_use_nodes: Vec> = params .iter() @@ -483,6 +486,27 @@ fn inline<'db>( for usage in &self_token_usages { editor.replace(usage.clone(), this_token.clone()); } + // Due to the difficulty in handling the parameters referenced by macro calls + // in macro generation functions, so add a syntax-based fallback + let mut depth = 0u32; + let not_replaced = |it: &syntax::SyntaxElement| { + self_token_usages + .iter() + .all(|usage| !usage.text_range().contains_range(it.text_range())) + }; + let is_item_like = |kind| ast::Item::can_cast(kind) && !ast::MacroCall::can_cast(kind); + for event in body.syntax().preorder_with_tokens() { + match event { + syntax::WalkEvent::Enter(it) if is_item_like(it.kind()) => depth += 1, + syntax::WalkEvent::Leave(it) if is_item_like(it.kind()) => depth -= 1, + syntax::WalkEvent::Enter(it) + if it.kind() == T![self] && depth == 0 && not_replaced(&it) => + { + editor.replace(it, this_token.clone()); + } + _ => (), + } + } }; // Inline parameter expressions or generate `let` statements depending on whether inlining works or not. @@ -623,10 +647,15 @@ fn inline<'db>( body = ast::BlockExpr::cast(body_prettified).unwrap(); } + fn reindent(value: T) -> T { + value.reset_indent().indent(1.into()) + } let is_async_fn = function.is_async(sema.db); if is_async_fn { cov_mark::hit!(inline_call_async_fn); - body = make.async_move_block_expr(body.statements(), body.tail_expr()); + body = make + .async_move_block_expr(body.statements().map(reindent), body.tail_expr().map(reindent)); + original_body_indent = IndentLevel(0); // Arguments should be evaluated outside the async block, and then moved into it. if !let_stmts.is_empty() { @@ -636,8 +665,9 @@ fn inline<'db>( } } else if !let_stmts.is_empty() { // Prepend let statements to the body's existing statements - let stmts: Vec = let_stmts.into_iter().chain(body.statements()).collect(); - body = make.block_expr(stmts, body.tail_expr()); + let stmts: Vec = + let_stmts.into_iter().chain(body.statements().map(reindent)).collect(); + body = make.block_expr(stmts, body.tail_expr().map(reindent)); original_body_indent = IndentLevel(0); } @@ -1965,6 +1995,64 @@ pub fn main() { #[test] fn inline_call_with_reference_in_macros() { + check_assist( + inline_call, + r#" +macro_rules! identity { ($($t:tt)*) => { $($t)* }; } +struct Foo; +impl Foo { + fn foo(self, r1: u32, r2: u32, (complex,): (u32,)) { + identity! { + let _ = self; + let _ = r1; + let _ = (r2, r2); + let _ = complex; + } + impl Foo { + fn nested(self) { _ = self; } + } + } +} +fn bar() { + Foo.$0foo(1, 2, (3,)); +} +"#, + r#" +macro_rules! identity { ($($t:tt)*) => { $($t)* }; } +struct Foo; +impl Foo { + fn foo(self, r1: u32, r2: u32, (complex,): (u32,)) { + identity! { + let _ = self; + let _ = r1; + let _ = (r2, r2); + let _ = complex; + } + impl Foo { + fn nested(self) { _ = self; } + } + } +} +fn bar() { + { + let this = Foo; + let r1 = 1; + let r2 = 2; + let (complex,) = (3,); + identity! { + let _ = this; + let _ = r1; + let _ = (r2, r2); + let _ = complex; + } + impl Foo { + fn nested(self) { _ = self; } + } + }; +} +"#, + ); + check_assist( inline_call, r#" @@ -2003,7 +2091,7 @@ fn _hash2(self_: &u64, state: &mut u64) { }; } "#, - ) + ); } #[test] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index fb6a747a64803..07ac8675dab57 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -5,7 +5,7 @@ use std::{collections::hash_map, ops::ControlFlow}; use hir::{Complete, Function, HasContainer, ItemContainer, MethodCandidateCallback, Name}; use ide_db::{FxHashMap, FxHashSet}; use itertools::Either; -use syntax::SmolStr; +use syntax::{AstNode, SmolStr, ast}; use crate::{ CompletionItem, CompletionItemKind, Completions, @@ -150,6 +150,17 @@ pub(crate) fn complete_undotted_self( _ => return, }; + let receiver = + path_ctx.original_path.as_ref().and_then(|it| ast::Expr::cast(it.syntax().parent()?)); + let fake_dot_access = &DotAccess { + receiver, + receiver_ty: None, + kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }, + ctx: DotAccessExprCtx { + in_block_expr: expr_ctx.in_block_expr, + in_breakable: expr_ctx.in_breakable, + }, + }; let (param_name, ty) = match self_param { Either::Left(self_param) => ("self", &self_param.ty(ctx.db)), Either::Right(this_param) => ("this", this_param.ty()), @@ -159,21 +170,7 @@ pub(crate) fn complete_undotted_self( ctx, ty, |acc, field, ty| { - acc.add_field( - ctx, - &DotAccess { - receiver: None, - receiver_ty: None, - kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }, - ctx: DotAccessExprCtx { - in_block_expr: expr_ctx.in_block_expr, - in_breakable: expr_ctx.in_breakable, - }, - }, - Some(SmolStr::new_static(param_name)), - field, - &ty, - ) + acc.add_field(ctx, fake_dot_access, Some(SmolStr::new_static(param_name)), field, &ty) }, |acc, field, ty| { acc.add_tuple_field(ctx, Some(SmolStr::new_static(param_name)), field, &ty) @@ -181,21 +178,7 @@ pub(crate) fn complete_undotted_self( false, ); complete_methods(ctx, ty, &ctx.traits_in_scope(), |func| { - acc.add_method( - ctx, - &DotAccess { - receiver: None, - receiver_ty: None, - kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }, - ctx: DotAccessExprCtx { - in_block_expr: expr_ctx.in_block_expr, - in_breakable: expr_ctx.in_breakable, - }, - }, - func, - Some(SmolStr::new_static(param_name)), - None, - ) + acc.add_method(ctx, fake_dot_access, func, Some(SmolStr::new_static(param_name)), None) }); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs index bea829465552d..b0d34bfc44ecb 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs @@ -41,15 +41,19 @@ pub(crate) fn complete_mod( } let module_definition_file = - current_module.definition_source_file_id(ctx.db).original_file(ctx.db); - let source_root_id = - ctx.db.file_source_root(module_definition_file.file_id(ctx.db)).source_root_id(ctx.db); + current_module.definition_source_file_id(ctx.db).original_file(ctx.db).file_id(ctx.db); + let source_root_id = ctx.db.file_source_root(module_definition_file).source_root_id(ctx.db); let source_root = ctx.db.source_root(source_root_id).source_root(ctx.db); + let crate_roots = base_db::all_crates(ctx.db) + .iter() + .map(|krate| krate.root_file_id(ctx.db).file_id(ctx.db)) + .collect::>(); let directory_to_look_for_submodules = directory_to_look_for_submodules( current_module, ctx.db, - source_root.path_for_file(&module_definition_file.file_id(ctx.db))?, + crate_roots.contains(&module_definition_file), + source_root.path_for_file(&module_definition_file)?, )?; let existing_mod_declarations = current_module @@ -65,9 +69,7 @@ pub(crate) fn complete_mod( source_root .iter() - .filter(|&submodule_candidate_file| { - submodule_candidate_file != module_definition_file.file_id(ctx.db) - }) + .filter(|&submodule_candidate_file| submodule_candidate_file != module_definition_file) .filter(|&submodule_candidate_file| { module_declaration_file.is_none_or(|it| it.file_id(ctx.db) != submodule_candidate_file) }) @@ -75,11 +77,10 @@ pub(crate) fn complete_mod( let submodule_path = source_root.path_for_file(&submodule_file)?; let directory_with_submodule = submodule_path.parent()?; let (name, ext) = submodule_path.name_and_extension()?; - if ext != Some("rs") { + if ext != Some("rs") || crate_roots.contains(&submodule_file) { return None; } match name { - "lib" | "main" => None, "mod" => { if directory_with_submodule.parent()? == directory_to_look_for_submodules { match directory_with_submodule.name_and_extension()? { @@ -118,6 +119,7 @@ pub(crate) fn complete_mod( fn directory_to_look_for_submodules( module: Module, db: &RootDatabase, + is_root: bool, module_file_path: &VfsPath, ) -> Option { let directory_with_module_path = module_file_path.parent()?; @@ -126,7 +128,8 @@ fn directory_to_look_for_submodules( return None; } let base_directory = match name { - "mod" | "lib" | "main" => Some(directory_with_module_path), + "mod" => Some(directory_with_module_path), + _ if is_root => Some(directory_with_module_path), regular_rust_file_name => { if matches!( ( @@ -225,6 +228,68 @@ mod $0 ); } + #[test] + fn exclude_crate_roots() { + check( + r#" +//- /lib.rs crate:lib +mod $0 +//- /main.rs crate:main +//- /sub.rs +"#, + expect![[r#" + md sub; + "#]], + ); + check( + r#" +//- /main.rs crate:main +mod $0 +//- /lib.rs crate:lib +//- /sub.rs +"#, + expect![[r#" + md sub; + "#]], + ); + } + + #[test] + fn contained_submodule_name_same_as_root() { + check( + r#" +//- /lib.rs +mod sub { + mod $0 +} +//- /sub/lib.rs +//- /sub/main.rs +"#, + expect![[r#" + md lib; + md main; + "#]], + ); + } + + #[test] + fn inside_name_same_as_root() { + check( + r#" +//- /foo/lib.rs +mod $0 +//- /foo/lib/loader.rs +//- /lib.rs +mod foo { + mod lib; +} +"#, + expect![[r#" + md loader; + "#]], + ); + } + #[test] fn main_module_completion() { check( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs index 7432c5226bfad..a93679a2b9d79 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs @@ -31,8 +31,8 @@ pub(crate) fn complete_expr_snippet( } if in_block_expr { - snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc, ctx.db); - snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc, ctx.db); + snippet(ctx, cap, "pd", "eprintln!(\"$1 = {:?}\", $1);").add_to(acc, ctx.db); + snippet(ctx, cap, "ppd", "eprintln!(\"$1 = {:#?}\", $1);").add_to(acc, ctx.db); let item = snippet( ctx, cap, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 95c966d609818..3dadc97d0730e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -3582,6 +3582,29 @@ fn main() { fn main() fn() [] "#]], ); + check_relevance( + r#" +struct S { info: u32 } +impl S { + fn info(&self) -> u32 { self.info } + fn foo(&self) { + needs(i$0); + } +} +fn needs(info: &mut u32) {} + "#, + expect![[r#" + fd self.info u32 [name] + fd &mut self.info [type+name] + me self.info() fn(&self) -> u32 [name] + me &mut self.info() [type+name] + lc self &S [local] + st S S [] + sp Self S [] + fn needs(…) fn(&mut u32) [] + me self.foo() fn(&self) [] + "#]], + ); // Regression test https://github.com/rust-lang/rust-analyzer/issues/22324 check_relevance( r#" diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 0ed4d7c9c648e..446c60fb1496a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -121,7 +121,7 @@ fn render( } else { compute_type_match(completion, &ctx.completion.rebase_ty(&func.ty(db))) }, - exact_name_match: compute_exact_name_match(completion, &call), + exact_name_match: compute_exact_name_match(completion, name.as_str()), function, trait_: trait_info, is_skipping_completion: matches!(func_kind, FuncKind::Method(_, Some(_))), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs index 465f59559d294..d1ddd114cb4c2 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs @@ -49,6 +49,68 @@ fn f(x: u8, c: char) { _ => {} } } +"#, + ); + } + + #[test] + fn inferred_invalid_type_range_patterns() { + check_diagnostics( + r#" +trait Zero { + const ZERO: Self; +} + +struct S; + +impl Zero for S { + const ZERO: Self = S; +} + +fn f() { + match S { + Zero::ZERO..=Zero::ZERO => {} + //^^^^^^^^^^^^^^^^^^^^^^^ error: only `char` and numeric types are allowed in range patterns + Zero::ZERO.. => {} + //^^^^^^^^^^^^ error: only `char` and numeric types are allowed in range patterns + ..Zero::ZERO => {} + //^^^^^^^^^^^^ error: only `char` and numeric types are allowed in range patterns + _ => {} + } +} +"#, + ); + } + + #[test] + fn inferred_valid_type_range_patterns() { + check_diagnostics( + r#" +trait Zero { + const ZERO: Self; +} + +impl Zero for u8 { + const ZERO: Self = 0; +} + +impl Zero for char { + const ZERO: Self = '0'; +} + +fn f(x: u8) { + match x { + Zero::ZERO..=Zero::ZERO => {} + _ => {} + } +} + +fn g(x: char) { + match x { + Zero::ZERO..=Zero::ZERO => {} + _ => {} + } +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index d4147f38b2aaf..fbcd5d672ebc1 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -68,7 +68,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = ])); pub(in crate::grammar) const EXPR_RECOVERY_SET: TokenSet = - TokenSet::new(&[T!['}'], T![')'], T![']'], T![,]]); + TokenSet::new(&[T!['('], T!['}'], T![')'], T![']'], T![,]]); pub(super) fn atom_expr( p: &mut Parser<'_>, diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs index 88a43972329ba..593b7dbafd236 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs @@ -44,6 +44,7 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[ T![macro], T![;], ]); +const ITEM_PAREN_RECOVERY_SET: TokenSet = ITEM_RECOVERY_SET.union(TokenSet::new(&[T!['(']])); pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) { let m = p.start(); @@ -432,7 +433,9 @@ fn macro_def(p: &mut Parser<'_>, m: Marker) { fn fn_(p: &mut Parser<'_>, m: Marker) { p.bump(T![fn]); - name_r(p, ITEM_RECOVERY_SET); + // test_err function_missing_name + // fn () {} + name_r(p, ITEM_PAREN_RECOVERY_SET); // test function_type_params // fn foo(){} generic_params::opt_generic_param_list(p); diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs index 71e536c35896b..30a4f67865ec0 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs @@ -867,6 +867,10 @@ mod err { run_and_expect_errors("test_data/parser/inline/err/fn_ret_recovery.rs"); } #[test] + fn function_missing_name() { + run_and_expect_errors("test_data/parser/inline/err/function_missing_name.rs"); + } + #[test] fn function_ret_type_missing_arrow() { run_and_expect_errors("test_data/parser/inline/err/function_ret_type_missing_arrow.rs"); } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/function_missing_name.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/function_missing_name.rast new file mode 100644 index 0000000000000..02de0263ad98b --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/function_missing_name.rast @@ -0,0 +1,14 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + R_CURLY "}" + WHITESPACE "\n" +error 2: expected a name diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/function_missing_name.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/function_missing_name.rs new file mode 100644 index 0000000000000..a0f0fb1bf5671 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/function_missing_name.rs @@ -0,0 +1 @@ +fn () {} diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 5865509a201af..72c667451d374 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -290,12 +290,21 @@ pub struct CargoMetadataConfig { /// Extra env vars to set when invoking the cargo command pub extra_env: FxHashMap>, /// What kind of metadata are we fetching: workspace, rustc, or sysroot. - pub kind: &'static str, + pub kind: CargoMetadataKind, /// The toolchain version, if known. /// Used to conditionally enable unstable cargo features. pub toolchain_version: Option, } +#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] +pub enum CargoMetadataKind { + #[default] + Workspace, + DetachedFile, + Rustc, + Sysroot, +} + // Deserialize helper for the cargo metadata #[derive(Deserialize, Default)] struct PackageMetadata { @@ -595,7 +604,7 @@ pub(crate) struct FetchMetadata { manifest_path: ManifestPath, lockfile_copy: Option, #[expect(dead_code)] - kind: &'static str, + kind: CargoMetadataKind, no_deps: bool, no_deps_result: anyhow::Result, other_options: Vec, @@ -662,10 +671,18 @@ impl FetchMetadata { if cargo_toml.is_rust_manifest() { other_options.push("-Zscript".to_owned()); } else if let Some(v) = config.toolchain_version.as_ref() { - lockfile_copy = make_lockfile_copy( - v, - &<_ as AsRef>::as_ref(cargo_toml).with_extension("lock"), - ); + let manifest: &Utf8Path = cargo_toml.as_ref(); + let lockfile_path = if config.kind == CargoMetadataKind::Rustc { + // The `rustc-dev` component ships `rustc-src/rust/compiler/rustc/Cargo.toml` + // without the workspace root manifest, so the lockfile at + // `rustc-src/rust/Cargo.lock` is neither next to the manifest nor discoverable + // by cargo. Without a copy of it, `cargo metadata --locked` fails and we degrade + // to `--no-deps` metadata, losing all rustc crates (e.g. `rustc_middle`). + manifest.ancestors().nth(3).map(|dir| dir.join("Cargo.lock")) + } else { + Some(manifest.with_extension("lock")) + }; + lockfile_copy = lockfile_path.and_then(|path| make_lockfile_copy(v, &path)); } if !config.targets.is_empty() { diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 7f55ab0a727e8..db3cecb5b2a31 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -28,7 +28,9 @@ use crate::{ WorkspaceBuildScripts, build_dependencies::{BuildScriptOutput, ProcMacroDylibPath}, cargo_config_file::CargoConfigFile, - cargo_workspace::{CargoMetadataConfig, DepKind, FetchMetadata, PackageData, RustLibSource}, + cargo_workspace::{ + CargoMetadataConfig, CargoMetadataKind, DepKind, FetchMetadata, PackageData, RustLibSource, + }, env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env}, project_json::{Crate, CrateArrayIdx}, sysroot::RustLibSrcWorkspace, @@ -296,7 +298,7 @@ impl ProjectWorkspace { config_path: config_path.clone(), extra_env: extra_env.clone(), toolchain_version: toolchain.clone(), - kind: "workspace", + kind: CargoMetadataKind::Workspace, }, &sysroot, *no_deps, @@ -357,7 +359,7 @@ impl ProjectWorkspace { config_path: config_path.clone(), extra_env: extra_env.clone(), toolchain_version: toolchain.clone(), - kind: "rustc-dev" + kind: CargoMetadataKind::Rustc }, &sysroot, *no_deps, @@ -602,7 +604,7 @@ impl ProjectWorkspace { config_path: config.config_path.clone(), extra_env: config.extra_env.clone(), toolchain_version: toolchain.clone(), - kind: "detached-file", + kind: CargoMetadataKind::DetachedFile, }, &sysroot, config.no_deps, @@ -1999,6 +2001,6 @@ fn sysroot_metadata_config( // extra_args. extra_env: config.extra_env.clone(), toolchain_version, - kind: "sysroot", + kind: CargoMetadataKind::Sysroot, } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index a9759ebed0cf9..3cd7a9ac9282e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -719,10 +719,10 @@ impl GlobalState { let fetch_semantic = self.vfs_done && self.fetch_workspaces_queue.last_op_result().is_some() && (!self.config.run_build_scripts(None) - || (self.fetch_build_data_queue.last_op_result().is_none() + || (self.fetch_build_data_queue.last_op_result().is_some() && !self.fetch_build_data_queue.op_in_progress())) && (!self.config.expand_proc_macros() - || (self.fetch_proc_macros_queue.last_op_result().is_none() + || (self.fetch_proc_macros_queue.last_op_result().is_some() && !self.fetch_proc_macros_queue.op_in_progress())); move |sender| { // We aren't observing the semantics token cache here @@ -821,7 +821,7 @@ impl GlobalState { fn update_status_or_notify(&mut self) { let status = self.current_status(); if self.last_reported_status != status { - self.last_reported_status = status.clone(); + let old_status = std::mem::replace(&mut self.last_reported_status, status.clone()); if self.config.server_status_notification() { self.send_notification::(status); @@ -829,7 +829,7 @@ impl GlobalState { health @ (lsp_ext::Health::Warning | lsp_ext::Health::Error), Some(message), ) = (status.health, &status.message) - && self.last_reported_status.message != status.message + && old_status.message != status.message { let open_log_button = tracing::enabled!(tracing::Level::ERROR) && (self.fetch_build_data_error().is_err() diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 8a3ea34394a31..3ad39c50ec60e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1681,3 +1681,57 @@ fn test() { assert_eq!(arr.len(), 1); expect![[r#"{"goal":"Goal { param_env: ParamEnv { clauses: [] }, predicate: Binder { value: TraitPredicate(usize: Trait, polarity:Positive), bound_vars: [] } }","result":"Err(NoSolution)","depth":0,"candidates":[]}"#]].assert_eq(&arr[0].to_string()); } + +#[test] +fn test_push_semantic_diagnostics() { + if skip_slow_tests() { + return; + } + + let code = r#" +fn main() { + let _: i32 = true; +} +"#; + let server = Project::with_fixture(&format!( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/main.rs +{code}"# + )) + .with_config(serde_json::json!({ + "cargo": { + "buildScripts": { + "enable": true, + }, + }, + "procMacro": { + "enable": true, + }, + })) + .server() + .wait_until_workspace_is_loaded(); + + server.notification::(DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: server.doc_id("src/main.rs").uri, + language_id: LanguageKind::Rust, + version: 0, + text: code.to_owned(), + }, + }); + + let diagnostics = server.wait_for_diagnostics(); + assert!( + diagnostics.diagnostics.iter().any(|d| matches!( + &d.message, + lsp_types::Message::String(s) if s.contains("expected i32, found bool") + )), + "expected type mismatch diagnostic, got: {:?}", + diagnostics.diagnostics, + ); +} diff --git a/src/tools/rust-analyzer/crates/stdx/src/tempfile.rs b/src/tools/rust-analyzer/crates/stdx/src/tempfile.rs index 8907f4ca18b80..1498f0322bb50 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/tempfile.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/tempfile.rs @@ -21,7 +21,7 @@ impl NamedTempFile { /// Creates a new `NamedTempFile` that is a copy of an existing file. pub fn new_from_existing(prefix: &str, existing: &Path) -> io::Result { let result = NamedTempFile::new(prefix)?; - std::fs::copy(existing, &result.path)?; + io::copy(&mut File::open(existing)?, &mut File::options().write(true).open(&result.path)?)?; Ok(result) } @@ -160,10 +160,12 @@ mod imp { const FILE_ATTRIBUTE_TEMPORARY: u32 = 0x100; const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; + const GENERIC_READ: u32 = 0x80000000; pub(super) fn create(prefix: &str) -> io::Result { let (file, path) = general_imp::create(prefix, |mut options, path| { options + .access_mode(GENERIC_READ) .attributes(FILE_ATTRIBUTE_TEMPORARY) .custom_flags(FILE_FLAG_DELETE_ON_CLOSE) .open(path) @@ -194,6 +196,39 @@ mod tests { use super::*; + #[test] + fn named_temp_file_new_from_existing_copies_file() { + let dir = NamedTempDir::new("test-").unwrap(); + let source = dir.path().join("source"); + fs::write(&source, b"contents").unwrap(); + + let file = NamedTempFile::new_from_existing("test-copy-", &source).unwrap(); + assert_eq!(fs::read(file.path()).unwrap(), b"contents"); + fs::write(&source, b"changed").unwrap(); + assert_eq!(fs::read(file.path()).unwrap(), b"contents"); + + let path = file.path().to_owned(); + drop(file); + assert!(!fs::exists(path).unwrap()); + assert_eq!(fs::read(source).unwrap(), b"changed"); + } + + #[cfg(windows)] + #[test] + fn named_temp_file_allows_read_only_sharing() { + use std::os::windows::fs::OpenOptionsExt; + + const FILE_SHARE_READ: u32 = 1; + const FILE_SHARE_DELETE: u32 = 4; + + let file = NamedTempFile::new("test-").unwrap(); + let _reader = fs::OpenOptions::new() + .read(true) + .share_mode(FILE_SHARE_READ | FILE_SHARE_DELETE) + .open(file.path()) + .unwrap(); + } + #[test] fn named_temp_file_new_creates_file() { let file = NamedTempFile::new("test-").unwrap(); diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index a9df1acdae9a7..b2ff2c08fb9a8 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -9,6 +9,9 @@ edition.workspace = true license.workspace = true rust-version.workspace = true +[package.metadata.cargo-machete] +ignored = ["unicode-ident"] + [lib] doctest = false @@ -27,6 +30,10 @@ smallvec.workspace = true parser.workspace = true stdx.workspace = true +# This is a transitive dep, but we need to specify this +# for the workspace-wide pinning +unicode-ident.workspace = true + [dev-dependencies] rayon.workspace = true expect-test = "1.5.1" diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml index 8ba63ae868655..fbe5febc01ccc 100644 --- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml +++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml @@ -3,7 +3,7 @@ name = "toolchain" version = "0.0.0" repository.workspace = true description = "Discovery of `cargo` & `rustc` executables for rust-analyzer." - +publish = false authors.workspace = true edition.workspace = true license.workspace = true diff --git a/src/tools/rust-analyzer/lib/smol_str/CHANGELOG.md b/src/tools/rust-analyzer/lib/smol_str/CHANGELOG.md index 6327275d07dcb..1980f484c39b9 100644 --- a/src/tools/rust-analyzer/lib/smol_str/CHANGELOG.md +++ b/src/tools/rust-analyzer/lib/smol_str/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.3.7 - 2026-10-20 + +- Add `SmolStr::INLINE_CAP` +- Add some missing methods and trait implements for `SmolStr` and `SmolStrBuilder` +- Fix incorrect `eq` implements for `SmolStrBuilder` +- Fix borsh deserialization off-by-one for inline threshold + ## 0.3.6 - 2026-03-04 - Fix the `borsh` feature. diff --git a/src/tools/rust-analyzer/lib/smol_str/Cargo.toml b/src/tools/rust-analyzer/lib/smol_str/Cargo.toml index 719462bc9a5d9..a42940fad44e7 100644 --- a/src/tools/rust-analyzer/lib/smol_str/Cargo.toml +++ b/src/tools/rust-analyzer/lib/smol_str/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "smol_str" -version = "0.3.6" +version = "0.3.7" description = "small-string optimized string type with O(1) clone" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/smol_str" diff --git a/src/tools/rust-analyzer/lib/smol_str/src/lib.rs b/src/tools/rust-analyzer/lib/smol_str/src/lib.rs index c592cb25d2373..63e3d42e11b37 100644 --- a/src/tools/rust-analyzer/lib/smol_str/src/lib.rs +++ b/src/tools/rust-analyzer/lib/smol_str/src/lib.rs @@ -947,7 +947,7 @@ mod private { macro_rules! format_smolstr { ($($tt:tt)*) => {{ let mut w = $crate::SmolStrBuilder::new(); - ::core::fmt::Write::write_fmt(&mut w, format_args!($($tt)*)).expect("a formatting trait implementation returned an error"); + ::core::fmt::Write::write_fmt(&mut w, ::core::format_args!($($tt)*)).expect("a formatting trait implementation returned an error"); w.finish() }}; } diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs index f8a7f1875539a..d4720accc54dd 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen.rs @@ -16,6 +16,7 @@ pub(crate) mod feature_docs; mod grammar; mod lints; mod parser_inline_tests; +mod target_features; impl flags::Codegen { pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { @@ -26,8 +27,10 @@ impl flags::Codegen { parser_inline_tests::generate(self.check); feature_docs::generate(self.check); diagnostics_docs::generate(self.check); - // lints::generate(self.check) Updating clones the rust repo, so don't run it unless + // Updating clones the rust repo, so don't run these unless // explicitly asked for + // lints::generate(self.check); + // target_features::generate(self.check); } flags::CodegenType::Grammar => grammar::generate(self.check), flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check), @@ -35,6 +38,7 @@ impl flags::Codegen { flags::CodegenType::LintDefinitions => lints::generate(self.check), flags::CodegenType::ParserTests => parser_inline_tests::generate(self.check), flags::CodegenType::FeatureDocs => feature_docs::generate(self.check), + flags::CodegenType::TargetFeatures => target_features::generate(self.check), } Ok(()) } @@ -218,3 +222,24 @@ fn ensure_file_contents(cg: CodegenType, file: &Path, contents: &str, check: boo fn normalize_newlines(s: &str) -> String { s.replace("\r\n", "\n") } + +/// Performs a shallow clone of rust-lang/rust and returns the path to the cloned repository root +fn clone_rust(sh: &Shell) -> PathBuf { + let rust_repo = project_root().join("./target/rust"); + if rust_repo.exists() { + cmd!(sh, "git -C {rust_repo} pull --rebase").run().unwrap(); + } else { + cmd!(sh, "git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}") + .run() + .unwrap(); + } + // need submodules for Cargo to parse the workspace correctly + cmd!( + sh, + "git -C {rust_repo} submodule update --init --recursive --depth=1 -- + compiler library src/tools src/doc/book" + ) + .run() + .unwrap(); + rust_repo +} diff --git a/src/tools/rust-analyzer/xtask/src/codegen/lints.rs b/src/tools/rust-analyzer/xtask/src/codegen/lints.rs index e4eddc5f9f6ba..bd568f19b1702 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/lints.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/lints.rs @@ -13,7 +13,7 @@ use stdx::format_to; use xshell::{Shell, cmd}; use crate::{ - codegen::{add_preamble, ensure_file_contents, reformat}, + codegen::{add_preamble, clone_rust, ensure_file_contents, reformat}, project_root, util::list_files, }; @@ -23,23 +23,7 @@ const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs"; /// This clones rustc repo, and so is not worth to keep up-to-date on a constant basis. pub(crate) fn generate(check: bool) { let sh = &Shell::new().unwrap(); - - let rust_repo = project_root().join("./target/rust"); - if rust_repo.exists() { - cmd!(sh, "git -C {rust_repo} pull --rebase").run().unwrap(); - } else { - cmd!(sh, "git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}") - .run() - .unwrap(); - } - // need submodules for Cargo to parse the workspace correctly - cmd!( - sh, - "git -C {rust_repo} submodule update --init --recursive --depth=1 -- - compiler library src/tools src/doc/book" - ) - .run() - .unwrap(); + let rust_repo = clone_rust(sh); let mut contents = String::from( r" diff --git a/src/tools/rust-analyzer/xtask/src/codegen/target_features.rs b/src/tools/rust-analyzer/xtask/src/codegen/target_features.rs new file mode 100644 index 0000000000000..325eecf2a4578 --- /dev/null +++ b/src/tools/rust-analyzer/xtask/src/codegen/target_features.rs @@ -0,0 +1,110 @@ +//! Extracts the list of target feature implications from rustc_target to a generated file that rust-analyzer can use for implications. + +use std::{collections::BTreeSet, fs, iter::repeat}; + +use itertools::Itertools; +use xshell::Shell; + +use crate::{ + codegen::{add_preamble, clone_rust, ensure_file_contents, reformat}, + project_root, +}; + +const DESTINATION: &str = "crates/hir-ty/src/target_feature/generated.rs"; + +/// This clones the rust repo, and so is not worth to keep up-to-date on a constant basis. +pub(crate) fn generate(check: bool) { + let sh = &Shell::new().unwrap(); + let rust_repo = clone_rust(sh); + let rustc_target_contents = + fs::read_to_string(rust_repo.join("compiler/rustc_target/src/target_features.rs")).unwrap(); + + let mut contents = String::from( + r#" +// spellchecker:off + +#[expect(dead_code, reason = "stubs for rustc_target")] +pub(super) enum Stability { + Stable, + Unstable(()), + InternalOnly { reason: &'static str, hard_error: bool }, +} +use Stability::*; + +type ImpliedFeatures = &'static [&'static str]; + "#, + ); + + // Identifiers of all _FEATURES arrays in rustc_target + let mut array_names = vec![]; + // Identifiers of all Unstable(sym::) feature gates + let mut unstable_feature_gates = BTreeSet::new(); + + // Whether or not the line iterator is currently in the middle of a feature list array + let mut currently_in_feature_list = false; + // Go through the file and do some manual parsing to keep only the lines that are part of a target feature array. + let target_feature_arrays = rustc_target_contents + .lines() + .filter(|line| { + if line.contains("&[(&str, Stability, ImpliedFeatures)]") { + // Start of a new feature list + assert!(!currently_in_feature_list); + currently_in_feature_list = true; + array_names.push(extract_list_ident_to_array_entry(line).unwrap()); + } else if currently_in_feature_list && *line == "];" { + // This is the end of a feature list, so ignore all lines after this one until the start of the next feature list + currently_in_feature_list = false; + return true; + } + + if currently_in_feature_list { + // Keep this line and maybe create a stub feature gate + unstable_feature_gates.extend(extract_to_unstable_feature_gate(line)); + true + } else { + false + } + }) + .interleave_shortest(repeat("\n")); + contents.extend(target_feature_arrays); + + let mut implications_raw = String::from( + "pub(super) const TARGET_FEATURE_IMPLICATIONS_RAW: &[&[(&str, Stability, ImpliedFeatures)]] = &[\n", + ); + implications_raw.extend(array_names); + implications_raw.push_str("];\n"); + contents.push_str(&implications_raw); + + let mut sym = String::from( + r#" +#[expect(non_upper_case_globals, reason = "stubs for rustc_target")] +mod sym { +"#, + ); + sym.extend(unstable_feature_gates); + sym.push_str("}\n// spellchecker:on\n"); + contents.push_str(&sym); + + let contents = add_preamble(crate::flags::CodegenType::TargetFeatures, reformat(contents)); + + let destination = project_root().join(DESTINATION); + ensure_file_contents( + crate::flags::CodegenType::TargetFeatures, + destination.as_path(), + &contents, + check, + ); +} + +/// Extract the identifier of a feature list `const $ARCH_FEATURES:` or `static $ARCH_FEATURES:` to a list entry `$ARCH_FEATURES,` +fn extract_list_ident_to_array_entry(line: &str) -> Option { + let ident = line.split_once(' ')?.1.split_once(':')?.0; + Some(format!("{ident},\n")) +} + +/// Extract the identifier from `Unstable(sym::$IDENT)` and create a new mock identifier with it +fn extract_to_unstable_feature_gate(line: &str) -> Option { + let ident = line.split_once("Unstable(sym::")?.1.split_once(')')?.0; + + Some(format!("pub(in super::super) const {ident}: () = ();\n")) +} diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs index ecf38666934a0..f6040eaf68c51 100644 --- a/src/tools/rust-analyzer/xtask/src/flags.rs +++ b/src/tools/rust-analyzer/xtask/src/flags.rs @@ -210,6 +210,7 @@ pub enum CodegenType { LintDefinitions, ParserTests, FeatureDocs, + TargetFeatures, } impl fmt::Display for CodegenType { @@ -222,6 +223,7 @@ impl fmt::Display for CodegenType { Self::LintDefinitions => write!(f, "lint-definitions"), Self::ParserTests => write!(f, "parser-tests"), Self::FeatureDocs => write!(f, "feature-docs"), + Self::TargetFeatures => write!(f, "target-features"), } } } @@ -237,6 +239,7 @@ impl FromStr for CodegenType { "lint-definitions" => Ok(Self::LintDefinitions), "parser-tests" => Ok(Self::ParserTests), "feature-docs" => Ok(Self::FeatureDocs), + "target-features" => Ok(Self::TargetFeatures), _ => Err("Invalid option".to_owned()), } } diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index c61b43492ce9e..0df194066072e 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -195,9 +195,7 @@ impl ParseSess { } pub(crate) fn span_to_file_contents(&self, span: Span) -> Arc { - self.raw_psess - .source_map() - .lookup_source_file(span.data().lo) + self.raw_psess.source_map().lookup_source_file(span.lo()) } pub(crate) fn span_to_first_line_string(&self, span: Span) -> String {