Skip to content

Commit

Permalink
Auto merge of #129126 - GuillaumeGomez:rollup-abnvlgj, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #128348 (Unconditionally allow shadow call-stack sanitizer for AArch64)
 - #128922 (rust-analyzer: use in-tree `pattern_analysis` crate)
 - #128935 (More work on `zstd` compression)
 - #129072 (Infer async closure args from `Fn` bound even if there is no corresponding `Future` bound on return)
 - #129101 (Fix projections when parent capture is by-ref but child capture is by-value in the `ByMoveBody` pass)
 - #129106 (Remove redundant type ops: `Eq`/`Subtype`)
 - #129122 (Remove duplicated `Rustdoc::output` method from `run-make-support` lib)
 - #129124 (rustdoc-json: Use FxHashMap from rustdoc_json_types)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Aug 15, 2024
2 parents d2b5aa6 + 38c9f38 commit ed311ef
Show file tree
Hide file tree
Showing 43 changed files with 408 additions and 234 deletions.
45 changes: 34 additions & 11 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_middle::span_bug;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::ArgKind;
use rustc_trait_selection::traits;
Expand Down Expand Up @@ -539,6 +539,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// we identify the `FnOnce<Args, Output = ?Fut>` bound, and if the output type is
/// an inference variable `?Fut`, we check if that is bounded by a `Future<Output = Ty>`
/// projection.
///
/// This function is actually best-effort with the return type; if we don't find a
/// `Future` projection, we still will return arguments that we extracted from the `FnOnce`
/// projection, and the output will be an unconstrained type variable instead.
fn extract_sig_from_projection_and_future_bound(
&self,
cause_span: Option<Span>,
Expand All @@ -564,24 +568,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};

// FIXME: We may want to elaborate here, though I assume this will be exceedingly rare.
let mut return_ty = None;
for bound in self.obligations_for_self_ty(return_vid) {
if let Some(ret_projection) = bound.predicate.as_projection_clause()
&& let Some(ret_projection) = ret_projection.no_bound_vars()
&& self.tcx.is_lang_item(ret_projection.def_id(), LangItem::FutureOutput)
{
let sig = projection.rebind(self.tcx.mk_fn_sig(
input_tys,
ret_projection.term.expect_type(),
false,
hir::Safety::Safe,
Abi::Rust,
));

return Some(ExpectedSig { cause_span, sig });
return_ty = Some(ret_projection.term.expect_type());
break;
}
}

None
// SUBTLE: If we didn't find a `Future<Output = ...>` bound for the return
// vid, we still want to attempt to provide inference guidance for the async
// closure's arguments. Instantiate a new vid to plug into the output type.
//
// You may be wondering, what if it's higher-ranked? Well, given that we
// found a type variable for the `FnOnce::Output` projection above, we know
// that the output can't mention any of the vars.
//
// Also note that we use a fresh var here for the signature since the signature
// records the output of the *future*, and `return_vid` above is the type
// variable of the future, not its output.
//
// FIXME: We probably should store this signature inference output in a way
// that does not misuse a `FnSig` type, but that can be done separately.
let return_ty =
return_ty.unwrap_or_else(|| self.next_ty_var(cause_span.unwrap_or(DUMMY_SP)));

let sig = projection.rebind(self.tcx.mk_fn_sig(
input_tys,
return_ty,
false,
hir::Safety::Safe,
Abi::Rust,
));

return Some(ExpectedSig { cause_span, sig });
}

