Skip to content

Commit 579c993

Browse files
committed
Auto merge of rust-lang#104935 - matthiaskrgr:rollup-nuca86l, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#104121 (Refine `instruction_set` MIR inline rules) - rust-lang#104675 (Unsupported query error now specifies if its unsupported for local or external crate) - rust-lang#104839 (improve array_from_fn documenation) - rust-lang#104880 ([llvm-wrapper] adapt for LLVM API change) - rust-lang#104899 (rustdoc: remove no-op CSS `#help dt { display: block }`) - rust-lang#104906 (Remove AscribeUserTypeCx) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8841bee + 1fe18a5 commit 579c993

File tree

10 files changed

+143
-135
lines changed

10 files changed

+143
-135
lines changed

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,11 @@ LLVMRustOptimize(
627627
bool DebugPassManager = false;
628628

629629
PassInstrumentationCallbacks PIC;
630+
#if LLVM_VERSION_LT(16, 0)
630631
StandardInstrumentations SI(DebugPassManager);
632+
#else
633+
StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
634+
#endif
631635
SI.registerCallbacks(PIC);
632636

633637
if (LlvmSelfProfiler){

compiler/rustc_middle/src/ty/query.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,16 @@ macro_rules! define_callbacks {
276276

277277
impl Default for Providers {
278278
fn default() -> Self {
279+
use crate::query::Key;
280+
279281
Providers {
280282
$($name: |_, key| bug!(
281-
"`tcx.{}({:?})` is not supported for external or local crate;\n
282-
hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported (likely the local crate).\n
283+
"`tcx.{}({:?})` is not supported for {} crate;\n
284+
hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported.\n
283285
If that's not the case, {} was likely never assigned to a provider function.\n",
284286
stringify!($name),
285287
key,
288+
if key.query_crate_is_local() { "local" } else { "external" },
286289
stringify!($name),
287290
),)*
288291
}

compiler/rustc_mir_transform/src/inline.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,12 @@ impl<'tcx> Inliner<'tcx> {
375375
return Err("incompatible sanitizer set");
376376
}
377377

378-
if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set {
378+
// Two functions are compatible if the callee has no attribute (meaning
379+
// that it's codegen agnostic), or sets an attribute that is identical
380+
// to this function's attribute.
381+
if callee_attrs.instruction_set.is_some()
382+
&& callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
383+
{
379384
return Err("incompatible instruction set");
380385
}
381386

@@ -453,6 +458,15 @@ impl<'tcx> Inliner<'tcx> {
453458
if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
454459
work_list.push(unwind);
455460
}
461+
} else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
462+
&& matches!(term.kind, TerminatorKind::InlineAsm { .. })
463+
{
464+
// During the attribute checking stage we allow a callee with no
465+
// instruction_set assigned to count as compatible with a function that does
466+
// assign one. However, during this stage we require an exact match when any
467+
// inline-asm is detected. LLVM will still possibly do an inline later on
468+
// if the no-attribute function ends up with the same instruction set anyway.
469+
return Err("Cannot move inline-asm across instruction sets");
456470
} else {
457471
work_list.extend(term.successors())
458472
}

compiler/rustc_query_impl/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern crate rustc_middle;
2020
use rustc_data_structures::sync::AtomicU64;
2121
use rustc_middle::arena::Arena;
2222
use rustc_middle::dep_graph::{self, DepKindStruct};
23+
use rustc_middle::query::Key;
2324
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
2425
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
2526
use rustc_middle::ty::TyCtxt;
@@ -32,8 +33,6 @@ use rustc_query_system::query::*;
3233
#[cfg(parallel_compiler)]
3334
pub use rustc_query_system::query::{deadlock, QueryContext};
3435

35-
use rustc_middle::query::Key;
36-
3736
pub use rustc_query_system::query::QueryConfig;
3837
pub(crate) use rustc_query_system::query::QueryVTable;
3938

compiler/rustc_traits/src/type_op.rs

+50-107
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use rustc_hir as hir;
2-
use rustc_hir::def_id::DefId;
3-
use rustc_infer::infer::at::ToTrace;
42
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
53
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
64
use rustc_infer::traits::ObligationCauseCode;
@@ -57,122 +55,67 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
5755
"type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
5856
mir_ty, def_id, user_substs
5957
);
60-
let cx = AscribeUserTypeCx { ocx, param_env, span: span.unwrap_or(DUMMY_SP) };
61-
cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
62-
Ok(())
63-
}
58+
let span = span.unwrap_or(DUMMY_SP);
6459

65-
struct AscribeUserTypeCx<'me, 'tcx> {
66-
ocx: &'me ObligationCtxt<'me, 'tcx>,
67-
param_env: ty::ParamEnv<'tcx>,
68-
span: Span,
69-
}
60+
let UserSubsts { user_self_ty, substs } = user_substs;
61+
let tcx = ocx.infcx.tcx;
62+
let cause = ObligationCause::dummy_with_span(span);
7063

71-
impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
72-
fn normalize<T>(&self, value: T) -> T
73-
where
74-
T: TypeFoldable<'tcx>,
75-
{
76-
self.normalize_with_cause(value, ObligationCause::misc(self.span, hir::CRATE_HIR_ID))
77-
}
64+
let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
65+
let ty = ocx.normalize(cause.clone(), param_env, ty);
66+
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
7867

79-
fn normalize_with_cause<T>(&self, value: T, cause: ObligationCause<'tcx>) -> T
80-
where
81-
T: TypeFoldable<'tcx>,
82-
{
83-
self.ocx.normalize(cause, self.param_env, value)
84-
}
68+
ocx.eq(&cause, param_env, mir_ty, ty)?;
8569

86-
fn eq<T>(&self, a: T, b: T) -> Result<(), NoSolution>
87-
where
88-
T: ToTrace<'tcx>,
89-
{
90-
Ok(self.ocx.eq(&ObligationCause::dummy_with_span(self.span), self.param_env, a, b)?)
91-
}
70+
// Prove the predicates coming along with `def_id`.
71+
//
72+
// Also, normalize the `instantiated_predicates`
73+
// because otherwise we wind up with duplicate "type
74+
// outlives" error messages.
75+
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
9276

93-
fn prove_predicate(&self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
94-
self.ocx.register_obligation(Obligation::new(
95-
self.ocx.infcx.tcx,
96-
cause,
97-
self.param_env,
98-
predicate,
99-
));
100-
}
77+
debug!(?instantiated_predicates);
78+
for (instantiated_predicate, predicate_span) in
79+
zip(instantiated_predicates.predicates, instantiated_predicates.spans)
80+
{
81+
let span = if span == DUMMY_SP { predicate_span } else { span };
82+
let cause = ObligationCause::new(
83+
span,
84+
hir::CRATE_HIR_ID,
85+
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
86+
);
87+
let instantiated_predicate =
88+
ocx.normalize(cause.clone(), param_env, instantiated_predicate);
10189

102-
fn tcx(&self) -> TyCtxt<'tcx> {
103-
self.ocx.infcx.tcx
90+
ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
10491
}
10592

106-
#[instrument(level = "debug", skip(self))]
107-
fn relate_mir_and_user_ty(
108-
&self,
109-
mir_ty: Ty<'tcx>,
110-
def_id: DefId,
111-
user_substs: UserSubsts<'tcx>,
112-
) -> Result<(), NoSolution> {
113-
let UserSubsts { user_self_ty, substs } = user_substs;
114-
let tcx = self.tcx();
115-
116-
let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
117-
let ty = self.normalize(ty);
118-
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
119-
120-
self.eq(mir_ty, ty)?;
121-
122-
// Prove the predicates coming along with `def_id`.
123-
//
124-
// Also, normalize the `instantiated_predicates`
125-
// because otherwise we wind up with duplicate "type
126-
// outlives" error messages.
127-
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
128-
129-
let cause = ObligationCause::dummy_with_span(self.span);
130-
131-
debug!(?instantiated_predicates);
132-
for (instantiated_predicate, predicate_span) in
133-
zip(instantiated_predicates.predicates, instantiated_predicates.spans)
134-
{
135-
let span = if self.span == DUMMY_SP { predicate_span } else { self.span };
136-
let cause = ObligationCause::new(
137-
span,
138-
hir::CRATE_HIR_ID,
139-
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
140-
);
141-
let instantiated_predicate =
142-
self.normalize_with_cause(instantiated_predicate, cause.clone());
143-
self.prove_predicate(instantiated_predicate, cause);
144-
}
93+
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
94+
let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
95+
let impl_self_ty = ocx.normalize(cause.clone(), param_env, impl_self_ty);
14596

146-
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
147-
let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
148-
let impl_self_ty = self.normalize(impl_self_ty);
97+
ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
14998

150-
self.eq(self_ty, impl_self_ty)?;
151-
152-
self.prove_predicate(
153-
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
154-
.to_predicate(tcx),
155-
cause.clone(),
156-
);
157-
}
158-
159-
// In addition to proving the predicates, we have to
160-
// prove that `ty` is well-formed -- this is because
161-
// the WF of `ty` is predicated on the substs being
162-
// well-formed, and we haven't proven *that*. We don't
163-
// want to prove the WF of types from `substs` directly because they
164-
// haven't been normalized.
165-
//
166-
// FIXME(nmatsakis): Well, perhaps we should normalize
167-
// them? This would only be relevant if some input
168-
// type were ill-formed but did not appear in `ty`,
169-
// which...could happen with normalization...
170-
self.prove_predicate(
171-
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx),
172-
cause,
173-
);
174-
Ok(())
99+
let predicate: Predicate<'tcx> =
100+
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())).to_predicate(tcx);
101+
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
175102
}
103+
104+
// In addition to proving the predicates, we have to
105+
// prove that `ty` is well-formed -- this is because
106+
// the WF of `ty` is predicated on the substs being
107+
// well-formed, and we haven't proven *that*. We don't
108+
// want to prove the WF of types from `substs` directly because they
109+
// haven't been normalized.
110+
//
111+
// FIXME(nmatsakis): Well, perhaps we should normalize
112+
// them? This would only be relevant if some input
113+
// type were ill-formed but did not appear in `ty`,
114+
// which...could happen with normalization...
115+
let predicate: Predicate<'tcx> =
116+
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx);
117+
ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
118+
Ok(())
176119
}
177120

