authorbors <bors@rust-lang.org> 2024-06-30 20:14:40 UTC
committerbors <bors@rust-lang.org> 2024-06-30 20:14:40 UTC
log6868c831a1eb45c5150ff623cef5e42a8b8946d0
tree25442147b3a5744d947f7cdbb69ab40b92e78db5
parentef3d6fd7002500af0a985f70d3ac5152623c1396
parent40371973535621352543572c6f8e43978204ba9a

Auto merge of #127174 - matthiaskrgr:rollup-q87j6cn, r=matthiaskrgr

Rollup of 9 pull requests Successful merges: - #126018 (Remove the `box_pointers` lint.) - #126895 (Fix simd_gather documentation) - #126981 (Replace some magic booleans in match-lowering with enums) - #127038 (Update test comment) - #127053 (Update the LoongArch target documentation) - #127069 (small correction to fmt::Pointer impl) - #127157 (coverage: Avoid getting extra unexpansion info when we don't need it) - #127160 (Add a regression test for #123630) - #127161 (Improve `run-make-support` library `args` API) r? `@ghost` `@rustbot` modify labels: rollup

33 files changed, 427 insertions(+), 346 deletions(-)

compiler/rustc_lint/messages.ftl-2
......@@ -56,8 +56,6 @@ lint_builtin_asm_labels = avoid using named labels in inline assembly
5656 .help = only local labels of the form `<number>:` should be used in inline asm
5757 .note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
5858
59lint_builtin_box_pointers = type uses owned (Box type) pointers: {$ty}
60
6159lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature
6260 .previous_decl_label = `{$orig}` previously declared here
6361 .mismatch_label = this signature doesn't match the previous declaration
compiler/rustc_lint/src/builtin.rs+3-79
......@@ -24,9 +24,9 @@ use crate::fluent_generated as fluent;
2424use crate::{
2525 errors::BuiltinEllipsisInclusiveRangePatterns,
2626 lints::{
27 BuiltinAnonymousParams, BuiltinBoxPointers, BuiltinConstNoMangle,
28 BuiltinDeprecatedAttrLink, BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed,
29 BuiltinDerefNullptr, BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
27 BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
28 BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr,
29 BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
3030 BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
3131 BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
3232 BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
......@@ -56,7 +56,6 @@ use rustc_middle::bug;
5656use rustc_middle::lint::in_external_macro;
5757use rustc_middle::ty::layout::LayoutOf;
5858use rustc_middle::ty::print::with_no_trimmed_paths;
59use rustc_middle::ty::GenericArgKind;
6059use rustc_middle::ty::TypeVisitableExt;
6160use rustc_middle::ty::Upcast;
6261use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
......@@ -134,80 +133,6 @@ impl EarlyLintPass for WhileTrue {
134133 }
135134}
136135
137declare_lint! {
138 /// The `box_pointers` lints use of the Box type.
139 ///
140 /// ### Example
141 ///
142 /// ```rust,compile_fail
143 /// #![deny(box_pointers)]
144 /// struct Foo {
145 /// x: Box<i32>,
146 /// }
147 /// ```
148 ///
149 /// {{produces}}
150 ///
151 /// ### Explanation
152 ///
153 /// This lint is mostly historical, and not particularly useful. `Box<T>`
154 /// used to be built into the language, and the only way to do heap
155 /// allocation. Today's Rust can call into other allocators, etc.
156 BOX_POINTERS,
157 Allow,
158 "use of owned (Box type) heap memory"
159}
160
161declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
162
163impl BoxPointers {
164 fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
165 for leaf in ty.walk() {
166 if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
167 && leaf_ty.is_box()
168 {
169 cx.emit_span_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
170 }
171 }
172 }
173}
174
175impl<'tcx> LateLintPass<'tcx> for BoxPointers {
176 fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
177 match it.kind {
178 hir::ItemKind::Fn(..)
179 | hir::ItemKind::TyAlias(..)
180 | hir::ItemKind::Enum(..)
181 | hir::ItemKind::Struct(..)
182 | hir::ItemKind::Union(..) => self.check_heap_type(
183 cx,
184 it.span,
185 cx.tcx.type_of(it.owner_id).instantiate_identity(),
186 ),
187 _ => (),
188 }
189
190 // If it's a struct, we also have to check the fields' types
191 match it.kind {
192 hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
193 for field in struct_def.fields() {
194 self.check_heap_type(
195 cx,
196 field.span,
197 cx.tcx.type_of(field.def_id).instantiate_identity(),
198 );
199 }
200 }
201 _ => (),
202 }
203 }
204
205 fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
206 let ty = cx.typeck_results().node_type(e.hir_id);
207 self.check_heap_type(cx, e.span, ty);
208 }
209}
210
211136declare_lint! {
212137 /// The `non_shorthand_field_patterns` lint detects using `Struct { x: x }`
213138 /// instead of `Struct { x }` in a pattern.
......@@ -1640,7 +1565,6 @@ declare_lint_pass!(
16401565 /// which are used by other parts of the compiler.
16411566 SoftLints => [
16421567 WHILE_TRUE,
1643 BOX_POINTERS,
16441568 NON_SHORTHAND_FIELD_PATTERNS,
16451569 UNSAFE_CODE,
16461570 MISSING_DOCS,
compiler/rustc_lint/src/lib.rs+4-1
......@@ -187,7 +187,6 @@ late_lint_methods!(
187187 ImproperCTypesDefinitions: ImproperCTypesDefinitions,
188188 InvalidFromUtf8: InvalidFromUtf8,
189189 VariantSizeDifferences: VariantSizeDifferences,
190 BoxPointers: BoxPointers,
191190 PathStatements: PathStatements,
192191 LetUnderscore: LetUnderscore,
193192 InvalidReferenceCasting: InvalidReferenceCasting,
......@@ -551,6 +550,10 @@ fn register_builtins(store: &mut LintStore) {
551550 "converted into hard error, see RFC #3535 \
552551 <https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
553552 );
553 store.register_removed(
554 "box_pointers",
555 "it does not detect other kinds of allocations, and existed only for historical reasons",
556 );
554557}
555558
556559fn register_internals(store: &mut LintStore) {
compiler/rustc_lint/src/lints.rs-6
......@@ -66,12 +66,6 @@ pub struct BuiltinWhileTrue {
6666 pub replace: String,
6767}
6868
69#[derive(LintDiagnostic)]
70#[diag(lint_builtin_box_pointers)]
71pub struct BuiltinBoxPointers<'a> {
72 pub ty: Ty<'a>,
73}
74
7569#[derive(LintDiagnostic)]
7670#[diag(lint_builtin_non_shorthand_field_patterns)]
7771pub struct BuiltinNonShorthandFieldPatterns {
compiler/rustc_mir_build/src/build/block.rs+17-4
......@@ -1,3 +1,4 @@
1use crate::build::matches::{DeclareLetBindings, EmitStorageLive, ScheduleDrops};
12use crate::build::ForGuard::OutsideGuard;
23use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
34use rustc_middle::middle::region::Scope;
......@@ -201,7 +202,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
201202 pattern,
202203 UserTypeProjections::none(),
203204 &mut |this, _, _, node, span, _, _| {
204 this.storage_live_binding(block, node, span, OutsideGuard, true);
205 this.storage_live_binding(
206 block,
207 node,
208 span,
209 OutsideGuard,
210 ScheduleDrops::Yes,
211 );
205212 },
206213 );
207214 let else_block_span = this.thir[*else_block].span;
......@@ -213,8 +220,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
213220 pattern,
214221 None,
215222 initializer_span,
216 false,
217 true,
223 DeclareLetBindings::No,
224 EmitStorageLive::No,
218225 )
219226 });
220227 matching.and(failure)
......@@ -291,7 +298,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
291298 pattern,
292299 UserTypeProjections::none(),
293300 &mut |this, _, _, node, span, _, _| {
294 this.storage_live_binding(block, node, span, OutsideGuard, true);
301 this.storage_live_binding(
302 block,
303 node,
304 span,
305 OutsideGuard,
306 ScheduleDrops::Yes,
307 );
295308 this.schedule_drop_for_binding(node, span, OutsideGuard);
296309 },
297310 )
compiler/rustc_mir_build/src/build/expr/into.rs+3-2
......@@ -1,6 +1,7 @@
11//! See docs in build/expr/mod.rs
22
33use crate::build::expr::category::{Category, RvalueFunc};
4use crate::build::matches::DeclareLetBindings;
45use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary};
56use rustc_ast::InlineAsmOptions;
67use rustc_data_structures::fx::FxHashMap;
......@@ -86,7 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8687 cond,
8788 Some(condition_scope), // Temp scope
8889 source_info,
89 true, // Declare `let` bindings normally
90 DeclareLetBindings::Yes, // Declare `let` bindings normally
9091 ));
9192
9293 // Lower the `then` arm into its block.
......@@ -163,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
163164 source_info,
164165 // This flag controls how inner `let` expressions are lowered,
165166 // but either way there shouldn't be any of those in here.
166 true,
167 DeclareLetBindings::LetNotPermitted,
167168 )
168169 });
169170 let (short_circuit, continuation, constant) = match op {
compiler/rustc_mir_build/src/build/matches/mod.rs+130-46
......@@ -28,6 +28,7 @@ mod simplify;
2828mod test;
2929mod util;
3030
31use std::assert_matches::assert_matches;
3132use std::borrow::Borrow;
3233use std::mem;
3334
......@@ -39,9 +40,50 @@ struct ThenElseArgs {
3940 /// `self.local_scope()` is used.
4041 temp_scope_override: Option<region::Scope>,
4142 variable_source_info: SourceInfo,
43 /// Determines how bindings should be handled when lowering `let` expressions.
44 ///
4245 /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`].
43 /// When false (for match guards), `let` bindings won't be declared.
44 declare_let_bindings: bool,
46 declare_let_bindings: DeclareLetBindings,
47}
48
49/// Should lowering a `let` expression also declare its bindings?
50///
51/// Used by [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`].
52#[derive(Clone, Copy)]
53pub(crate) enum DeclareLetBindings {
54 /// Yes, declare `let` bindings as normal for `if` conditions.
55 Yes,
56 /// No, don't declare `let` bindings, because the caller declares them
57 /// separately due to special requirements.
58 ///
59 /// Used for match guards and let-else.
60 No,
61 /// Let expressions are not permitted in this context, so it is a bug to
62 /// try to lower one (e.g inside lazy-boolean-or or boolean-not).
63 LetNotPermitted,
64}
65
66/// Used by [`Builder::bind_matched_candidate_for_arm_body`] to determine
67/// whether or not to call [`Builder::storage_live_binding`] to emit
68/// [`StatementKind::StorageLive`].
69#[derive(Clone, Copy)]
70pub(crate) enum EmitStorageLive {
71 /// Yes, emit `StorageLive` as normal.
72 Yes,
73 /// No, don't emit `StorageLive`. The caller has taken responsibility for
74 /// emitting `StorageLive` as appropriate.
75 No,
76}
77
78/// Used by [`Builder::storage_live_binding`] and [`Builder::bind_matched_candidate_for_arm_body`]
79/// to decide whether to schedule drops.
80#[derive(Clone, Copy, Debug)]
81pub(crate) enum ScheduleDrops {
82 /// Yes, the relevant functions should also schedule drops as appropriate.
83 Yes,
84 /// No, don't schedule drops. The caller has taken responsibility for any
85 /// appropriate drops.
86 No,
4587}
4688
4789impl<'a, 'tcx> Builder<'a, 'tcx> {
......@@ -57,7 +99,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5799 expr_id: ExprId,
58100 temp_scope_override: Option<region::Scope>,
59101 variable_source_info: SourceInfo,
60 declare_let_bindings: bool,
102 declare_let_bindings: DeclareLetBindings,
61103 ) -> BlockAnd<()> {
62104 self.then_else_break_inner(
63105 block,
......@@ -91,13 +133,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
91133 this.then_else_break_inner(
92134 block,
93135 lhs,
94 ThenElseArgs { declare_let_bindings: true, ..args },
136 ThenElseArgs {
137 declare_let_bindings: DeclareLetBindings::LetNotPermitted,
138 ..args
139 },
95140 )
96141 });
97142 let rhs_success_block = unpack!(this.then_else_break_inner(
98143 failure_block,
99144 rhs,
100 ThenElseArgs { declare_let_bindings: true, ..args },
145 ThenElseArgs {
146 declare_let_bindings: DeclareLetBindings::LetNotPermitted,
147 ..args
148 },
101149 ));
102150
103151 // Make the LHS and RHS success arms converge to a common block.
......@@ -127,7 +175,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
127175 this.then_else_break_inner(
128176 block,
129177 arg,
130 ThenElseArgs { declare_let_bindings: true, ..args },
178 ThenElseArgs {
179 declare_let_bindings: DeclareLetBindings::LetNotPermitted,
180 ..args
181 },
131182 )
132183 });
133184 this.break_for_else(success_block, args.variable_source_info);
......@@ -147,7 +198,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
147198 Some(args.variable_source_info.scope),
148199 args.variable_source_info.span,
149200 args.declare_let_bindings,
150 false,
201 EmitStorageLive::Yes,
151202 ),
152203 _ => {
153204 let mut block = block;
......@@ -440,7 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
440491 &fake_borrow_temps,
441492 scrutinee_span,
442493 Some((arm, match_scope)),
443 false,
494 EmitStorageLive::Yes,
444495 );
445496
446497 this.fixed_temps_scope = old_dedup_scope;
......@@ -485,7 +536,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
485536 fake_borrow_temps: &[(Place<'tcx>, Local, FakeBorrowKind)],
486537 scrutinee_span: Span,
487538 arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
488 storages_alive: bool,
539 emit_storage_live: EmitStorageLive,
489540 ) -> BasicBlock {
490541 if candidate.subcandidates.is_empty() {
491542 // Avoid generating another `BasicBlock` when we only have one
......@@ -496,8 +547,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
496547 fake_borrow_temps,
497548 scrutinee_span,
498549 arm_match_scope,
499 true,
500 storages_alive,
550 ScheduleDrops::Yes,
551 emit_storage_live,
501552 )
502553 } else {
503554 // It's helpful to avoid scheduling drops multiple times to save
......@@ -515,7 +566,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
515566 // To handle this we instead unschedule it's drop after each time
516567 // we lower the guard.
517568 let target_block = self.cfg.start_new_block();
518 let mut schedule_drops = true;
569 let mut schedule_drops = ScheduleDrops::Yes;
519570 let arm = arm_match_scope.unzip().0;
520571 // We keep a stack of all of the bindings and type ascriptions
521572 // from the parent candidates that we visit, that also need to
......@@ -534,10 +585,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
534585 scrutinee_span,
535586 arm_match_scope,
536587 schedule_drops,
537 storages_alive,
588 emit_storage_live,
538589 );
539590 if arm.is_none() {
540 schedule_drops = false;
591 schedule_drops = ScheduleDrops::No;
541592 }
542593 self.cfg.goto(binding_end, outer_source_info, target_block);
543594 },
......@@ -563,8 +614,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
563614 match irrefutable_pat.kind {
564615 // Optimize the case of `let x = ...` to write directly into `x`
565616 PatKind::Binding { mode: BindingMode(ByRef::No, _), var, subpattern: None, .. } => {
566 let place =
567 self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
617 let place = self.storage_live_binding(
618 block,
619 var,
620 irrefutable_pat.span,
621 OutsideGuard,
622 ScheduleDrops::Yes,
623 );
568624 unpack!(block = self.expr_into_dest(place, block, initializer_id));
569625
570626 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
......@@ -597,8 +653,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
597653 },
598654 ascription: thir::Ascription { ref annotation, variance: _ },
599655 } => {
600 let place =
601 self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
656 let place = self.storage_live_binding(
657 block,
658 var,
659 irrefutable_pat.span,
660 OutsideGuard,
661 ScheduleDrops::Yes,
662 );
602663 unpack!(block = self.expr_into_dest(place, block, initializer_id));
603664
604665 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
......@@ -704,7 +765,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
704765 &[],
705766 irrefutable_pat.span,
706767 None,
707 false,
768 EmitStorageLive::Yes,
708769 )
709770 .unit()
710771 }
......@@ -780,13 +841,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
780841 }
781842 }
782843
844 /// Emits a [`StatementKind::StorageLive`] for the given var, and also
845 /// schedules a drop if requested (and possible).
783846 pub(crate) fn storage_live_binding(
784847 &mut self,
785848 block: BasicBlock,
786849 var: LocalVarId,
787850 span: Span,
788851 for_guard: ForGuard,
789 schedule_drop: bool,
852 schedule_drop: ScheduleDrops,
790853 ) -> Place<'tcx> {
791854 let local_id = self.var_local_id(var, for_guard);
792855 let source_info = self.source_info(span);
......@@ -794,7 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
794857 // Although there is almost always scope for given variable in corner cases
795858 // like #92893 we might get variable with no scope.
796859 if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id)
797 && schedule_drop
860 && matches!(schedule_drop, ScheduleDrops::Yes)
798861 {
799862 self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
800863 }
......@@ -1991,8 +2054,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19912054// Pat binding - used for `let` and function parameters as well.
19922055
19932056impl<'a, 'tcx> Builder<'a, 'tcx> {
1994 /// If the bindings have already been declared, set `declare_bindings` to
1995 /// `false` to avoid duplicated bindings declaration; used for if-let guards.
2057 /// Lowers a `let` expression that appears in a suitable context
2058 /// (e.g. an `if` condition or match guard).
2059 ///
2060 /// Also used for lowering let-else statements, since they have similar
2061 /// needs despite not actually using `let` expressions.
2062 ///
2063 /// Use [`DeclareLetBindings`] to control whether the `let` bindings are
2064 /// declared or not.
19962065 pub(crate) fn lower_let_expr(
19972066 &mut self,
19982067 mut block: BasicBlock,
......@@ -2000,8 +2069,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20002069 pat: &Pat<'tcx>,
20012070 source_scope: Option<SourceScope>,
20022071 scope_span: Span,
2003 declare_bindings: bool,
2004 storages_alive: bool,
2072 declare_let_bindings: DeclareLetBindings,
2073 emit_storage_live: EmitStorageLive,
20052074 ) -> BlockAnd<()> {
20062075 let expr_span = self.thir[expr_id].span;
20072076 let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
......@@ -2017,10 +2086,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20172086
20182087 self.break_for_else(otherwise_block, self.source_info(expr_span));
20192088
2020 if declare_bindings {
2021 let expr_place = scrutinee.try_to_place(self);
2022 let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
2023 self.declare_bindings(source_scope, pat.span.to(scope_span), pat, None, opt_expr_place);
2089 match declare_let_bindings {
2090 DeclareLetBindings::Yes => {
2091 let expr_place = scrutinee.try_to_place(self);
2092 let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
2093 self.declare_bindings(
2094 source_scope,
2095 pat.span.to(scope_span),
2096 pat,
2097 None,
2098 opt_expr_place,
2099 );
2100 }
2101 DeclareLetBindings::No => {} // Caller is responsible for bindings.
2102 DeclareLetBindings::LetNotPermitted => {
2103 self.tcx.dcx().span_bug(expr_span, "let expression not expected in this context")
2104 }
20242105 }
20252106
20262107 let success = self.bind_pattern(
......@@ -2029,7 +2110,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20292110 &[],
20302111 expr_span,
20312112 None,
2032 storages_alive,
2113 emit_storage_live,
20332114 );
20342115
20352116 // If branch coverage is enabled, record this branch.
......@@ -2053,8 +2134,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20532134 fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)],
20542135 scrutinee_span: Span,
20552136 arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
2056 schedule_drops: bool,
2057 storages_alive: bool,
2137 schedule_drops: ScheduleDrops,
2138 emit_storage_live: EmitStorageLive,
20582139 ) -> BasicBlock {
20592140 debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
20602141
......@@ -2203,7 +2284,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22032284 guard,
22042285 None, // Use `self.local_scope()` as the temp scope
22052286 this.source_info(arm.span),
2206 false, // For guards, `let` bindings are declared separately
2287 DeclareLetBindings::No, // For guards, `let` bindings are declared separately
22072288 )
22082289 });
22092290
......@@ -2264,12 +2345,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22642345 let cause = FakeReadCause::ForGuardBinding;
22652346 self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id));
22662347 }
2267 assert!(schedule_drops, "patterns with guards must schedule drops");
2348 assert_matches!(
2349 schedule_drops,
2350 ScheduleDrops::Yes,
2351 "patterns with guards must schedule drops"
2352 );
22682353 self.bind_matched_candidate_for_arm_body(
22692354 post_guard_block,
2270 true,
2355 ScheduleDrops::Yes,
22712356 by_value_bindings,
2272 storages_alive,
2357 emit_storage_live,
22732358 );
22742359
22752360 post_guard_block
......@@ -2281,7 +2366,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
22812366 block,
22822367 schedule_drops,
22832368 bindings,
2284 storages_alive,
2369 emit_storage_live,
22852370 );
22862371 block
22872372 }
......@@ -2317,7 +2402,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23172402 fn bind_matched_candidate_for_guard<'b>(
23182403 &mut self,
23192404 block: BasicBlock,
2320 schedule_drops: bool,
2405 schedule_drops: ScheduleDrops,
23212406 bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
23222407 ) where
23232408 'tcx: 'b,
......@@ -2370,9 +2455,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23702455 fn bind_matched_candidate_for_arm_body<'b>(
23712456 &mut self,
23722457 block: BasicBlock,
2373 schedule_drops: bool,
2458 schedule_drops: ScheduleDrops,
23742459 bindings: impl IntoIterator<Item = &'b Binding<'tcx>>,
2375 storages_alive: bool,
2460 emit_storage_live: EmitStorageLive,
23762461 ) where
23772462 'tcx: 'b,
23782463 {
......@@ -2382,21 +2467,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23822467 // Assign each of the bindings. This may trigger moves out of the candidate.
23832468 for binding in bindings {
23842469 let source_info = self.source_info(binding.span);
2385 let local = if storages_alive {
2470 let local = match emit_storage_live {
23862471 // Here storages are already alive, probably because this is a binding
23872472 // from let-else.
23882473 // We just need to schedule drop for the value.
2389 self.var_local_id(binding.var_id, OutsideGuard).into()
2390 } else {
2391 self.storage_live_binding(
2474 EmitStorageLive::No => self.var_local_id(binding.var_id, OutsideGuard).into(),
2475 EmitStorageLive::Yes => self.storage_live_binding(
23922476 block,
23932477 binding.var_id,
23942478 binding.span,
23952479 OutsideGuard,
23962480 schedule_drops,
2397 )
2481 ),
23982482 };
2399 if schedule_drops {
2483 if matches!(schedule_drops, ScheduleDrops::Yes) {
24002484 self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
24012485 }
24022486 let rvalue = match binding.binding_mode.0 {
compiler/rustc_mir_transform/src/coverage/mappings.rs+5-7
......@@ -9,9 +9,8 @@ use rustc_middle::ty::TyCtxt;
99use rustc_span::Span;
1010
1111use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
12use crate::coverage::spans::{
13 extract_refined_covspans, unexpand_into_body_span_with_visible_macro,
14};
12use crate::coverage::spans::extract_refined_covspans;
13use crate::coverage::unexpand::unexpand_into_body_span;
1514use crate::coverage::ExtractedHirInfo;
1615
1716/// Associates an ordinary executable code span with its corresponding BCB.
......@@ -202,8 +201,7 @@ pub(super) fn extract_branch_pairs(
202201 if !raw_span.ctxt().outer_expn_data().is_root() {
203202 return None;
204203 }
205 let (span, _) =
206 unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
204 let span = unexpand_into_body_span(raw_span, hir_info.body_span)?;
207205
208206 let bcb_from_marker =
209207 |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
......@@ -238,7 +236,7 @@ pub(super) fn extract_mcdc_mappings(
238236 if !raw_span.ctxt().outer_expn_data().is_root() {
239237 return None;
240238 }
241 let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?;
239 let span = unexpand_into_body_span(raw_span, body_span)?;
242240
243241 let true_bcb = bcb_from_marker(true_marker)?;
244242 let false_bcb = bcb_from_marker(false_marker)?;
......@@ -261,7 +259,7 @@ pub(super) fn extract_mcdc_mappings(
261259
262260 mcdc_decisions.extend(branch_info.mcdc_decision_spans.iter().filter_map(
263261 |decision: &mir::coverage::MCDCDecisionSpan| {
264 let (span, _) = unexpand_into_body_span_with_visible_macro(decision.span, body_span)?;
262 let span = unexpand_into_body_span(decision.span, body_span)?;
265263
266264 let end_bcbs = decision
267265 .end_markers
compiler/rustc_mir_transform/src/coverage/mod.rs+1
......@@ -6,6 +6,7 @@ mod mappings;
66mod spans;
77#[cfg(test)]
88mod tests;
9mod unexpand;
910
1011use rustc_middle::mir::coverage::{
1112 CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind,
compiler/rustc_mir_transform/src/coverage/spans.rs-5
......@@ -14,11 +14,6 @@ use crate::coverage::ExtractedHirInfo;
1414
1515mod from_mir;
1616
17// FIXME(#124545) It's awkward that we have to re-export this, because it's an
18// internal detail of `from_mir` that is also needed when handling branch and
19// MC/DC spans. Ideally we would find a more natural home for it.
20pub(super) use from_mir::unexpand_into_body_span_with_visible_macro;
21
2217pub(super) fn extract_refined_covspans(
2318 mir_body: &mir::Body<'_>,
2419 hir_info: &ExtractedHirInfo,
compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs+2-54
......@@ -4,12 +4,13 @@ use rustc_middle::mir::{
44 self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
55 TerminatorKind,
66};
7use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
7use rustc_span::{Span, Symbol};
88
99use crate::coverage::graph::{
1010 BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
1111};
1212use crate::coverage::spans::Covspan;
13use crate::coverage::unexpand::unexpand_into_body_span_with_visible_macro;
1314use crate::coverage::ExtractedHirInfo;
1415
1516pub(crate) struct ExtractedCovspans {
......@@ -215,59 +216,6 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
215216 }
216217}
217218
218/// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range
219/// within the function's body source. This span is guaranteed to be contained
220/// within, or equal to, the `body_span`. If the extrapolated span is not
221/// contained within the `body_span`, `None` is returned.
222///
223/// [^1]Expansions result from Rust syntax including macros, syntactic sugar,
224/// etc.).
225pub(crate) fn unexpand_into_body_span_with_visible_macro(
226 original_span: Span,
227 body_span: Span,
228) -> Option<(Span, Option<Symbol>)> {
229 let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?;
230
231 let visible_macro = prev
232 .map(|prev| match prev.ctxt().outer_expn_data().kind {
233 ExpnKind::Macro(MacroKind::Bang, name) => Some(name),
234 _ => None,
235 })
236 .flatten();
237
238 Some((span, visible_macro))
239}
240
241/// Walks through the expansion ancestors of `original_span` to find a span that
242/// is contained in `body_span` and has the same [`SyntaxContext`] as `body_span`.
243/// The ancestor that was traversed just before the matching span (if any) is
244/// also returned.
245///
246/// For example, a return value of `Some((ancestor, Some(prev))` means that:
247/// - `ancestor == original_span.find_ancestor_inside_same_ctxt(body_span)`
248/// - `ancestor == prev.parent_callsite()`
249///
250/// [`SyntaxContext`]: rustc_span::SyntaxContext
251fn unexpand_into_body_span_with_prev(
252 original_span: Span,
253 body_span: Span,
254) -> Option<(Span, Option<Span>)> {
255 let mut prev = None;
256 let mut curr = original_span;
257
258 while !body_span.contains(curr) || !curr.eq_ctxt(body_span) {
259 prev = Some(curr);
260 curr = curr.parent_callsite()?;
261 }
262
263 debug_assert_eq!(Some(curr), original_span.find_ancestor_in_same_ctxt(body_span));
264 if let Some(prev) = prev {
265 debug_assert_eq!(Some(curr), prev.parent_callsite());
266 }
267
268 Some((curr, prev))
269}
270
271219#[derive(Debug)]
272220pub(crate) struct Hole {
273221 pub(crate) span: Span,
compiler/rustc_mir_transform/src/coverage/unexpand.rs created+60
......@@ -0,0 +1,60 @@
1use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
2
3/// Walks through the expansion ancestors of `original_span` to find a span that
4/// is contained in `body_span` and has the same [syntax context] as `body_span`.
5pub(crate) fn unexpand_into_body_span(original_span: Span, body_span: Span) -> Option<Span> {
6 // Because we don't need to return any extra ancestor information,
7 // we can just delegate directly to `find_ancestor_inside_same_ctxt`.
8 original_span.find_ancestor_inside_same_ctxt(body_span)
9}
10
11/// Walks through the expansion ancestors of `original_span` to find a span that
12/// is contained in `body_span` and has the same [syntax context] as `body_span`.
13///
14/// If the returned span represents a bang-macro invocation (e.g. `foo!(..)`),
15/// the returned symbol will be the name of that macro (e.g. `foo`).
16pub(crate) fn unexpand_into_body_span_with_visible_macro(
17 original_span: Span,
18 body_span: Span,
19) -> Option<(Span, Option<Symbol>)> {
20 let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?;
21
22 let visible_macro = prev
23 .map(|prev| match prev.ctxt().outer_expn_data().kind {
24 ExpnKind::Macro(MacroKind::Bang, name) => Some(name),
25 _ => None,
26 })
27 .flatten();
28
29 Some((span, visible_macro))
30}
31
32/// Walks through the expansion ancestors of `original_span` to find a span that
33/// is contained in `body_span` and has the same [syntax context] as `body_span`.
34/// The ancestor that was traversed just before the matching span (if any) is
35/// also returned.
36///
37/// For example, a return value of `Some((ancestor, Some(prev)))` means that:
38/// - `ancestor == original_span.find_ancestor_inside_same_ctxt(body_span)`
39/// - `prev.parent_callsite() == ancestor`
40///
41/// [syntax context]: rustc_span::SyntaxContext
42fn unexpand_into_body_span_with_prev(
43 original_span: Span,
44 body_span: Span,
45) -> Option<(Span, Option<Span>)> {
46 let mut prev = None;
47 let mut curr = original_span;
48
49 while !body_span.contains(curr) || !curr.eq_ctxt(body_span) {
50 prev = Some(curr);
51 curr = curr.parent_callsite()?;
52 }
53
54 debug_assert_eq!(Some(curr), original_span.find_ancestor_inside_same_ctxt(body_span));
55 if let Some(prev) = prev {
56 debug_assert_eq!(Some(curr), prev.parent_callsite());
57 }
58
59 Some((curr, prev))
60}
library/core/src/fmt/mod.rs+1-2
......@@ -2484,8 +2484,7 @@ impl Display for char {
24842484#[stable(feature = "rust1", since = "1.0.0")]
24852485impl<T: ?Sized> Pointer for *const T {
24862486 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
2487 // Cast is needed here because `.expose_provenance()` requires `T: Sized`.
2488 pointer_fmt_inner((*self as *const ()).expose_provenance(), f)
2487 pointer_fmt_inner(self.expose_provenance(), f)
24892488 }
24902489}
24912490
library/core/src/intrinsics/simd.rs-3
......@@ -263,9 +263,6 @@ extern "rust-intrinsic" {
263263 ///
264264 /// `V` must be a vector of integers with the same length as `T` (but any element size).
265265 ///
266 /// `idx` must be a constant: either naming a constant item, or an inline
267 /// `const {}` expression.
268 ///
269266 /// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer.
270267 /// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from
271268 /// `val`.
src/doc/rustc/src/platform-support/loongarch-linux.md+91-48
......@@ -1,30 +1,24 @@
1# loongarch\*-unknown-linux-\*
1# `loongarch*-unknown-linux-*`
22
3**Tier: 2**
3**Tier: 2 (with Host Tools)**
44
5[LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited.
5[LoongArch][la-docs] Linux targets.
6LoongArch is a RISC ISA developed by Loongson Technology Corporation Limited.
67
7[LoongArch]: https://loongson.github.io/LoongArch-Documentation/README-EN.html
8| Target | Description |
9|--------|-------------|
10| `loongarch64-unknown-linux-gnu` | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) |
11| `loongarch64-unknown-linux-musl` | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5) |
812
9The target name follow this format: `<machine>-<vendor>-<os><fabi_suffix>`, where `<machine>` specifies the CPU family/model, `<vendor>` specifies the vendor and `<os>` the operating system name.
10While the integer base ABI is implied by the machine field, the floating point base ABI type is encoded into the os field of the specifier using the string suffix `<fabi-suffix>`.
13These support both native and cross builds, and have full support for `std`.
1114
12| `<fabi-suffix>` | `Description` |
13|------------------------|--------------------------------------------------------------------|
14| f64 | The base ABI use 64-bits FPRs for parameter passing. (lp64d)|
15| f32 | The base ABI uses 32-bit FPRs for parameter passing. (lp64f)|
16| sf | The base ABI uses no FPR for parameter passing. (lp64s) |
15Reference material:
1716
18<br>
17* [LoongArch ISA manuals][la-docs]
18* [Application Binary Interface for the LoongArch&trade; Architecture][la-abi-specs]
1919
20|`ABI type(Base ABI/ABI extension)`| `C library` | `kernel` | `target tuple` |
21|----------------------------------|-------------|----------|----------------------------------|
22| lp64d/base | glibc | linux | loongarch64-unknown-linux-gnu |
23| lp64f/base | glibc | linux | loongarch64-unknown-linux-gnuf32 |
24| lp64s/base | glibc | linux | loongarch64-unknown-linux-gnusf |
25| lp64d/base | musl libc | linux | loongarch64-unknown-linux-musl|
26| lp64f/base | musl libc | linux | loongarch64-unknown-linux-muslf32|
27| lp64s/base | musl libc | linux | loongarch64-unknown-linux-muslsf |
20[la-abi-specs]: https://github.com/loongson/la-abi-specs
21[la-docs]: https://loongson.github.io/LoongArch-Documentation/README-EN.html
2822
2923## Target maintainers
3024
......@@ -35,23 +29,57 @@ While the integer base ABI is implied by the machine field, the floating po
3529
3630## Requirements
3731
38This target is cross-compiled.
39A GNU toolchain for LoongArch target is required. It can be downloaded from https://github.com/loongson/build-tools/releases, or built from the source code of GCC (12.1.0 or later) and Binutils (2.40 or later).
32### OS Version
4033
41## Building the target
34The minimum supported Linux version is 5.19.
4235
43The target can be built by enabling it for a `rustc` build.
36Some Linux distributions, mostly commercial ones, may provide forked Linux
37kernels that has a version number less than 5.19 for their LoongArch ports.
38Such kernels may still get patched to be compatible with the upstream Linux
395.19 UAPI, therefore supporting the targets described in this document, but
40this is not always the case. The `rustup` installer contains a check for this,
41and will abort if incompatibility is detected.
42
43### Host toolchain
44
45The targets require a reasonably up-to-date LoongArch toolchain on the host.
46Currently the following components are used by the Rust CI to build the target,
47and the versions can be seen as the minimum requirement:
48
49* GNU Binutils 2.40
50* GCC 13.x
51* glibc 2.36
52* linux-headers 5.19
53
54Of these, glibc and linux-headers are at their respective earliest versions with
55mainline LoongArch support, so it is impossible to use older versions of these.
56Older versions of Binutils and GCC will not work either, due to lack of support
57for newer LoongArch ELF relocation types, among other features.
58
59Recent LLVM/Clang toolchains may be able to build the targets, but are not
60currently being actively tested.
61
62## Building
63
64These targets are distributed through `rustup`, and otherwise require no
65special configuration.
66
67If you need to build your own Rust for some reason though, the targets can be
68simply enabled in `config.toml`. For example:
4469
4570```toml
4671[build]
4772target = ["loongarch64-unknown-linux-gnu"]
4873```
4974
50Make sure `loongarch64-unknown-linux-gnu-gcc` can be searched from the directories specified in`$PATH`. Alternatively, you can use GNU LoongArch Toolchain by adding the following to `config.toml`:
75Make sure the LoongArch toolchain binaries are reachable from `$PATH`.
76Alternatively, you can explicitly configure the paths in `config.toml`:
5177
5278```toml
5379[target.loongarch64-unknown-linux-gnu]
54# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
80# Adjust the paths to point at your toolchain
81# Suppose the toolchain is placed at /TOOLCHAIN_PATH, and the cross prefix is
82# "loongarch64-unknown-linux-gnu-":
5583cc = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc"
5684cxx = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++"
5785ar = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ar"
......@@ -59,36 +87,51 @@ ranlib = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ranlib"
5987linker = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc"
6088```
6189
62## Cross-compilation
90### Cross-compilation
6391
64This target can be cross-compiled on a `x86_64-unknown-linux-gnu` host. Cross-compilation on other hosts may work but is not tested.
92This target can be cross-compiled on a `x86_64-unknown-linux-gnu` host.
93Other hosts are also likely to work, but not actively tested.
94
95You can test the cross build directly on the host, thanks to QEMU linux-user emulation.
96An example is given below:
97
98```sh
99# Suppose the cross toolchain is placed at $TOOLCHAIN_PATH, with a cross prefix
100# of "loongarch64-unknown-linux-gnu-".
101export CC_loongarch64_unknown_linux_gnu="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-gcc
102export CXX_loongarch64_unknown_linux_gnu="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-g++
103export AR_loongarch64_unknown_linux_gnu="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-gcc-ar
104export CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PATH"/bin/loongarch64-unknown-linux-gnu-gcc
105
106# Point qemu-loongarch64 to the LoongArch sysroot.
107# Suppose the sysroot is located at "sysroot" below the toolchain root:
108export CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-loongarch64 -L $TOOLCHAIN_PATH/sysroot"
109# Or alternatively, if binfmt_misc is set up for running LoongArch binaries
110# transparently:
111export QEMU_LD_PREFIX="$TOOLCHAIN_PATH"/sysroot
65112
66## Testing
67To test a cross-compiled binary on your build system, install the qemu binary that supports the LoongArch architecture and execute the following commands.
68```text
69CC_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
70CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++ \
71AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \
72CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
73# SET TARGET SYSTEM LIBRARY PATH
74CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRARY_PATH" \
75113cargo run --target loongarch64-unknown-linux-gnu --release
76114```
77Tested on x86 architecture, other architectures not tested.
78115
79## Building Rust programs
116## Testing
117
118There are no special requirements for testing and running the targets.
119For testing cross builds on the host, please refer to the "Cross-compilation"
120section above.
80121
81Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `std` by using `build-std` or similar.
122## Building Rust programs
82123
83If `rustc` has support for that target and the library artifacts are available, then Rust static libraries can be built for that target:
124As the targets are available through `rustup`, it is very easy to build Rust
125programs for these targets: same as with other architectures.
126Note that you will need a LoongArch C/C++ toolchain for linking, or if you want
127to compile C code along with Rust (such as for Rust crates with C dependencies).
84128
85```shell
86$ rustc --target loongarch64-unknown-linux-gnu your-code.rs --crate-type staticlib
87$ ls libyour_code.a
129```sh
130rustup target add loongarch64-unknown-linux-gnu
131cargo build --target loongarch64-unknown-linux-gnu
88132```
89133
90On Rust Nightly it's possible to build without the target artifacts available:
134Availability of pre-built artifacts through `rustup` are as follows:
91135
92```text
93cargo build -Z build-std --target loongarch64-unknown-linux-gnu
94```
136* `loongarch64-unknown-linux-gnu`: since Rust 1.71;
137* `loongarch64-unknown-linux-musl`: since Rust 1.81.
src/doc/rustc/src/platform-support/loongarch-none.md+34-22
......@@ -4,10 +4,10 @@
44
55Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, etc.
66
7| Target | Descriptions |
8|------------------------------------|-------------------------------------------------------|
9| loongarch64-unknown-none | LoongArch 64-bit, LP64D ABI (freestanding, hardfloat) |
10| loongarch64-unknown-none-softfloat | LoongArch 64-bit, LP64S ABI (freestanding, softfloat) |
7| Target | Description |
8|--------|-------------|
9| `loongarch64-unknown-none` | LoongArch 64-bit, LP64D ABI (freestanding, hard-float) |
10| `loongarch64-unknown-none-softfloat` | LoongArch 64-bit, LP64S ABI (freestanding, soft-float) |
1111
1212## Target maintainers
1313
......@@ -19,6 +19,8 @@ Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, e
1919This target is cross-compiled. There is no support for `std`. There is no
2020default allocator, but it's possible to use `alloc` by supplying an allocator.
2121
22The `*-softfloat` target does not assume existence of FPU or any other LoongArch
23ISA extension, and does not make use of any non-GPR register.
2224This allows the generated code to run in environments, such as kernels, which
2325may need to avoid the use of such registers or which may have special considerations
2426about the use of such registers (e.g. saving and restoring them to avoid breaking
......@@ -26,54 +28,64 @@ userspace code using the same registers). You can change code generation to use
2628additional CPU features via the `-C target-feature=` codegen options to rustc, or
2729via the `#[target_feature]` mechanism within Rust code.
2830
29By default, code generated with this target should run on any `loongarch`
30hardware; enabling additional target features may raise this baseline.
31By default, code generated with the soft-float target should run on any
32LoongArch64 hardware, with the hard-float target additionally requiring an FPU;
33enabling additional target features may raise this baseline.
3134
32Code generated with this target will use the `small` code model by default.
35Code generated with the targets will use the `small` code model by default.
3336You can change this using the `-C code-model=` option to rustc.
3437
35On `loongarch64-unknown-none*`, `extern "C"` uses the [standard calling
36convention](https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html).
38On `loongarch64-unknown-none*`, `extern "C"` uses the [architecture's standard calling convention][lapcs].
3739
38This target generates binaries in the ELF format. Any alternate formats or
40[lapcs]: https://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc
41
42The targets generate binaries in the ELF format. Any alternate formats or
3943special considerations for binary layout will require linker options or linker
4044scripts.
4145
4246## Building the target
4347
44You can build Rust with support for the target by adding it to the `target`
48You can build Rust with support for the targets by adding them to the `target`
4549list in `config.toml`:
4650
4751```toml
4852[build]
4953build-stage = 1
50target = ["loongarch64-unknown-none"]
54target = [
55 "loongarch64-unknown-none",
56 "loongarch64-unknown-none-softfloat",
57]
5158```
5259
60## Testing
61
62As the targets support a variety of different environments and do not support
63`std`, they do not support running the Rust test suite.
64
5365## Building Rust programs
5466
55```text
67Starting with Rust 1.74, precompiled artifacts are provided via `rustup`:
68
69```sh
70# install cross-compile toolchain
71rustup target add loongarch64-unknown-none
5672# target flag may be used with any cargo or rustc command
5773cargo build --target loongarch64-unknown-none
5874```
5975
60## Testing
61
62As `loongarch64-unknown-none*` supports a variety of different environments and does
63not support `std`, this target does not support running the Rust test suite.
64
6576## Cross-compilation toolchains and C code
6677
67If you want to compile C code along with Rust (such as for Rust crates with C
68dependencies), you will need an appropriate `loongarch` toolchain.
78For cross builds, you will need an appropriate LoongArch C/C++ toolchain for
79linking, or if you want to compile C code along with Rust (such as for Rust
80crates with C dependencies).
6981
7082Rust *may* be able to use an `loongarch64-unknown-linux-gnu-` toolchain with
7183appropriate standalone flags to build for this toolchain (depending on the assumptions
7284of that toolchain, see below), or you may wish to use a separate
7385`loongarch64-unknown-none` toolchain.
7486
75On some `loongarch` hosts that use ELF binaries, you *may* be able to use the host
87On some LoongArch hosts that use ELF binaries, you *may* be able to use the host
7688C toolchain, if it does not introduce assumptions about the host environment
7789that don't match the expectations of a standalone environment. Otherwise, you
7890may need a separate toolchain for standalone/freestanding development, just as
79when cross-compiling from a non-`loongarch` platform.
91when cross-compiling from a non-LoongArch platform.
src/tools/run-make-support/src/lib.rs+3-2
......@@ -525,11 +525,12 @@ macro_rules! impl_common_helpers {
525525 /// Generic command arguments provider. Prefer specific helper methods if possible.
526526 /// Note that for some executables, arguments might be platform specific. For C/C++
527527 /// compilers, arguments might be platform *and* compiler specific.
528 pub fn args<S>(&mut self, args: &[S]) -> &mut Self
528 pub fn args<V, S>(&mut self, args: V) -> &mut Self
529529 where
530 V: AsRef<[S]>,
530531 S: AsRef<::std::ffi::OsStr>,
531532 {
532 self.cmd.args(args);
533 self.cmd.args(args.as_ref());
533534 self
534535 }
535536
src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs-1
......@@ -49,7 +49,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
4949 label: "bindings_with_variant_name",
5050 description: r##"detects pattern bindings with the same name as one of the matched variants"##,
5151 },
52 Lint { label: "box_pointers", description: r##"use of owned (Box type) heap memory"## },
5352 Lint {
5453 label: "break_with_label_and_loop",
5554 description: r##"`break` expression with label and unlabeled loop as value expression"##,
tests/run-make/arguments-non-c-like-enum/rmake.rs+2-2
......@@ -10,8 +10,8 @@ pub fn main() {
1010 cc().input("test.c")
1111 .input(static_lib_name("nonclike"))
1212 .out_exe("test")
13 .args(&extra_c_flags())
14 .args(&extra_cxx_flags())
13 .args(extra_c_flags())
14 .args(extra_cxx_flags())
1515 .inspect(|cmd| eprintln!("{cmd:?}"))
1616 .run();
1717 run("test");
tests/run-make/c-link-to-rust-staticlib/rmake.rs+1-1
......@@ -9,7 +9,7 @@ use std::fs;
99
1010fn main() {
1111 rustc().input("foo.rs").run();
12 cc().input("bar.c").input(static_lib_name("foo")).out_exe("bar").args(&extra_c_flags()).run();
12 cc().input("bar.c").input(static_lib_name("foo")).out_exe("bar").args(extra_c_flags()).run();
1313 run("bar");
1414 remove_file(static_lib_name("foo"));
1515 run("bar");
tests/run-make/c-link-to-rust-va-list-fn/rmake.rs+1-1
......@@ -12,7 +12,7 @@ fn main() {
1212 cc().input("test.c")
1313 .input(static_lib_name("checkrust"))
1414 .out_exe("test")
15 .args(&extra_c_flags())
15 .args(extra_c_flags())
1616 .run();
1717 run("test");
1818}
tests/run-make/glibc-staticlib-args/rmake.rs+2-2
......@@ -11,8 +11,8 @@ fn main() {
1111 cc().input("program.c")
1212 .arg(static_lib_name("library"))
1313 .out_exe("program")
14 .args(&extra_c_flags())
15 .args(&extra_cxx_flags())
14 .args(extra_c_flags())
15 .args(extra_cxx_flags())
1616 .run();
1717 run(&bin_name("program"));
1818}
tests/run-make/print-check-cfg/rmake.rs+2-6
......@@ -86,12 +86,8 @@ fn main() {
8686}
8787
8888fn check(CheckCfg { args, contains }: CheckCfg) {
89 let output = rustc()
90 .input("lib.rs")
91 .arg("-Zunstable-options")
92 .arg("--print=check-cfg")
93 .args(&*args)
94 .run();
89 let output =
90 rustc().input("lib.rs").arg("-Zunstable-options").arg("--print=check-cfg").args(args).run();
9591
9692 let stdout = output.stdout_utf8();
9793
tests/run-make/return-non-c-like-enum/rmake.rs+2-2
......@@ -11,8 +11,8 @@ fn main() {
1111 cc().input("test.c")
1212 .arg(&static_lib_name("nonclike"))
1313 .out_exe("test")
14 .args(&extra_c_flags())
15 .args(&extra_cxx_flags())
14 .args(extra_c_flags())
15 .args(extra_cxx_flags())
1616 .run();
1717 run("test");
1818}
tests/run-make/textrel-on-minimal-lib/rmake.rs+2-2
......@@ -20,8 +20,8 @@ fn main() {
2020 .out_exe(&dynamic_lib_name("bar"))
2121 .arg("-fPIC")
2222 .arg("-shared")
23 .args(&extra_c_flags())
24 .args(&extra_cxx_flags())
23 .args(extra_c_flags())
24 .args(extra_cxx_flags())
2525 .run();
2626 llvm_readobj()
2727 .input(dynamic_lib_name("bar"))
tests/ui/const-generics/repeat_expr_hack_gives_right_generics.rs+13-9
......@@ -1,14 +1,18 @@
1// Given an anon const `a`: `{ N }` and some anon const `b` which references the
2// first anon const: `{ [1; a] }`. `b` should not have any generics as it is not
3// a simple `N` argument nor is it a repeat expr count.
1// Given a const argument `a`: `{ N }` and some const argument `b` which references the
2// first anon const like so: `{ [1; a] }`. The `b` anon const should not be allowed to use
3// any generic parameters as:
4// - The anon const is not a simple bare parameter, e.g. `N`
5// - The anon const is not the *length* of an array repeat expression, e.g. the `N` in `[1; N]`.
46//
5// On the other hand `b` *is* a repeat expr count and so it should inherit its
6// parents generics as part of the `const_evaluatable_unchecked` fcw (#76200).
7// On the other hand `a` *is* a const argument for the length of a repeat expression and
8// so it *should* inherit the generics declared on its parent definition. (This hack is
9// introduced for backwards compatibility and is tracked in #76200)
710//
8// In this specific case however `b`'s parent should be `a` and so it should wind
9// up not having any generics after all. If `a` were to inherit its generics from
10// the enclosing item then the reference to `a` from `b` would contain generic
11// parameters not usable by `b` which would cause us to ICE.
11// In this specific case `a`'s parent should be `b` which does not have any generics.
12// This means that even though `a` inherits generics from `b`, it still winds up not having
13// access to any generic parameters. If `a` were to inherit its generics from the surrounding
14// function `foo` then the reference to `a` from `b` would contain generic parameters not usable
15// by `b` which would cause us to ICE.
1216
1317fn bar<const N: usize>() {}
1418
tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr+1-1
......@@ -1,5 +1,5 @@
11error: generic parameters may not be used in const operations
2 --> $DIR/repeat_expr_hack_gives_right_generics.rs:16:17
2 --> $DIR/repeat_expr_hack_gives_right_generics.rs:20:17
33 |
44LL | bar::<{ [1; N] }>();
55 | ^ cannot perform const operation using `N`
tests/ui/lint/lint-owned-heap-memory.rs deleted-12
......@@ -1,12 +0,0 @@
1#![allow(dead_code)]
2#![forbid(box_pointers)]
3
4
5struct Foo {
6 x: Box<isize> //~ ERROR type uses owned
7}
8
9fn main() {
10 let _x: Foo = Foo { x : Box::new(10) };
11 //~^ ERROR type uses owned
12}
tests/ui/lint/lint-owned-heap-memory.stderr deleted-20
......@@ -1,20 +0,0 @@
1error: type uses owned (Box type) pointers: Box<isize>
2 --> $DIR/lint-owned-heap-memory.rs:6:5
3 |
4LL | x: Box<isize>
5 | ^^^^^^^^^^^^^
6 |
7note: the lint level is defined here
8 --> $DIR/lint-owned-heap-memory.rs:2:11
9 |
10LL | #![forbid(box_pointers)]
11 | ^^^^^^^^^^^^
12
13error: type uses owned (Box type) pointers: Box<isize>
14 --> $DIR/lint-owned-heap-memory.rs:10:29
15 |
16LL | let _x: Foo = Foo { x : Box::new(10) };
17 | ^^^^^^^^^^^^
18
19error: aborting due to 2 previous errors
20
tests/ui/lint/reasons-erroneous.rs+1-1
......@@ -9,7 +9,7 @@
99#![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
1010//~^ ERROR malformed lint attribute
1111//~| NOTE bad attribute argument
12#![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
12#![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
1313//~^ ERROR malformed lint attribute
1414//~| NOTE bad attribute argument
1515#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
tests/ui/lint/reasons-erroneous.stderr+3-3
......@@ -17,10 +17,10 @@ LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides thei
1717 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
1818
1919error[E0452]: malformed lint attribute input
20 --> $DIR/reasons-erroneous.rs:12:23
20 --> $DIR/reasons-erroneous.rs:12:22
2121 |
22LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
23 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
22LL | #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
23 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
2424
2525error[E0452]: malformed lint attribute input
2626 --> $DIR/reasons-erroneous.rs:15:36
tests/ui/suggestions/types/dont-suggest-path-names.rs created+17
......@@ -0,0 +1,17 @@
1// This is a regression test for #123630
2//
3// Prior to #123703 this was resulting in compiler suggesting add a type signature
4// for `lit` containing path to a file containing `Select` - something obviously invalid.
5
6struct Select<F, I>(F, I);
7fn select<F, I>(filter: F) -> Select<F, I> {}
8//~^ 7:31: 7:43: mismatched types [E0308]
9
10fn parser1() {
11 let lit = select(|x| match x {
12 //~^ 11:23: 11:24: type annotations needed [E0282]
13 _ => (),
14 });
15}
16
17fn main() {}
tests/ui/suggestions/types/dont-suggest-path-names.stderr created+26
......@@ -0,0 +1,26 @@
1error[E0308]: mismatched types
2 --> $DIR/dont-suggest-path-names.rs:7:31
3 |
4LL | fn select<F, I>(filter: F) -> Select<F, I> {}
5 | ------ ^^^^^^^^^^^^ expected `Select<F, I>`, found `()`
6 | |
7 | implicitly returns `()` as its body has no tail or `return` expression
8 |
9 = note: expected struct `Select<F, I>`
10 found unit type `()`
11
12error[E0282]: type annotations needed
13 --> $DIR/dont-suggest-path-names.rs:11:23
14 |
15LL | let lit = select(|x| match x {
16 | ^ - type must be known at this point
17 |
18help: consider giving this closure parameter an explicit type
19 |
20LL | let lit = select(|x: /* Type */| match x {
21 | ++++++++++++
22
23error: aborting due to 2 previous errors
24
25Some errors have detailed explanations: E0282, E0308.
26For more information about an error, try `rustc --explain E0282`.