fn sig_of_closure(
Expand Down
27 changes: 3 additions & 24 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@ use crate::query::plumbing::{
};
use crate::traits::query::{
CanonicalAliasGoal, CanonicalPredicateGoal, CanonicalTyGoal,
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, DropckConstraint,
DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult,
OutlivesBound,
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpProvePredicateGoal, DropckConstraint, DropckOutlivesResult,
MethodAutoderefStepsResult, NoSolution, NormalizationResult, OutlivesBound,
};
use crate::traits::{
specialization_graph, CodegenObligationError, EvaluationResult, ImplSource,
Expand Down Expand Up @@ -2090,26 +2089,6 @@ rustc_queries! {
desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value }
}

/// Do not call this query directly: part of the `Eq` type-op
query type_op_eq(
goal: CanonicalTypeOpEqGoal<'tcx>
) -> Result<
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
NoSolution,
> {
desc { "evaluating `type_op_eq` `{:?}`", goal.value.value }
}

/// Do not call this query directly: part of the `Subtype` type-op
query type_op_subtype(
goal: CanonicalTypeOpSubtypeGoal<'tcx>
) -> Result<
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
NoSolution,
> {
desc { "evaluating `type_op_subtype` `{:?}`", goal.value.value }
}

/// Do not call this query directly: part of the `ProvePredicate` type-op
query type_op_prove_predicate(
goal: CanonicalTypeOpProvePredicateGoal<'tcx>
Expand Down
54 changes: 40 additions & 14 deletions compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ use rustc_middle::mir::{self, dump_mir, MirPass};
use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_target::abi::{FieldIdx, VariantIdx};

use crate::pass_manager::validate_body;

pub struct ByMoveBody;

impl<'tcx> MirPass<'tcx> for ByMoveBody {
Expand Down Expand Up @@ -131,20 +133,40 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|(parent_field_idx, parent_capture), (child_field_idx, child_capture)| {
// Store this set of additional projections (fields and derefs).
// We need to re-apply them later.
let child_precise_captures =
&child_capture.place.projections[parent_capture.place.projections.len()..];
let mut child_precise_captures = child_capture.place.projections
[parent_capture.place.projections.len()..]
.to_vec();

// If the parent captures by-move, and the child captures by-ref, then we
// need to peel an additional `deref` off of the body of the child.
let needs_deref = child_capture.is_by_ref() && !parent_capture.is_by_ref();
if needs_deref {
assert_ne!(
coroutine_kind,
ty::ClosureKind::FnOnce,
// If the parent capture is by-ref, then we need to apply an additional
// deref before applying any further projections to this place.
if parent_capture.is_by_ref() {
child_precise_captures.insert(
0,
Projection { ty: parent_capture.place.ty(), kind: ProjectionKind::Deref },
);
}
// If the child capture is by-ref, then we need to apply a "ref"
// projection (i.e. `&`) at the end. But wait! We don't have that
// as a projection kind. So instead, we can apply its dual and
// *peel* a deref off of the place when it shows up in the MIR body.
// Luckily, by construction this is always possible.
let peel_deref = if child_capture.is_by_ref() {
assert!(
parent_capture.is_by_ref() || coroutine_kind != ty::ClosureKind::FnOnce,
"`FnOnce` coroutine-closures return coroutines that capture from \
their body; it will always result in a borrowck error!"
);
}
true
} else {
false
};

// Regarding the behavior above, you may think that it's redundant to both
// insert a deref and then peel a deref if the parent and child are both
// captured by-ref. This would be correct, except for the case where we have
// precise capturing projections, since the inserted deref is to the *beginning*
// and the peeled deref is at the *end*. I cannot seem to actually find a
// case where this happens, though, but let's keep this code flexible.

// Finally, store the type of the parent's captured place. We need
// this when building the field projection in the MIR body later on.
Expand All @@ -164,7 +186,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
(
FieldIdx::from_usize(parent_field_idx + num_args),
parent_capture_ty,
needs_deref,
peel_deref,
child_precise_captures,
),
)
Expand Down Expand Up @@ -192,6 +214,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
let mut by_move_body = body.clone();
MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));

// Let's just always validate this body.
validate_body(tcx, &mut by_move_body, "Initial coroutine_by_move body".to_string());

// FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body.
by_move_body.source = mir::MirSource::from_instance(InstanceKind::CoroutineKindShim {
coroutine_def_id: coroutine_def_id.to_def_id(),
Expand All @@ -202,7 +228,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {

struct MakeByMoveBody<'tcx> {
tcx: TyCtxt<'tcx>,
field_remapping: UnordMap<FieldIdx, (FieldIdx, Ty<'tcx>, bool, &'tcx [Projection<'tcx>])>,
field_remapping: UnordMap<FieldIdx, (FieldIdx, Ty<'tcx>, bool, Vec<Projection<'tcx>>)>,
by_move_coroutine_ty: Ty<'tcx>,
}

Expand All @@ -223,14 +249,14 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
if place.local == ty::CAPTURE_STRUCT_LOCAL
&& let Some((&mir::ProjectionElem::Field(idx, _), projection)) =
place.projection.split_first()
&& let Some(&(remapped_idx, remapped_ty, needs_deref, bridging_projections)) =
&& let Some(&(remapped_idx, remapped_ty, peel_deref, ref bridging_projections)) =
self.field_remapping.get(&idx)
{
// As noted before, if the parent closure captures a field by value, and
// the child captures a field by ref, then for the by-move body we're
// generating, we also are taking that field by value. Peel off a deref,
// since a layer of ref'ing has now become redundant.
let final_projections = if needs_deref {
let final_projections = if peel_deref {
let Some((mir::ProjectionElem::Deref, projection)) = projection.split_first()
else {
bug!(
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) {

// Sanitizers can only be used on platforms that we know have working sanitizer codegen.
let supported_sanitizers = sess.target.options.supported_sanitizers;
let unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers;
let mut unsupported_sanitizers = sess.opts.unstable_opts.sanitizer - supported_sanitizers;
// Niche: if `fixed-x18`, or effectively switching on `reserved-x18` flag, is enabled
// we should allow Shadow Call Stack sanitizer.
if sess.opts.unstable_opts.fixed_x18 && sess.target.arch == "aarch64" {
unsupported_sanitizers -= SanitizerSet::SHADOWCALLSTACK;
}
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => {
Expand Down
33 changes: 0 additions & 33 deletions compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ use crate::traits::{ObligationCause, ObligationCtxt};

pub mod ascribe_user_type;
pub mod custom;
pub mod eq;
pub mod implied_outlives_bounds;
pub mod normalize;
pub mod outlives;
pub mod prove_predicate;
pub mod subtype;

pub use rustc_middle::traits::query::type_op::*;

Expand Down
30 changes: 0 additions & 30 deletions compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs

This file was deleted.

24 changes: 0 additions & 24 deletions compiler/rustc_traits/src/type_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,14 @@ use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
type_op_ascribe_user_type_with_span, AscribeUserType,
};
use rustc_trait_selection::traits::query::type_op::eq::Eq;
use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};

pub(crate) fn provide(p: &mut Providers) {
*p = Providers {
type_op_ascribe_user_type,
type_op_eq,
type_op_prove_predicate,
type_op_subtype,
type_op_normalize_ty,
type_op_normalize_clause,
type_op_normalize_fn_sig,
Expand All @@ -39,16 +35,6 @@ fn type_op_ascribe_user_type<'tcx>(
})
}

fn type_op_eq<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
let (param_env, Eq { a, b }) = key.into_parts();
Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?)
})
}

fn type_op_normalize<'tcx, T>(
ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, Normalize<T>>,
Expand Down Expand Up @@ -91,16 +77,6 @@ fn type_op_normalize_poly_fn_sig<'tcx>(
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
}

fn type_op_subtype<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
let (param_env, Subtype { sub, sup }) = key.into_parts();
Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?)
})
}

