Skip to content

Commit 27e38f8

Browse files
committed
Auto merge of rust-lang#132626 - workingjubilee:rollup-hbmtbzk, r=workingjubilee
Rollup of 11 pull requests Successful merges: - rust-lang#131153 (Improve duplicate derive Copy/Clone diagnostics) - rust-lang#132025 (fix suggestion for diagnostic error E0027) - rust-lang#132303 (More tests for non-exhaustive C-like enums in FFI) - rust-lang#132492 (remove support for extern-block const intrinsics) - rust-lang#132587 (Revert "Avoid nested replacement ranges" from rust-lang#129346.) - rust-lang#132596 ([rustdoc] Fix `--show-coverage` when JSON output format is used) - rust-lang#132598 (Clippy: Move some attribute lints to be early pass (post expansion)) - rust-lang#132601 (Update books) - rust-lang#132606 (Improve example of `impl Pattern for &[char]`) - rust-lang#132608 (document `type_implements_trait`) - rust-lang#132609 (docs: fix grammar in doc comment at unix/process.rs) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 96477c5 + 7bff6ff commit 27e38f8

File tree

82 files changed

+1705
-1401
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1705
-1401
lines changed

compiler/rustc_attr/src/builtin.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,7 @@ pub fn find_stability(
273273
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
274274
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
275275
///
276-
/// `is_const_fn` indicates whether this is a function marked as `const`. It will always
277-
/// be false for intrinsics in an `extern` block!
276+
/// `is_const_fn` indicates whether this is a function marked as `const`.
278277
pub fn find_const_stability(
279278
sess: &Session,
280279
attrs: &[Attribute],
@@ -330,7 +329,7 @@ pub fn find_const_stability(
330329
}
331330
}
332331

333-
// Merge promotable and not_exposed_on_stable into stability info
332+
// Merge promotable and const_stable_indirect into stability info
334333
if promotable {
335334
match &mut const_stab {
336335
Some((stab, _)) => stab.promotable = promotable,
@@ -352,10 +351,7 @@ pub fn find_const_stability(
352351
})
353352
}
354353
}
355-
_ => {
356-
// We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
357-
// the `default_const_unstable` logic.
358-
}
354+
_ => {}
359355
}
360356
}
361357
// Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

+17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_middle::ty::{self, Ty};
1010
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
1111
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
1212
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
13+
use rustc_trait_selection::infer::InferCtxtExt;
1314
use tracing::debug;
1415

