Skip to content

Commit 6689597

Browse files
committed
Auto merge of #132831 - workingjubilee:rollup-6fdif44, r=workingjubilee
Rollup of 6 pull requests Successful merges: - #131258 (Stabilize s390x inline assembly) - #132801 (interpret: get_alloc_info: also return mutability) - #132823 (require const_impl_trait gate for all conditional and trait const calls) - #132824 (Update grammar in wasm-c-abi's compiler flag documentation) - #132825 (Exclude relnotes-tracking-issue from needs-triage) - #132828 (Additional tests to ensure let is rejected during parsing) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7660aed + c19d56c commit 6689597

38 files changed

+3312
-1236
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
4848
| asm::InlineAsmArch::RiscV32
4949
| asm::InlineAsmArch::RiscV64
5050
| asm::InlineAsmArch::LoongArch64
51+
| asm::InlineAsmArch::S390x
5152
);
5253
if !is_stable && !self.tcx.features().asm_experimental_arch() {
5354
feature_err(

compiler/rustc_const_eval/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ const_eval_closure_fndef_not_const =
2525
function defined here, but it is not `const`
2626
const_eval_closure_non_const =
2727
cannot call non-const closure in {const_eval_const_context}s
28+
29+
const_eval_conditionally_const_call =
30+
cannot call conditionally-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
31+
2832
const_eval_consider_dereferencing =
2933
consider dereferencing here
3034

compiler/rustc_const_eval/src/check_consts/check.rs

+30-59
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::mir::visit::Visitor;
1515
use rustc_middle::mir::*;
1616
use rustc_middle::span_bug;
1717
use rustc_middle::ty::adjustment::PointerCoercion;
18-
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt};
18+
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
1919
use rustc_mir_dataflow::Analysis;
2020
use rustc_mir_dataflow::impls::MaybeStorageLive;
2121
use rustc_mir_dataflow::storage::always_storage_live_locals;
@@ -361,31 +361,21 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
361361
!is_transient
362362
}
363363

364+
/// Returns whether there are const-conditions.
364365
fn revalidate_conditional_constness(
365366
&mut self,
366367
callee: DefId,
367368
callee_args: ty::GenericArgsRef<'tcx>,
368-
call_source: CallSource,
369369
call_span: Span,
370-
) {
370+
) -> bool {
371371
let tcx = self.tcx;
372372
if !tcx.is_conditionally_const(callee) {
373-
return;
373+
return false;
374374
}
375375

376376
let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args);
377-
// If there are any const conditions on this fn and `const_trait_impl`
378-
// is not enabled, simply bail. We shouldn't be able to call conditionally
379-
// const functions on stable.
380-
if !const_conditions.is_empty() && !tcx.features().const_trait_impl() {
381-
self.check_op(ops::FnCallNonConst {
382-
callee,
383-
args: callee_args,
384-
span: call_span,
385-
call_source,
386-
feature: Some(sym::const_trait_impl),
387-
});
388-
return;
377+
if const_conditions.is_empty() {
378+
return false;
389379
}
390380

391381
let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
@@ -421,6 +411,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
421411
tcx.dcx()
422412
.span_delayed_bug(call_span, "this should have reported a ~const error in HIR");
423413
}
414+
415+
true
424416
}
425417
}
426418

@@ -627,11 +619,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
627619
_ => unreachable!(),
628620
};
629621

630-
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
622+
let ConstCx { tcx, body, .. } = *self.ccx;
631623

632624
let fn_ty = func.ty(body, tcx);
633625