fn type_op_prove_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
Expand Down
6 changes: 3 additions & 3 deletions src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/
RUN ./build-clang.sh
ENV CC=clang CXX=clang++

# rustc's LLVM needs zstd.
COPY scripts/zstd.sh /tmp/
RUN ./zstd.sh
# Build zstd to enable `llvm.libzstd`.
COPY host-x86_64/dist-x86_64-linux/build-zstd.sh /tmp/
RUN ./build-zstd.sh

COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
--enable-sanitizers \
--enable-profiler \
--enable-compiler-docs
--enable-compiler-docs \
--set llvm.libzstd=true
ENV SCRIPT python3 ../x.py --stage 2 test
5 changes: 5 additions & 0 deletions src/doc/rustc/src/platform-support/android.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ Currently the `riscv64-linux-android` target requires the following architecture
* `Zba` (address calculation instructions)
* `Zbb` (base instructions)
* `Zbs` (single-bit instructions)

### aarch64-linux-android on Nightly compilers

As soon as `-Zfixed-x18` compiler flag is supplied, the [`ShadowCallStack` sanitizer](https://releases.llvm.org/7.0.1/tools/clang/docs/ShadowCallStack.html)
instrumentation is also made avaiable by supplying the second compiler flag `-Zsanitizer=shadow-call-stack`.
Loading

0 comments on commit ed311ef

Please sign in to comment.