178121
fn type_op_eq<'tcx>(

library/core/src/array/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ mod iter;
2323
#[stable(feature = "array_value_iter", since = "1.51.0")]
2424
pub use iter::IntoIter;
2525

26-
/// Creates an array `[T; N]` where each array element `T` is returned by the `cb` call.
26+
/// Creates an array of type [T; N], where each element `T` is the returned value from `cb`
27+
/// using that element's index.
2728
///
2829
/// # Arguments
2930
///
@@ -36,8 +37,18 @@ pub use iter::IntoIter;
3637
/// // elements to produce is the length of array down there: only arrays of
3738
/// // equal lengths can be compared, so the const generic parameter `N` is
3839
/// // inferred to be 5, thus creating array of 5 elements.
40+
///
3941
/// let array = core::array::from_fn(|i| i);
42+
/// // indexes are: 0 1 2 3 4
4043
/// assert_eq!(array, [0, 1, 2, 3, 4]);
44+
///
45+
/// let array2: [usize; 8] = core::array::from_fn(|i| i * 2);
46+
/// // indexes are: 0 1 2 3 4 5 6 7
47+
/// assert_eq!(array2, [0, 2, 4, 6, 8, 10, 12, 14]);
48+
///
49+
/// let bool_arr = core::array::from_fn::<_, 5, _>(|i| i % 2 == 0);
50+
/// // indexes are: 0 1 2 3 4
51+
/// assert_eq!(bool_arr, [true, false, true, false, true]);
4152
/// ```
4253
#[inline]
4354
#[stable(feature = "array_from_fn", since = "1.63.0")]