634-
let (mut callee, mut fn_args) = match *fn_ty.kind() {
626+
let (callee, fn_args) = match *fn_ty.kind() {
635627
ty::FnDef(def_id, fn_args) => (def_id, fn_args),
636628

637629
ty::FnPtr(..) => {
@@ -645,57 +637,38 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
645637
}
646638
};
647639

648-
self.revalidate_conditional_constness(callee, fn_args, call_source, *fn_span);
640+
let has_const_conditions =
641+
self.revalidate_conditional_constness(callee, fn_args, *fn_span);
649642

650-
let mut is_trait = false;
651643
// Attempting to call a trait method?
652644
if let Some(trait_did) = tcx.trait_of_item(callee) {
653-
trace!("attempting to call a trait method");
645+
// We can't determine the actual callee here, so we have to do different checks
646+
// than usual.
654647

648+
trace!("attempting to call a trait method");
655649
let trait_is_const = tcx.is_const_trait(trait_did);
656-
// trait method calls are only permitted when `effects` is enabled.
657-
// typeck ensures the conditions for calling a const trait method are met,
658-
// so we only error if the trait isn't const. We try to resolve the trait
659-
// into the concrete method, and uses that for const stability checks.
660-
// FIXME(const_trait_impl) we might consider moving const stability checks
661-
// to typeck as well.
662-
if tcx.features().const_trait_impl() && trait_is_const {
663-
// This skips the check below that ensures we only call `const fn`.
664-
is_trait = true;
665-
666-
if let Ok(Some(instance)) =
667-
Instance::try_resolve(tcx, param_env, callee, fn_args)
668-
&& let InstanceKind::Item(def) = instance.def
669-
{
670-
// Resolve a trait method call to its concrete implementation, which may be in a
671-
// `const` trait impl. This is only used for the const stability check below, since
672-
// we want to look at the concrete impl's stability.
673-
fn_args = instance.args;
674-
callee = def;
675-
}
650+
651+
if trait_is_const {
652+
// Trait calls are always conditionally-const.
653+
self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
654+
// FIXME(const_trait_impl): do a more fine-grained check whether this
655+
// particular trait can be const-stably called.
676656
} else {
677-
// if the trait is const but the user has not enabled the feature(s),
678-
// suggest them.
679-
let feature = if trait_is_const {
680-
Some(if tcx.features().const_trait_impl() {
681-
sym::effects
682-
} else {
683-
sym::const_trait_impl
684-
})
685-
} else {
686-
None
687-
};
657+
// Not even a const trait.
688658
self.check_op(ops::FnCallNonConst {
689659
callee,
690660
args: fn_args,
691661
span: *fn_span,
692662
call_source,
693-
feature,
694663
});
695-
// If we allowed this, we're in miri-unleashed mode, so we might
696-
// as well skip the remaining checks.
697-
return;
698664
}
665+
// That's all we can check here.
666+
return;
667+
}
668+
669+
// Even if we know the callee, ensure we can use conditionally-const calls.
670+
if has_const_conditions {
671+
self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
699672
}
700673

701674
// At this point, we are calling a function, `callee`, whose `DefId` is known...
@@ -783,14 +756,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
783756
return;
784757
}
785758

786-
// Trait functions are not `const fn` so we have to skip them here.
787-
if !tcx.is_const_fn(callee) && !is_trait {
759+
if !tcx.is_const_fn(callee) {
788760
self.check_op(ops::FnCallNonConst {
789761
callee,
790762
args: fn_args,
791763
span: *fn_span,
792764
call_source,
793-
feature: None,
794765
});
795766
// If we allowed this, we're in miri-unleashed mode, so we might
796767
// as well skip the remaining checks.

compiler/rustc_const_eval/src/check_consts/ops.rs

+34-19
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,52 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
7070
}
7171
}
7272

73+
/// A call to a function that is in a trait, or has trait bounds that make it conditionally-const.
74+
#[derive(Debug)]
75+
pub(crate) struct ConditionallyConstCall<'tcx> {
76+
pub callee: DefId,
77+
pub args: GenericArgsRef<'tcx>,
78+
}
79+
80+
impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
81+
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
82+
// We use the `const_trait_impl` gate for all conditionally-const calls.
83+
Status::Unstable {
84+
gate: sym::const_trait_impl,
85+
safe_to_expose_on_stable: false,
86+
// We don't want the "mark the callee as `#[rustc_const_stable_indirect]`" hint
87+
is_function_call: false,
88+
}
89+
}
90+
91+
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
92+
ccx.tcx.sess.create_feature_err(
93+
errors::ConditionallyConstCall {
94+
span,
95+
def_path_str: ccx.tcx.def_path_str_with_args(self.callee, self.args),
96+
def_descr: ccx.tcx.def_descr(self.callee),
97+
kind: ccx.const_kind(),
98+
},
99+
sym::const_trait_impl,
100+
)
101+
}
102+
}
103+
73104
/// A function call where the callee is not marked as `const`.
74105
#[derive(Debug, Clone, Copy)]
75106
pub(crate) struct FnCallNonConst<'tcx> {
76107
pub callee: DefId,
77108
pub args: GenericArgsRef<'tcx>,
78109
pub span: Span,
79110
pub call_source: CallSource,
80-
pub feature: Option<Symbol>,
81111
}
82112