1516
use crate::MirBorrowckCtxt;
@@ -267,6 +268,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
267268
kind,
268269
self.is_upvar_field_projection(original_path.as_ref())
269270
);
271+
if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) {
272+
// If the type may implement Copy, skip the error.
273+
// It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
274+
self.dcx().span_delayed_bug(
275+
span,
276+
"Type may implement copy, but there is no other error.",
277+
);
278+
return;
279+
}
270280
(
271281
match kind {
272282
&IllegalMoveOriginKind::BorrowedContent { target_place } => self
@@ -291,6 +301,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
291301
self.buffer_error(err);
292302
}
293303

304+
fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool {
305+
let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
306+
// This is only going to be ambiguous if there are incoherent impls, because otherwise
307+
// ambiguity should never happen in MIR.
308+
self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
309+
}
310+
294311
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
295312
let description = if place.projection.len() == 1 {
296313
format!("static item {}", self.describe_any_place(place.as_ref()))

compiler/rustc_const_eval/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ const_eval_uninhabited_enum_variant_written =
399399
const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
400400
.help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
401401
const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
402-
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
402+
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
403403
404404
const_eval_unreachable = entering unreachable code
405405
const_eval_unreachable_unwind =

compiler/rustc_const_eval/src/check_consts/check.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -736,16 +736,25 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
736736

737737
// Intrinsics are language primitives, not regular calls, so treat them separately.
738738
if let Some(intrinsic) = tcx.intrinsic(callee) {
739+
// We use `intrinsic.const_stable` to determine if this can be safely exposed to
740+
// stable code, rather than `const_stable_indirect`. This is to make
741+
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
742+
// We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
743+
// fallback body is safe to expose on stable.
744+
let is_const_stable = intrinsic.const_stable
745+
|| (!intrinsic.must_be_overridden
746+
&& tcx.is_const_fn(callee)
747+
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
739748
match tcx.lookup_const_stability(callee) {
740749
None => {
741750
// Non-const intrinsic.
742751
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
743752
}
744-
Some(ConstStability { feature: None, const_stable_indirect, .. }) => {
753+
Some(ConstStability { feature: None, .. }) => {
745754
// Intrinsic does not need a separate feature gate (we rely on the
746755
// regular stability checker). However, we have to worry about recursive
747756
// const stability.
748-
if !const_stable_indirect && self.enforce_recursive_const_stability() {
757+
if !is_const_stable && self.enforce_recursive_const_stability() {
749758
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
750759
span: self.span,
751760
def_path: self.tcx.def_path_str(callee),
@@ -755,17 +764,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
755764
Some(ConstStability {
756765
feature: Some(feature),
757766
level: StabilityLevel::Unstable { .. },
758-
const_stable_indirect,
759767
..
760768
}) => {
761769
self.check_op(ops::IntrinsicUnstable {
762770
name: intrinsic.name,
763771
feature,
764-
const_stable_indirect,
772+
const_stable: is_const_stable,
765773
});
766774
}
767775
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
768-
// All good.
776+
// All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
777+
// can be *directly* invoked from stable const code) does not always
778+
// have the `#[rustc_const_stable_intrinsic]` attribute (which controls
779+
// exposing an intrinsic indirectly); we accept this call anyway.
769780
}
770781
}
771782
// This completes the checks for intrinsics.

compiler/rustc_const_eval/src/check_consts/ops.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -354,14 +354,14 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst {
354354
pub(crate) struct IntrinsicUnstable {
355355
pub name: Symbol,
356356
pub feature: Symbol,
357-
pub const_stable_indirect: bool,
357+
pub const_stable: bool,
358358
}
359359

360360
impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
361361
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
362362
Status::Unstable {
363363
gate: self.feature,
364-
safe_to_expose_on_stable: self.const_stable_indirect,
364+
safe_to_expose_on_stable: self.const_stable,
365365
// We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`,
366366
// that's not a trivial change!
367367
is_function_call: false,

compiler/rustc_const_eval/src/const_eval/fn_queries.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,9 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
2525
hir::Constness::Const
2626
}
2727
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
28-
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
29-
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
30-
// foreign items cannot be evaluated at compile-time.
31-
let is_const = if tcx.intrinsic(def_id).is_some() {
32-
tcx.lookup_const_stability(def_id).is_some()
33-
} else {
34-
false
35-
};
36-
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
28+
hir::Node::ForeignItem(_) => {
29+
// Foreign items cannot be evaluated at compile-time.
30+
hir::Constness::NotConst
3731
}
3832
hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
3933
_ => {

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
837837
rustc_const_stable_indirect, Normal,
838838
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
839839
),
840+
rustc_attr!(
841+
rustc_const_stable_intrinsic, Normal,
842+
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
843+
),
840844
gated!(
841845
rustc_allow_const_fn_unstable, Normal,
842846
template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,

compiler/rustc_hir_typeck/src/pat.rs

+19
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20712071
s = pluralize!(len),
20722072
them = if len == 1 { "it" } else { "them" },
20732073
),
2074+
format!(
2075+
"{}{}{}{}",
2076+
prefix,
2077+
unmentioned_fields
2078+
.iter()
2079+
.map(|(_, name)| {
2080+
let field_name = name.to_string();
2081+
format!("{field_name}: _")
2082+
})
2083+
.collect::<Vec<_>>()
2084+
.join(", "),
2085+
if have_inaccessible_fields { ", .." } else { "" },
2086+
postfix,
2087+
),
2088+
Applicability::MachineApplicable,
2089+
);
2090+
err.span_suggestion(
2091+
sp,
2092+
"or always ignore missing fields here",
20742093
format!("{prefix}..{postfix}"),
20752094
Applicability::MachineApplicable,
20762095
);

compiler/rustc_middle/src/ty/intrinsic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub struct IntrinsicDef {
99
pub name: Symbol,
1010
/// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
1111
pub must_be_overridden: bool,
12+
/// Whether the intrinsic can be invoked from stable const fn
13+
pub const_stable: bool,
1214
}
1315

1416
impl TyCtxt<'_> {

compiler/rustc_middle/src/ty/util.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
17891789
Some(ty::IntrinsicDef {
17901790
name: tcx.item_name(def_id.into()),
17911791
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
1792+
const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
17921793
})
17931794
} else {
17941795
None

compiler/rustc_parse/src/parser/attr_wrapper.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,30 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
136136
node_replacements.array_windows()
137137
{
138138
assert!(
139-
node_range.0.end <= next_node_range.0.start,
140-
"Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})",
139+
node_range.0.end <= next_node_range.0.start
140+
|| node_range.0.end >= next_node_range.0.end,
141+
"Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
141142
node_range,
142143
tokens,
143144
next_node_range,
144145
next_tokens,
145146
);
146147
}
147148

148-
// Process the replace ranges.
149-
for (node_range, target) in node_replacements.into_iter() {
149+
// Process the replace ranges, starting from the highest start
150+
// position and working our way back. If have tokens like:
151+
//
152+
// `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
153+
//
154+
// Then we will generate replace ranges for both
155+
// the `#[cfg(FALSE)] field: bool` and the entire
156+
// `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
157+
//
158+
// By starting processing from the replace range with the greatest
159+
// start position, we ensure that any (outer) replace range which
160+
// encloses another (inner) replace range will fully overwrite the
161+
// inner range's replacement.
162+
for (node_range, target) in node_replacements.into_iter().rev() {
150163
assert!(
151164
!node_range.0.is_empty(),
152165
"Cannot replace an empty node range: {:?}",
@@ -383,9 +396,10 @@ impl<'a> Parser<'a> {
383396
// from `ParserRange` form to `NodeRange` form. We will perform the actual
384397
// replacement only when we convert the `LazyAttrTokenStream` to an
385398
// `AttrTokenStream`.
386-
self.capture_state
387-
.parser_replacements
388-
.drain(parser_replacements_start..parser_replacements_end)
399+
self.capture_state.parser_replacements
400+
[parser_replacements_start..parser_replacements_end]
401+
.iter()
402+
.cloned()
389403
.chain(inner_attr_parser_replacements)
390404
.map(|(parser_range, data)| {
391405
(NodeRange::new(parser_range, collect_pos.start_pos), data)

compiler/rustc_passes/src/stability.rs

-15
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
106106
def_id: LocalDefId,
107107
item_sp: Span,
108108
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
109-
is_foreign_item: bool,
110109
kind: AnnotationKind,
111110
inherit_deprecation: InheritDeprecation,
112111
inherit_const_stability: InheritConstStability,
@@ -175,11 +174,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
175174
// implied), check if the function/method is const or the parent impl block is const.
176175
if let Some(fn_sig) = fn_sig
177176
&& !fn_sig.header.is_const()
178-
// We have to exclude foreign items as they might be intrinsics. Sadly we can't check
179-
// their ABI; `fn_sig.abi` is *not* correct for foreign functions.
180-
&& !is_foreign_item
181177
&& const_stab.is_some()
182-
&& (!self.in_trait_impl || !self.tcx.is_const_fn(def_id.to_def_id()))
183178
{
184179
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
185180
}
@@ -398,7 +393,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
398393
ctor_def_id,
399394
i.span,
400395
None,
401-
/* is_foreign_item */ false,
402396
AnnotationKind::Required,
403397
InheritDeprecation::Yes,
404398
InheritConstStability::No,
@@ -417,7 +411,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
417411
i.owner_id.def_id,
418412
i.span,
419413
fn_sig,
420-
/* is_foreign_item */ false,
421414
kind,
422415
InheritDeprecation::Yes,
423416
const_stab_inherit,
@@ -437,7 +430,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
437430
ti.owner_id.def_id,
438431
ti.span,
439432
fn_sig,
440-
/* is_foreign_item */ false,
441433
AnnotationKind::Required,
442434
InheritDeprecation::Yes,
443435
InheritConstStability::No,
@@ -461,7 +453,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
461453
ii.owner_id.def_id,
462454
ii.span,
463455
fn_sig,
464-
/* is_foreign_item */ false,
465456
kind,
466457
InheritDeprecation::Yes,
467458
InheritConstStability::No,
@@ -477,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
477468
var.def_id,
478469
var.span,
479470
None,
480-
/* is_foreign_item */ false,
481471
AnnotationKind::Required,
482472
InheritDeprecation::Yes,
483473
InheritConstStability::No,
@@ -488,7 +478,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
488478
ctor_def_id,
489479
var.span,
490480
None,
491-
/* is_foreign_item */ false,
492481
AnnotationKind::Required,
493482
InheritDeprecation::Yes,
494483
InheritConstStability::No,
@@ -507,7 +496,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
507496
s.def_id,
508497
s.span,
509498
None,
510-
/* is_foreign_item */ false,
511499
AnnotationKind::Required,
512500
InheritDeprecation::Yes,
513501
InheritConstStability::No,
@@ -527,7 +515,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
527515
i.owner_id.def_id,
528516
i.span,
529517
fn_sig,
530-
/* is_foreign_item */ true,
531518
AnnotationKind::Required,
532519
InheritDeprecation::Yes,
533520
InheritConstStability::No,
@@ -550,7 +537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
550537
p.def_id,
551538
p.span,
552539
None,
553-
/* is_foreign_item */ false,
554540
kind,
555541
InheritDeprecation::No,
556542
InheritConstStability::No,
@@ -712,7 +698,6 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
712698
CRATE_DEF_ID,
713699
tcx.hir().span(CRATE_HIR_ID),
714700
None,
715-
/* is_foreign_item */ false,
716701
AnnotationKind::Required,
717702
InheritDeprecation::Yes,
718703
InheritConstStability::No,

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,7 @@ symbols! {
16631663
rustc_const_panic_str,
16641664
rustc_const_stable,
16651665
rustc_const_stable_indirect,
1666+
rustc_const_stable_intrinsic,
16661667
rustc_const_unstable,
16671668
rustc_conversion_suggestion,
16681669
rustc_deallocator,

0 commit comments

Comments
 (0)