src/librustdoc/html/static/css/rustdoc.css

-1
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
949949
#help dt {
950950
float: left;
951951
clear: left;
952-
display: block;
953952
margin-right: 0.5rem;
954953
}
955954
#help span.top, #help span.bottom {

src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff

+22-6
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@
66
let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
77
let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
88
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
9-
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:53:5: 53:30
9+
let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
10+
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:59:5: 59:30
11+
+ }
12+
+ scope 2 (inlined inline_always_and_using_inline_asm) { // at $DIR/inline_instruction_set.rs:60:5: 60:41
13+
+ scope 3 {
14+
+ }
1015
+ }
1116

1217
bb0: {
1318
StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
1419
_1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
1520
// mir::Constant
16-
// + span: $DIR/inline_instruction_set.rs:51:5: 51:24
21+
// + span: $DIR/inline_instruction_set.rs:57:5: 57:24
1722
// + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
1823
}
1924

@@ -22,7 +27,7 @@
2227
StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
2328
_2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
2429
// mir::Constant
25-
// + span: $DIR/inline_instruction_set.rs:52:5: 52:24
30+
// + span: $DIR/inline_instruction_set.rs:58:5: 58:24
2631
// + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
2732
}
2833

@@ -31,14 +36,25 @@
3136
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
3237
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
3338
- // mir::Constant
34-
- // + span: $DIR/inline_instruction_set.rs:53:5: 53:28
39+
- // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
3540
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
3641
- }
3742
-
3843
- bb3: {
3944
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
40-
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +4:2
41-
return; // scope 0 at $DIR/inline_instruction_set.rs:+4:2: +4:2
45+
StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
46+
- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
47+
- // mir::Constant
48+
- // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
49+
- // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
50+
+ asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
51+
}
52+
53+
- bb4: {
54+
+ bb3: {
55+
StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
56+
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +5:2
57+
return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
4258
}
4359
}
4460

src/test/mir-opt/inline/inline_instruction_set.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Checks that only functions with the compatible instruction_set attributes are inlined.
22
//
3+
// A function is "compatible" when the *callee* has the same attribute or no attribute.
4+
//
35
// compile-flags: --target thumbv4t-none-eabi
46
// needs-llvm-components: arm
57

@@ -36,19 +38,24 @@ fn instruction_set_t32() {}
3638
#[inline]
3739
fn instruction_set_default() {}
3840

41+
#[inline(always)]
42+
fn inline_always_and_using_inline_asm() {
43+
unsafe { asm!("/* do nothing */") };
44+
}
45+
3946
// EMIT_MIR inline_instruction_set.t32.Inline.diff
4047
#[instruction_set(arm::t32)]
4148
pub fn t32() {
4249
instruction_set_a32();
4350
instruction_set_t32();
44-
// The default instruction set is currently
45-
// conservatively assumed to be incompatible.
4651
instruction_set_default();
52+
inline_always_and_using_inline_asm();
4753
}
4854

4955
// EMIT_MIR inline_instruction_set.default.Inline.diff
5056
pub fn default() {
5157
instruction_set_a32();
5258
instruction_set_t32();
5359
instruction_set_default();
60+
inline_always_and_using_inline_asm();
5461
}

0 commit comments

Comments
 (0)