Skip to content

Commit

Permalink
Auto merge of #131495 - matthiaskrgr:rollup-lwf2u4i, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #130625 (Fix a few relative paths in rustc doc)
 - #131397 (fix/update teach_note from 'escaping mutable ref/ptr' const-check)
 - #131479 (Apple: Avoid redundant `-Wl,-dylib` flag when linking)
 - #131480 (Fix hardcoded strip path when cross-compiling from Linux to Darwin)
 - #131482 (structurally resolve adts and tuples expectations too)
 - #131484 (Add myself back to review rotation)
 - #131491 (impossible obligations fast path)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Oct 10, 2024
2 parents de19f2b + 1c62cff commit 4cc494b
Show file tree
Hide file tree
Showing 20 changed files with 171 additions and 87 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,9 @@ fn link_natively(
let strip = sess.opts.cg.strip;

if sess.target.is_like_osx {
let stripcmd = "/usr/bin/strip";
// Use system `strip` when running on host macOS.
// <https://github.com/rust-lang/rust/pull/130781>
let stripcmd = if cfg!(target_os = "macos") { "/usr/bin/strip" } else { "strip" };
match (strip, crate_type) {
(Strip::Debuginfo, _) => {
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S"))
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,14 @@ impl<'a> GccLinker<'a> {
fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) {
// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.is_like_osx {
if !self.is_ld {
if self.is_cc() {
// `-dynamiclib` makes `cc` pass `-dylib` to the linker.
self.cc_arg("-dynamiclib");
} else {
self.link_arg("-dylib");
// Clang also sets `-dynamic`, but that's implied by `-dylib`, so unnecessary.
}

self.link_arg("-dylib");

// Note that the `osx_rpath_install_name` option here is a hack
// purely to support bootstrap right now, we should get a more
// principled solution at some point to force the compiler to pass
Expand Down
51 changes: 26 additions & 25 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,16 @@ const_eval_incompatible_return_types =
const_eval_incompatible_types =
calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
const_eval_interior_mutable_data_refer =
const_eval_interior_mutable_ref_escaping =
{const_eval_const_context}s cannot refer to interior mutable data
.label = this borrow of an interior mutable value may end up in the final value
.help = to fix this, the value can be extracted to a separate `static` item and then referenced
.teach_note =
A constant containing interior mutable data behind a reference can allow you to modify that data.
This would make multiple uses of a constant to be able to see different values and allow circumventing
the `Send` and `Sync` requirements for shared mutable data, which is unsound.
References that escape into the final value of a constant or static must be immutable.
This is to avoid accidentally creating shared mutable state.
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
const_eval_intern_kind = {$kind ->
[static] static
Expand Down Expand Up @@ -229,6 +231,24 @@ const_eval_modified_global =
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
const_eval_mutable_raw_escaping =
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
.teach_note =
Pointers that escape into the final value of a constant or static must be immutable.
This is to avoid accidentally creating shared mutable state.
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
const_eval_mutable_ref_escaping =
mutable references are not allowed in the final value of {const_eval_const_context}s
.teach_note =
References that escape into the final value of a constant or static must be immutable.
This is to avoid accidentally creating shared mutable state.
If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
const_eval_non_const_fmt_macro_call =
cannot call non-const formatting macro in {const_eval_const_context}s
Expand Down Expand Up @@ -364,30 +384,11 @@ const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in
const_eval_unallowed_heap_allocations =
allocations are not allowed in {const_eval_const_context}s
.label = allocation not allowed in {const_eval_const_context}s
.teach_note = The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
.teach_note =
The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created.
const_eval_unallowed_inline_asm =
inline assembly is not allowed in {const_eval_const_context}s
const_eval_unallowed_mutable_raw =
raw mutable pointers are not allowed in the final value of {const_eval_const_context}s
.teach_note =
References in statics and constants may only refer to immutable values.
Statics are shared everywhere, and if they refer to mutable data one might violate memory
safety since holding multiple mutable references to shared data is not allowed.
If you really want global mutable state, try using static mut or a global UnsafeCell.
const_eval_unallowed_mutable_refs =
mutable references are not allowed in the final value of {const_eval_const_context}s
.teach_note =
Statics are shared everywhere, and if they refer to mutable data one might violate memory
safety since holding multiple mutable references to shared data is not allowed.
If you really want global mutable state, try using static mut or a global UnsafeCell.
const_eval_unallowed_op_in_const_context =
{$msg}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
}

// This can be called on stable via the `vec!` macro.
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
self.check_op(ops::HeapAllocation);
return;
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
DiagImportance::Secondary
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.dcx().create_err(errors::InteriorMutableDataRefer {
ccx.dcx().create_err(errors::InteriorMutableRefEscaping {
span,
opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)),
kind: ccx.const_kind(),
Expand Down Expand Up @@ -430,12 +430,12 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
match self.0 {
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw {
hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0764),
}),
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs {
hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0764),
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ pub(crate) struct UnstableConstFn {
}

#[derive(Diagnostic)]
#[diag(const_eval_unallowed_mutable_refs, code = E0764)]
pub(crate) struct UnallowedMutableRefs {
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
pub(crate) struct MutableRefEscaping {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
Expand All @@ -128,8 +128,8 @@ pub(crate) struct UnallowedMutableRefs {
}

#[derive(Diagnostic)]
#[diag(const_eval_unallowed_mutable_raw, code = E0764)]
pub(crate) struct UnallowedMutableRaw {
#[diag(const_eval_mutable_raw_escaping, code = E0764)]
pub(crate) struct MutableRawEscaping {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
Expand Down Expand Up @@ -181,8 +181,8 @@ pub(crate) struct UnallowedInlineAsm {
}

#[derive(Diagnostic)]
#[diag(const_eval_interior_mutable_data_refer, code = E0492)]
pub(crate) struct InteriorMutableDataRefer {
#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)]
pub(crate) struct InteriorMutableRefEscaping {
#[primary_span]
#[label]
pub span: Span,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub mod weak_lang_items;
#[cfg(test)]
mod tests;

#[doc(no_inline)]
pub use hir::*;
pub use hir_id::*;
pub use lang_items::{LangItem, LanguageItems};
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1783,7 +1783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
let flds = expected.only_has_type(self).and_then(|ty| {
let ty = self.resolve_vars_with_obligations(ty);
let ty = self.try_structurally_resolve_type(expr.span, ty);
match ty.kind() {
ty::Tuple(flds) => Some(&flds[..]),
_ => None,
Expand Down Expand Up @@ -1861,7 +1861,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let tcx = self.tcx;

let adt_ty = self.resolve_vars_with_obligations(adt_ty);
let adt_ty = self.try_structurally_resolve_type(span, adt_ty);
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
self.fudge_inference_if_ok(|| {
let ocx = ObligationCtxt::new(self);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod vec;
pub use idx::Idx;
pub use rustc_index_macros::newtype_index;
pub use slice::IndexSlice;
#[doc(no_inline)]
pub use vec::IndexVec;

/// Type size assertion. The first argument is a type and the second argument is its expected size.
Expand Down
72 changes: 54 additions & 18 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use crate::solve::inspect::{self, ProofTreeBuilder};
use crate::solve::search_graph::SearchGraph;
use crate::solve::{
CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind,
GoalSource, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
SolverMode,
GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData,
QueryResult, SolverMode,
};

pub(super) mod canonical;
Expand Down Expand Up @@ -126,11 +126,31 @@ pub enum GenerateProofTree {
}

pub trait SolverDelegateEvalExt: SolverDelegate {
/// Evaluates a goal from **outside** of the trait solver.
///
/// Using this while inside of the solver is wrong as it uses a new
/// search graph which would break cycle detection.
fn evaluate_root_goal(
&self,
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
generate_proof_tree: GenerateProofTree,
) -> (Result<(bool, Certainty), NoSolution>, Option<inspect::GoalEvaluation<Self::Interner>>);
) -> (
Result<(HasChanged, Certainty), NoSolution>,
Option<inspect::GoalEvaluation<Self::Interner>>,
);

/// Check whether evaluating `goal` with a depth of `root_depth` may
/// succeed. This only returns `false` if the goal is guaranteed to
/// not hold. In case evaluation overflows and fails with ambiguity this
/// returns `true`.
///
/// This is only intended to be used as a performance optimization
/// in coherence checking.
fn root_goal_may_hold_with_depth(
&self,
root_depth: usize,
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
) -> bool;

// FIXME: This is only exposed because we need to use it in `analyse.rs`
// which is not yet uplifted. Once that's done, we should remove this.
Expand All @@ -139,7 +159,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
generate_proof_tree: GenerateProofTree,
) -> (
Result<(NestedNormalizationGoals<Self::Interner>, bool, Certainty), NoSolution>,
Result<(NestedNormalizationGoals<Self::Interner>, HasChanged, Certainty), NoSolution>,
Option<inspect::GoalEvaluation<Self::Interner>>,
);
}
Expand All @@ -149,31 +169,41 @@ where
D: SolverDelegate<Interner = I>,
I: Interner,
{
/// Evaluates a goal from **outside** of the trait solver.
///
/// Using this while inside of the solver is wrong as it uses a new
/// search graph which would break cycle detection.
#[instrument(level = "debug", skip(self))]
fn evaluate_root_goal(
&self,
goal: Goal<I, I::Predicate>,
generate_proof_tree: GenerateProofTree,
) -> (Result<(bool, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
EvalCtxt::enter_root(self, generate_proof_tree, |ecx| {
) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| {
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
})
}

fn root_goal_may_hold_with_depth(
&self,
root_depth: usize,
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
) -> bool {
self.probe(|| {
EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, |ecx| {
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
})
.0
})
.is_ok()
}

#[instrument(level = "debug", skip(self))]
fn evaluate_root_goal_raw(
&self,
goal: Goal<I, I::Predicate>,
generate_proof_tree: GenerateProofTree,
) -> (
Result<(NestedNormalizationGoals<I>, bool, Certainty), NoSolution>,
Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>,
Option<inspect::GoalEvaluation<I>>,
) {
EvalCtxt::enter_root(self, generate_proof_tree, |ecx| {
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| {
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal)
})
}
Expand All @@ -197,10 +227,11 @@ where
/// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]).
pub(super) fn enter_root<R>(
delegate: &D,
root_depth: usize,
generate_proof_tree: GenerateProofTree,
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
) -> (R, Option<inspect::GoalEvaluation<I>>) {
let mut search_graph = SearchGraph::new(delegate.solver_mode());
let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth);

let mut ecx = EvalCtxt {
delegate,
Expand Down Expand Up @@ -339,7 +370,7 @@ where
goal_evaluation_kind: GoalEvaluationKind,
source: GoalSource,
goal: Goal<I, I::Predicate>,
) -> Result<(bool, Certainty), NoSolution> {
) -> Result<(HasChanged, Certainty), NoSolution> {
let (normalization_nested_goals, has_changed, certainty) =
self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?;
assert!(normalization_nested_goals.is_empty());
Expand All @@ -360,7 +391,7 @@ where
goal_evaluation_kind: GoalEvaluationKind,
_source: GoalSource,
goal: Goal<I, I::Predicate>,
) -> Result<(NestedNormalizationGoals<I>, bool, Certainty), NoSolution> {
) -> Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution> {
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
let mut goal_evaluation =
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
Expand All @@ -378,8 +409,13 @@ where
Ok(response) => response,
};

let has_changed = !response.value.var_values.is_identity_modulo_regions()
|| !response.value.external_constraints.opaque_types.is_empty();
let has_changed = if !response.value.var_values.is_identity_modulo_regions()
|| !response.value.external_constraints.opaque_types.is_empty()
{
HasChanged::Yes
} else {
HasChanged::No
};

let (normalization_nested_goals, certainty) =
self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
Expand Down Expand Up @@ -552,7 +588,7 @@ where
for (source, goal) in goals.goals {
let (has_changed, certainty) =
self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
if has_changed {
if has_changed == HasChanged::Yes {
unchanged_certainty = None;
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ enum GoalEvaluationKind {
Nested,
}

/// Whether evaluating this goal ended up changing the
/// inference state.
#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
pub enum HasChanged {
Yes,
No,
}

// FIXME(trait-system-refactor-initiative#117): we don't detect whether a response
// ended up pulling down any universes.
fn has_no_inference_or_external_constraints<I: Interner>(
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/search_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ where
}

const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize = 4;
fn recursion_limit(cx: I) -> usize {
cx.recursion_limit()
}

fn initial_provisional_result(
cx: I,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/solve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod inspect;
mod normalize;
mod select;

pub(crate) use delegate::SolverDelegate;
pub use fulfill::{FulfillmentCtxt, NextSolverError};
pub(crate) use normalize::deeply_normalize_for_diagnostics;
pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
Expand Down
Loading

0 comments on commit 4cc494b

Please sign in to comment.