Skip to content

Commit

Permalink
Auto merge of rust-lang#104935 - matthiaskrgr:rollup-nuca86l, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

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
  • Loading branch information
bors committed Nov 26, 2022
2 parents 8841bee + 1fe18a5 commit 579c993
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 135 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,11 @@ LLVMRustOptimize(
bool DebugPassManager = false;

PassInstrumentationCallbacks PIC;
#if LLVM_VERSION_LT(16, 0)
StandardInstrumentations SI(DebugPassManager);
#else
StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
#endif
SI.registerCallbacks(PIC);

if (LlvmSelfProfiler){
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_middle/src/ty/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,16 @@ macro_rules! define_callbacks {

impl Default for Providers {
fn default() -> Self {
use crate::query::Key;

Providers {
$($name: |_, key| bug!(
"`tcx.{}({:?})` is not supported for external or local crate;\n
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
"`tcx.{}({:?})` is not supported for {} crate;\n
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
If that's not the case, {} was likely never assigned to a provider function.\n",
stringify!($name),
key,
if key.query_crate_is_local() { "local" } else { "external" },
stringify!($name),
),)*
}
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,12 @@ impl<'tcx> Inliner<'tcx> {
return Err("incompatible sanitizer set");
}

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

Expand Down Expand Up @@ -453,6 +458,15 @@ impl<'tcx> Inliner<'tcx> {
if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
work_list.push(unwind);
}
} else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
&& matches!(term.kind, TerminatorKind::InlineAsm { .. })
{
// During the attribute checking stage we allow a callee with no
// instruction_set assigned to count as compatible with a function that does
// assign one. However, during this stage we require an exact match when any
// inline-asm is detected. LLVM will still possibly do an inline later on
// if the no-attribute function ends up with the same instruction set anyway.
return Err("Cannot move inline-asm across instruction sets");
} else {
work_list.extend(term.successors())
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_query_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ extern crate rustc_middle;
use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::{self, DepKindStruct};
use rustc_middle::query::Key;
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
use rustc_middle::ty::TyCtxt;
Expand All @@ -32,8 +33,6 @@ use rustc_query_system::query::*;
#[cfg(parallel_compiler)]
pub use rustc_query_system::query::{deadlock, QueryContext};

use rustc_middle::query::Key;

pub use rustc_query_system::query::QueryConfig;
pub(crate) use rustc_query_system::query::QueryVTable;

Expand Down
157 changes: 50 additions & 107 deletions compiler/rustc_traits/src/type_op.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_infer::traits::ObligationCauseCode;
Expand Down Expand Up @@ -57,122 +55,67 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
"type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
mir_ty, def_id, user_substs
);
let cx = AscribeUserTypeCx { ocx, param_env, span: span.unwrap_or(DUMMY_SP) };
cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
Ok(())
}
let span = span.unwrap_or(DUMMY_SP);

struct AscribeUserTypeCx<'me, 'tcx> {
ocx: &'me ObligationCtxt<'me, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
}
let UserSubsts { user_self_ty, substs } = user_substs;
let tcx = ocx.infcx.tcx;
let cause = ObligationCause::dummy_with_span(span);

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

fn normalize_with_cause<T>(&self, value: T, cause: ObligationCause<'tcx>) -> T
where
T: TypeFoldable<'tcx>,
{
self.ocx.normalize(cause, self.param_env, value)
}
ocx.eq(&cause, param_env, mir_ty, ty)?;

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

fn prove_predicate(&self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
self.ocx.register_obligation(Obligation::new(
self.ocx.infcx.tcx,
cause,
self.param_env,
predicate,
));
}
debug!(?instantiated_predicates);
for (instantiated_predicate, predicate_span) in
zip(instantiated_predicates.predicates, instantiated_predicates.spans)
{
let span = if span == DUMMY_SP { predicate_span } else { span };
let cause = ObligationCause::new(
span,
hir::CRATE_HIR_ID,
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
);
let instantiated_predicate =
ocx.normalize(cause.clone(), param_env, instantiated_predicate);

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

#[instrument(level = "debug", skip(self))]
fn relate_mir_and_user_ty(
&self,
mir_ty: Ty<'tcx>,
def_id: DefId,
user_substs: UserSubsts<'tcx>,
) -> Result<(), NoSolution> {
let UserSubsts { user_self_ty, substs } = user_substs;
let tcx = self.tcx();

let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
let ty = self.normalize(ty);
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);

self.eq(mir_ty, ty)?;

// Prove the predicates coming along with `def_id`.
//
// Also, normalize the `instantiated_predicates`
// because otherwise we wind up with duplicate "type
// outlives" error messages.
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);

let cause = ObligationCause::dummy_with_span(self.span);

debug!(?instantiated_predicates);
for (instantiated_predicate, predicate_span) in
zip(instantiated_predicates.predicates, instantiated_predicates.spans)
{
let span = if self.span == DUMMY_SP { predicate_span } else { self.span };
let cause = ObligationCause::new(
span,
hir::CRATE_HIR_ID,
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
);
let instantiated_predicate =
self.normalize_with_cause(instantiated_predicate, cause.clone());
self.prove_predicate(instantiated_predicate, cause);
}
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
let impl_self_ty = ocx.normalize(cause.clone(), param_env, impl_self_ty);

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

self.eq(self_ty, impl_self_ty)?;

self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
.to_predicate(tcx),
cause.clone(),
);
}

// In addition to proving the predicates, we have to
// prove that `ty` is well-formed -- this is because
// the WF of `ty` is predicated on the substs being
// well-formed, and we haven't proven *that*. We don't
// want to prove the WF of types from `substs` directly because they
// haven't been normalized.
//
// FIXME(nmatsakis): Well, perhaps we should normalize
// them? This would only be relevant if some input
// type were ill-formed but did not appear in `ty`,
// which...could happen with normalization...
self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx),
cause,
);
Ok(())
let predicate: Predicate<'tcx> =
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())).to_predicate(tcx);
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
}

