Skip to content

Commit

Permalink
Auto merge of #134716 - Zalathar:rollup-1h4q8cc, r=Zalathar
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #134638 (Fix effect predicates from item bounds in old solver)
 - #134662 (Fix safety docs for `dyn Any + Send {+ Sync}`)
 - #134689 (core: fix const ptr::swap_nonoverlapping when there are pointers at odd offsets)
 - #134699 (Belay new reviews for workingjubilee)
 - #134701 (Correctly note item kind in `NonConstFunctionCall` error message)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 24, 2024
2 parents f334342 + 772b95e commit d3e71fd
Show file tree
Hide file tree
Showing 104 changed files with 427 additions and 232 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ const_eval_non_const_fmt_macro_call =
cannot call non-const formatting macro in {const_eval_const_context}s
const_eval_non_const_fn_call =
cannot call non-const fn `{$def_path_str}` in {const_eval_const_context}s
cannot call non-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
const_eval_non_const_impl =
impl defined here, but it is not `const`
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
_ => ccx.dcx().create_err(errors::NonConstFnCall {
span,
def_descr: ccx.tcx.def_descr(callee),
def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
kind: ccx.const_kind(),
}),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ pub(crate) struct NonConstFnCall {
#[primary_span]
pub span: Span,
pub def_path_str: String,
pub def_descr: &'static str,
pub kind: ConstContext,
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0015.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn create_some() -> Option<u8> {
Some(1)
}
// error: cannot call non-const fn `create_some` in constants
// error: cannot call non-const function `create_some` in constants
const FOO: Option<u8> = create_some();
```

Expand Down
165 changes: 137 additions & 28 deletions compiler/rustc_trait_selection/src/traits/effects.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use rustc_hir as hir;
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt};
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
use rustc_middle::span_bug;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, TypingMode};
use rustc_type_ir::elaborate::elaborate;
use rustc_type_ir::solve::NoSolution;
use thin_vec::ThinVec;
use thin_vec::{ThinVec, thin_vec};

use super::SelectionContext;
use super::normalize::normalize_with_depth_to;

pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>;

Expand Down Expand Up @@ -38,6 +40,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
Err(EvaluationFailure::NoSolution) => {}
}

match evaluate_host_effect_from_item_bounds(selcx, obligation) {
Ok(result) => return Ok(result),
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
Err(EvaluationFailure::NoSolution) => {}
}

match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
Ok(result) => return Ok(result),
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
Expand All @@ -48,24 +56,45 @@ pub fn evaluate_host_effect_obligation<'tcx>(
}

fn match_candidate<'tcx>(
infcx: &InferCtxt<'tcx>,
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &HostEffectObligation<'tcx>,
candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
candidate_is_unnormalized: bool,
more_nested: impl FnOnce(&mut SelectionContext<'_, 'tcx>, &mut ThinVec<PredicateObligation<'tcx>>),
) -> Result<ThinVec<PredicateObligation<'tcx>>, NoSolution> {
if !candidate.skip_binder().constness.satisfies(obligation.predicate.constness) {
return Err(NoSolution);
}

let candidate = infcx.instantiate_binder_with_fresh_vars(
let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars(
obligation.cause.span,
BoundRegionConversionTime::HigherRankedType,
candidate,
);

let mut nested = infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
.into_obligations();
let mut nested = thin_vec![];

// Unlike param-env bounds, item bounds may not be normalized.
if candidate_is_unnormalized {
candidate = normalize_with_depth_to(
selcx,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth,
candidate,
&mut nested,
);
}

nested.extend(
selcx
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
.into_obligations(),
);

more_nested(selcx, &mut nested);

for nested in &mut nested {
nested.set_depth_from_parent(obligation.recursion_depth);
Expand All @@ -82,36 +111,116 @@ fn evaluate_host_effect_from_bounds<'tcx>(
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
let mut candidate = None;

for predicate in obligation.param_env.caller_bounds() {
let bound_predicate = predicate.kind();
if let ty::ClauseKind::HostEffect(data) = predicate.kind().skip_binder() {
let data = bound_predicate.rebind(data);
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
continue;
for clause in obligation.param_env.caller_bounds() {
let bound_clause = clause.kind();
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
continue;
};
let data = bound_clause.rebind(data);
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
continue;
}

if !drcx
.args_may_unify(obligation.predicate.trait_ref.args, data.skip_binder().trait_ref.args)
{
continue;
}

let is_match =
infcx.probe(|_| match_candidate(selcx, obligation, data, false, |_, _| {}).is_ok());

if is_match {
if candidate.is_some() {
return Err(EvaluationFailure::Ambiguous);
} else {
candidate = Some(data);
}
}
}

if !drcx.args_may_unify(
obligation.predicate.trait_ref.args,
data.skip_binder().trait_ref.args,
if let Some(data) = candidate {
Ok(match_candidate(selcx, obligation, data, false, |_, _| {})
.expect("candidate matched before, so it should match again"))
} else {
Err(EvaluationFailure::NoSolution)
}
}

fn evaluate_host_effect_from_item_bounds<'tcx>(
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &HostEffectObligation<'tcx>,
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
let infcx = selcx.infcx;
let tcx = infcx.tcx;
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
let mut candidate = None;

let mut consider_ty = obligation.predicate.self_ty();
while let ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) = *consider_ty.kind() {
if tcx.is_conditionally_const(alias_ty.def_id) {
for clause in elaborate(
tcx,
tcx.explicit_implied_const_bounds(alias_ty.def_id)
.iter_instantiated_copied(tcx, alias_ty.args)
.map(|(trait_ref, _)| {
trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness)
}),
) {
continue;
}
let bound_clause = clause.kind();
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
unreachable!("should not elaborate non-HostEffect from HostEffect")
};
let data = bound_clause.rebind(data);
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
continue;
}

let is_match = infcx.probe(|_| match_candidate(infcx, obligation, data).is_ok());
if !drcx.args_may_unify(
obligation.predicate.trait_ref.args,
data.skip_binder().trait_ref.args,
) {
continue;
}

if is_match {
if candidate.is_some() {
return Err(EvaluationFailure::Ambiguous);
} else {
candidate = Some(data);
let is_match = infcx
.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());

if is_match {
if candidate.is_some() {
return Err(EvaluationFailure::Ambiguous);
} else {
candidate = Some((data, alias_ty));
}
}
}
}

if kind != ty::Projection {
break;
}

consider_ty = alias_ty.self_ty();
}

if let Some(data) = candidate {
Ok(match_candidate(infcx, obligation, data)
.expect("candidate matched before, so it should match again"))
if let Some((data, alias_ty)) = candidate {
Ok(match_candidate(selcx, obligation, data, true, |selcx, nested| {
// An alias bound only holds if we also check the const conditions
// of the alias, so we need to register those, too.
let const_conditions = normalize_with_depth_to(
selcx,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth,
tcx.const_conditions(alias_ty.def_id).instantiate(tcx, alias_ty.args),
nested,
);
nested.extend(const_conditions.into_iter().map(|(trait_ref, _)| {
obligation
.with(tcx, trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness))
}));
})
.expect("candidate matched before, so it should match again"))
} else {
Err(EvaluationFailure::NoSolution)
}
Expand Down
14 changes: 12 additions & 2 deletions library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ impl dyn Any + Send {
///
/// # Safety
///
/// Same as the method on the type `dyn Any`.
/// The contained value must be of type `T`. Calling this method
/// with the incorrect type is *undefined behavior*.
#[unstable(feature = "downcast_unchecked", issue = "90850")]
#[inline]
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
Expand Down Expand Up @@ -451,7 +452,8 @@ impl dyn Any + Send {
///
/// # Safety
///
/// Same as the method on the type `dyn Any`.
/// The contained value must be of type `T`. Calling this method
/// with the incorrect type is *undefined behavior*.
#[unstable(feature = "downcast_unchecked", issue = "90850")]
#[inline]
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
Expand Down Expand Up @@ -552,6 +554,10 @@ impl dyn Any + Send + Sync {
/// assert_eq!(*x.downcast_ref_unchecked::<usize>(), 1);
/// }
/// ```
/// # Safety
///
/// The contained value must be of type `T`. Calling this method
/// with the incorrect type is *undefined behavior*.
#[unstable(feature = "downcast_unchecked", issue = "90850")]
#[inline]
pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
Expand All @@ -576,6 +582,10 @@ impl dyn Any + Send + Sync {
///
/// assert_eq!(*x.downcast_ref::<usize>().unwrap(), 2);
/// ```
/// # Safety
///
/// The contained value must be of type `T`. Calling this method
/// with the incorrect type is *undefined behavior*.
#[unstable(feature = "downcast_unchecked", issue = "90850")]
#[inline]
pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
Expand Down
14 changes: 7 additions & 7 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3795,15 +3795,15 @@ where
/// See [`const_eval_select()`] for the rules and requirements around that intrinsic.
pub(crate) macro const_eval_select {
(
@capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
@capture$([$($binders:tt)*])? { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
if const
$(#[$compiletime_attr:meta])* $compiletime:block
else
$(#[$runtime_attr:meta])* $runtime:block
) => {
// Use the `noinline` arm, after adding explicit `inline` attributes
$crate::intrinsics::const_eval_select!(
@capture { $($arg : $ty = $val),* } $(-> $ret)? :
@capture$([$($binders)*])? { $($arg : $ty = $val),* } $(-> $ret)? :
#[noinline]
if const
#[inline] // prevent codegen on this function
Expand All @@ -3817,20 +3817,20 @@ pub(crate) macro const_eval_select {
},
// With a leading #[noinline], we don't add inline attributes
(
@capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
@capture$([$($binders:tt)*])? { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
#[noinline]
if const
$(#[$compiletime_attr:meta])* $compiletime:block
else
$(#[$runtime_attr:meta])* $runtime:block
) => {{
$(#[$runtime_attr])*
fn runtime($($arg: $ty),*) $( -> $ret )? {
fn runtime$(<$($binders)*>)?($($arg: $ty),*) $( -> $ret )? {
$runtime
}

$(#[$compiletime_attr])*
const fn compiletime($($arg: $ty),*) $( -> $ret )? {
const fn compiletime$(<$($binders)*>)?($($arg: $ty),*) $( -> $ret )? {
// Don't warn if one of the arguments is unused.
$(let _ = $arg;)*

Expand All @@ -3842,14 +3842,14 @@ pub(crate) macro const_eval_select {
// We support leaving away the `val` expressions for *all* arguments
// (but not for *some* arguments, that's too tricky).
(
@capture { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? :
@capture$([$($binders:tt)*])? { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? :
if const
$(#[$compiletime_attr:meta])* $compiletime:block
else
$(#[$runtime_attr:meta])* $runtime:block
) => {
$crate::intrinsics::const_eval_select!(
@capture { $($arg : $ty = $arg),* } $(-> $ret)? :
@capture$([$($binders)*])? { $($arg : $ty = $arg),* } $(-> $ret)? :
if const
$(#[$compiletime_attr])* $compiletime
else
Expand Down
Loading

0 comments on commit d3e71fd

Please sign in to comment.