83113
impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
84114
// FIXME: make this translatable
85115
#[allow(rustc::diagnostic_outside_of_impl)]
86116
#[allow(rustc::untranslatable_diagnostic)]
87117
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
88-
let FnCallNonConst { callee, args, span, call_source, feature } = *self;
118+
let FnCallNonConst { callee, args, span, call_source } = *self;
89119
let ConstCx { tcx, param_env, .. } = *ccx;
90120
let caller = ccx.def_id();
91121

@@ -285,14 +315,6 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
285315
ccx.const_kind(),
286316
));
287317

288-
if let Some(feature) = feature {
289-
ccx.tcx.disabled_nightly_features(
290-
&mut err,
291-
Some(ccx.tcx.local_def_id_to_hir_id(caller)),
292-
[(String::new(), feature)],
293-
);
294-
}
295-
296318
if let ConstContext::Static(_) = ccx.const_kind() {
297319
err.note(fluent_generated::const_eval_lazy_lock);
298320
}
@@ -398,15 +420,8 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
398420

399421
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
400422
let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
401-
if let hir::CoroutineKind::Desugared(
402-
hir::CoroutineDesugaring::Async,
403-
hir::CoroutineSource::Block,
404-
) = self.0
405-
{
406-
ccx.tcx.sess.create_feature_err(
407-
errors::UnallowedOpInConstContext { span, msg },
408-
sym::const_async_blocks,
409-
)
423+
if let Status::Unstable { gate, .. } = self.status_in_item(ccx) {
424+
ccx.tcx.sess.create_feature_err(errors::UnallowedOpInConstContext { span, msg }, gate)
410425
} else {
411426
ccx.dcx().create_err(errors::UnallowedOpInConstContext { span, msg })
412427
}

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,9 @@ fn report_validation_error<'tcx>(
472472
backtrace.print_backtrace();
473473

474474
let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
475-
let (size, align, _) = ecx.get_alloc_info(alloc_id);
476-
let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes };
475+
let info = ecx.get_alloc_info(alloc_id);
476+
let raw_bytes =
477+
errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
477478

478479
crate::const_eval::report(
479480
*ecx.tcx,

compiler/rustc_const_eval/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ pub(crate) struct NonConstFmtMacroCall {
176176
pub kind: ConstContext,
177177
}
178178

179+
#[derive(Diagnostic)]
180+
#[diag(const_eval_conditionally_const_call)]
181+
pub(crate) struct ConditionallyConstCall {
182+
#[primary_span]
183+
pub span: Span,
184+
pub def_path_str: String,
185+
pub def_descr: &'static str,
186+
pub kind: ConstContext,
187+
}
188+
179189
#[derive(Diagnostic)]
180190
#[diag(const_eval_non_const_fn_call, code = E0015)]
181191
pub(crate) struct NonConstFnCall {

0 commit comments

Comments
 (0)