// In addition to proving the predicates, we have to
// prove that `ty` is well-formed -- this is because
// the WF of `ty` is predicated on the substs being
// well-formed, and we haven't proven *that*. We don't
// want to prove the WF of types from `substs` directly because they
// haven't been normalized.
//
// FIXME(nmatsakis): Well, perhaps we should normalize
// them? This would only be relevant if some input
// type were ill-formed but did not appear in `ty`,
// which...could happen with normalization...
let predicate: Predicate<'tcx> =
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx);
ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
Ok(())
}

fn type_op_eq<'tcx>(
Expand Down
13 changes: 12 additions & 1 deletion library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ mod iter;
#[stable(feature = "array_value_iter", since = "1.51.0")]
pub use iter::IntoIter;

/// Creates an array `[T; N]` where each array element `T` is returned by the `cb` call.
/// Creates an array of type [T; N], where each element `T` is the returned value from `cb`
/// using that element's index.
///
/// # Arguments
///
Expand All @@ -36,8 +37,18 @@ pub use iter::IntoIter;
/// // elements to produce is the length of array down there: only arrays of
/// // equal lengths can be compared, so the const generic parameter `N` is
/// // inferred to be 5, thus creating array of 5 elements.
///
/// let array = core::array::from_fn(|i| i);
/// // indexes are: 0 1 2 3 4
/// assert_eq!(array, [0, 1, 2, 3, 4]);
///
/// let array2: [usize; 8] = core::array::from_fn(|i| i * 2);
/// // indexes are: 0 1 2 3 4 5 6 7
/// assert_eq!(array2, [0, 2, 4, 6, 8, 10, 12, 14]);
///
/// let bool_arr = core::array::from_fn::<_, 5, _>(|i| i % 2 == 0);
/// // indexes are: 0 1 2 3 4
/// assert_eq!(bool_arr, [true, false, true, false, true]);
/// ```
#[inline]
#[stable(feature = "array_from_fn", since = "1.63.0")]
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
#help dt {
float: left;
clear: left;
display: block;
margin-right: 0.5rem;
}
#help span.top, #help span.bottom {
Expand Down
28 changes: 22 additions & 6 deletions src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:53:5: 53:30
let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:59:5: 59:30
+ }
+ scope 2 (inlined inline_always_and_using_inline_asm) { // at $DIR/inline_instruction_set.rs:60:5: 60:41
+ scope 3 {
+ }
+ }

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

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

Expand All @@ -31,14 +36,25 @@
StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
- // mir::Constant
- // + span: $DIR/inline_instruction_set.rs:53:5: 53:28
- // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
- }
-
- bb3: {
StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +4:2
return; // scope 0 at $DIR/inline_instruction_set.rs:+4:2: +4:2
StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
- // mir::Constant
- // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
- // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
+ asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
}

- bb4: {
+ bb3: {
StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42
_0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +5:2
return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2
}
}

11 changes: 9 additions & 2 deletions src/test/mir-opt/inline/inline_instruction_set.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Checks that only functions with the compatible instruction_set attributes are inlined.
//
// A function is "compatible" when the *callee* has the same attribute or no attribute.
//
// compile-flags: --target thumbv4t-none-eabi
// needs-llvm-components: arm

Expand Down Expand Up @@ -36,19 +38,24 @@ fn instruction_set_t32() {}
#[inline]
fn instruction_set_default() {}

#[inline(always)]
fn inline_always_and_using_inline_asm() {
unsafe { asm!("/* do nothing */") };
}

// EMIT_MIR inline_instruction_set.t32.Inline.diff
#[instruction_set(arm::t32)]
pub fn t32() {
instruction_set_a32();
instruction_set_t32();
// The default instruction set is currently
// conservatively assumed to be incompatible.
instruction_set_default();
inline_always_and_using_inline_asm();
}

// EMIT_MIR inline_instruction_set.default.Inline.diff
pub fn default() {
instruction_set_a32();
instruction_set_t32();
instruction_set_default();
inline_always_and_using_inline_asm();
}
Loading

0 comments on commit 579c993

Please sign in to comment.