mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #132626 - workingjubilee:rollup-hbmtbzk, r=workingjubilee
Rollup of 11 pull requests Successful merges: - #131153 (Improve duplicate derive Copy/Clone diagnostics) - #132025 (fix suggestion for diagnostic error E0027) - #132303 (More tests for non-exhaustive C-like enums in FFI) - #132492 (remove support for extern-block const intrinsics) - #132587 (Revert "Avoid nested replacement ranges" from #129346.) - #132596 ([rustdoc] Fix `--show-coverage` when JSON output format is used) - #132598 (Clippy: Move some attribute lints to be early pass (post expansion)) - #132601 (Update books) - #132606 (Improve example of `impl Pattern for &[char]`) - #132608 (document `type_implements_trait`) - #132609 (docs: fix grammar in doc comment at unix/process.rs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
27e38f8fc7
@ -273,8 +273,7 @@ pub fn find_stability(
|
||||
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
///
|
||||
/// `is_const_fn` indicates whether this is a function marked as `const`. It will always
|
||||
/// be false for intrinsics in an `extern` block!
|
||||
/// `is_const_fn` indicates whether this is a function marked as `const`.
|
||||
pub fn find_const_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
@ -330,7 +329,7 @@ pub fn find_const_stability(
|
||||
}
|
||||
}
|
||||
|
||||
// Merge promotable and not_exposed_on_stable into stability info
|
||||
// Merge promotable and const_stable_indirect into stability info
|
||||
if promotable {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
@ -352,10 +351,7 @@ pub fn find_const_stability(
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
|
||||
// the `default_const_unstable` logic.
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const
|
||||
|
@ -10,6 +10,7 @@ use rustc_middle::ty::{self, Ty};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::MirBorrowckCtxt;
|
||||
@ -267,6 +268,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
kind,
|
||||
self.is_upvar_field_projection(original_path.as_ref())
|
||||
);
|
||||
if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) {
|
||||
// If the type may implement Copy, skip the error.
|
||||
// It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
|
||||
self.dcx().span_delayed_bug(
|
||||
span,
|
||||
"Type may implement copy, but there is no other error.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
(
|
||||
match kind {
|
||||
&IllegalMoveOriginKind::BorrowedContent { target_place } => self
|
||||
@ -291,6 +301,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
|
||||
// This is only going to be ambiguous if there are incoherent impls, because otherwise
|
||||
// ambiguity should never happen in MIR.
|
||||
self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
|
||||
let description = if place.projection.len() == 1 {
|
||||
format!("static item {}", self.describe_any_place(place.as_ref()))
|
||||
|
@ -399,7 +399,7 @@ const_eval_uninhabited_enum_variant_written =
|
||||
const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
|
||||
.help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
|
||||
const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
|
||||
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
|
||||
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
|
||||
const_eval_unreachable = entering unreachable code
|
||||
const_eval_unreachable_unwind =
|
||||
|
@ -736,16 +736,25 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
|
||||
// Intrinsics are language primitives, not regular calls, so treat them separately.
|
||||
if let Some(intrinsic) = tcx.intrinsic(callee) {
|
||||
// We use `intrinsic.const_stable` to determine if this can be safely exposed to
|
||||
// stable code, rather than `const_stable_indirect`. This is to make
|
||||
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
|
||||
// We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
|
||||
// fallback body is safe to expose on stable.
|
||||
let is_const_stable = intrinsic.const_stable
|
||||
|| (!intrinsic.must_be_overridden
|
||||
&& tcx.is_const_fn(callee)
|
||||
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
|
||||
match tcx.lookup_const_stability(callee) {
|
||||
None => {
|
||||
// Non-const intrinsic.
|
||||
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
||||
}
|
||||
Some(ConstStability { feature: None, const_stable_indirect, .. }) => {
|
||||
Some(ConstStability { feature: None, .. }) => {
|
||||
// Intrinsic does not need a separate feature gate (we rely on the
|
||||
// regular stability checker). However, we have to worry about recursive
|
||||
// const stability.
|
||||
if !const_stable_indirect && self.enforce_recursive_const_stability() {
|
||||
if !is_const_stable && self.enforce_recursive_const_stability() {
|
||||
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
|
||||
span: self.span,
|
||||
def_path: self.tcx.def_path_str(callee),
|
||||
@ -755,17 +764,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
Some(ConstStability {
|
||||
feature: Some(feature),
|
||||
level: StabilityLevel::Unstable { .. },
|
||||
const_stable_indirect,
|
||||
..
|
||||
}) => {
|
||||
self.check_op(ops::IntrinsicUnstable {
|
||||
name: intrinsic.name,
|
||||
feature,
|
||||
const_stable_indirect,
|
||||
const_stable: is_const_stable,
|
||||
});
|
||||
}
|
||||
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||
// All good.
|
||||
// All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
|
||||
// can be *directly* invoked from stable const code) does not always
|
||||
// have the `#[rustc_const_stable_intrinsic]` attribute (which controls
|
||||
// exposing an intrinsic indirectly); we accept this call anyway.
|
||||
}
|
||||
}
|
||||
// This completes the checks for intrinsics.
|
||||
|
@ -354,14 +354,14 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst {
|
||||
pub(crate) struct IntrinsicUnstable {
|
||||
pub name: Symbol,
|
||||
pub feature: Symbol,
|
||||
pub const_stable_indirect: bool,
|
||||
pub const_stable: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
|
||||
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
|
||||
Status::Unstable {
|
||||
gate: self.feature,
|
||||
safe_to_expose_on_stable: self.const_stable_indirect,
|
||||
safe_to_expose_on_stable: self.const_stable,
|
||||
// We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`,
|
||||
// that's not a trivial change!
|
||||
is_function_call: false,
|
||||
|
@ -25,15 +25,9 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
||||
hir::Constness::Const
|
||||
}
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
|
||||
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
|
||||
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
|
||||
// foreign items cannot be evaluated at compile-time.
|
||||
let is_const = if tcx.intrinsic(def_id).is_some() {
|
||||
tcx.lookup_const_stability(def_id).is_some()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
|
||||
hir::Node::ForeignItem(_) => {
|
||||
// Foreign items cannot be evaluated at compile-time.
|
||||
hir::Constness::NotConst
|
||||
}
|
||||
hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
|
||||
_ => {
|
||||
|
@ -837,6 +837,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
rustc_const_stable_indirect, Normal,
|
||||
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_const_stable_intrinsic, Normal,
|
||||
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
|
||||
),
|
||||
gated!(
|
||||
rustc_allow_const_fn_unstable, Normal,
|
||||
template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
|
||||
|
@ -2071,6 +2071,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
s = pluralize!(len),
|
||||
them = if len == 1 { "it" } else { "them" },
|
||||
),
|
||||
format!(
|
||||
"{}{}{}{}",
|
||||
prefix,
|
||||
unmentioned_fields
|
||||
.iter()
|
||||
.map(|(_, name)| {
|
||||
let field_name = name.to_string();
|
||||
format!("{field_name}: _")
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
if have_inaccessible_fields { ", .." } else { "" },
|
||||
postfix,
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.span_suggestion(
|
||||
sp,
|
||||
"or always ignore missing fields here",
|
||||
format!("{prefix}..{postfix}"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
@ -9,6 +9,8 @@ pub struct IntrinsicDef {
|
||||
pub name: Symbol,
|
||||
/// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
|
||||
pub must_be_overridden: bool,
|
||||
/// Whether the intrinsic can be invoked from stable const fn
|
||||
pub const_stable: bool,
|
||||
}
|
||||
|
||||
impl TyCtxt<'_> {
|
||||
|
@ -1789,6 +1789,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
|
||||
Some(ty::IntrinsicDef {
|
||||
name: tcx.item_name(def_id.into()),
|
||||
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
|
||||
const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
@ -136,8 +136,9 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
|
||||
node_replacements.array_windows()
|
||||
{
|
||||
assert!(
|
||||
node_range.0.end <= next_node_range.0.start,
|
||||
"Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})",
|
||||
node_range.0.end <= next_node_range.0.start
|
||||
|| node_range.0.end >= next_node_range.0.end,
|
||||
"Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
|
||||
node_range,
|
||||
tokens,
|
||||
next_node_range,
|
||||
@ -145,8 +146,20 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
|
||||
);
|
||||
}
|
||||
|
||||
// Process the replace ranges.
|
||||
for (node_range, target) in node_replacements.into_iter() {
|
||||
// Process the replace ranges, starting from the highest start
|
||||
// position and working our way back. If have tokens like:
|
||||
//
|
||||
// `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
|
||||
//
|
||||
// Then we will generate replace ranges for both
|
||||
// the `#[cfg(FALSE)] field: bool` and the entire
|
||||
// `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
|
||||
//
|
||||
// By starting processing from the replace range with the greatest
|
||||
// start position, we ensure that any (outer) replace range which
|
||||
// encloses another (inner) replace range will fully overwrite the
|
||||
// inner range's replacement.
|
||||
for (node_range, target) in node_replacements.into_iter().rev() {
|
||||
assert!(
|
||||
!node_range.0.is_empty(),
|
||||
"Cannot replace an empty node range: {:?}",
|
||||
@ -383,9 +396,10 @@ impl<'a> Parser<'a> {
|
||||
// from `ParserRange` form to `NodeRange` form. We will perform the actual
|
||||
// replacement only when we convert the `LazyAttrTokenStream` to an
|
||||
// `AttrTokenStream`.
|
||||
self.capture_state
|
||||
.parser_replacements
|
||||
.drain(parser_replacements_start..parser_replacements_end)
|
||||
self.capture_state.parser_replacements
|
||||
[parser_replacements_start..parser_replacements_end]
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(inner_attr_parser_replacements)
|
||||
.map(|(parser_range, data)| {
|
||||
(NodeRange::new(parser_range, collect_pos.start_pos), data)
|
||||
|
@ -106,7 +106,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
def_id: LocalDefId,
|
||||
item_sp: Span,
|
||||
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
|
||||
is_foreign_item: bool,
|
||||
kind: AnnotationKind,
|
||||
inherit_deprecation: InheritDeprecation,
|
||||
inherit_const_stability: InheritConstStability,
|
||||
@ -175,11 +174,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
// implied), check if the function/method is const or the parent impl block is const.
|
||||
if let Some(fn_sig) = fn_sig
|
||||
&& !fn_sig.header.is_const()
|
||||
// We have to exclude foreign items as they might be intrinsics. Sadly we can't check
|
||||
// their ABI; `fn_sig.abi` is *not* correct for foreign functions.
|
||||
&& !is_foreign_item
|
||||
&& const_stab.is_some()
|
||||
&& (!self.in_trait_impl || !self.tcx.is_const_fn(def_id.to_def_id()))
|
||||
{
|
||||
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
|
||||
}
|
||||
@ -398,7 +393,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
ctor_def_id,
|
||||
i.span,
|
||||
None,
|
||||
/* is_foreign_item */ false,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -417,7 +411,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
i.owner_id.def_id,
|
||||
i.span,
|
||||
fn_sig,
|
||||
/* is_foreign_item */ false,
|
||||
kind,
|
||||
InheritDeprecation::Yes,
|
||||
const_stab_inherit,
|
||||
@ -437,7 +430,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
ti.owner_id.def_id,
|
||||
ti.span,
|
||||
fn_sig,
|
||||
/* is_foreign_item */ false,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -461,7 +453,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
ii.owner_id.def_id,
|
||||
ii.span,
|
||||
fn_sig,
|
||||
/* is_foreign_item */ false,
|
||||
kind,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -477,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
var.def_id,
|
||||
var.span,
|
||||
None,
|
||||
/* is_foreign_item */ false,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -488,7 +478,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
ctor_def_id,
|
||||
var.span,
|
||||
None,
|
||||
/* is_foreign_item */ false,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -507,7 +496,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
s.def_id,
|
||||
s.span,
|
||||
None,
|
||||
/* is_foreign_item */ false,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -527,7 +515,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
i.owner_id.def_id,
|
||||
i.span,
|
||||
fn_sig,
|
||||
/* is_foreign_item */ true,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
@ -550,7 +537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||
p.def_id,
|
||||
p.span,
|
||||
None,
|
||||
/* is_foreign_item */ false,
|
||||
kind,
|
||||
InheritDeprecation::No,
|
||||
InheritConstStability::No,
|
||||
@ -712,7 +698,6 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
||||
CRATE_DEF_ID,
|
||||
tcx.hir().span(CRATE_HIR_ID),
|
||||
None,
|
||||
/* is_foreign_item */ false,
|
||||
AnnotationKind::Required,
|
||||
InheritDeprecation::Yes,
|
||||
InheritConstStability::No,
|
||||
|
@ -1663,6 +1663,7 @@ symbols! {
|
||||
rustc_const_panic_str,
|
||||
rustc_const_stable,
|
||||
rustc_const_stable_indirect,
|
||||
rustc_const_stable_intrinsic,
|
||||
rustc_const_unstable,
|
||||
rustc_conversion_suggestion,
|
||||
rustc_deallocator,
|
||||
|
@ -60,6 +60,24 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
///
|
||||
/// Invokes `evaluate_obligation`, so in the event that evaluating
|
||||
/// `Ty: Trait` causes overflow, EvaluatedToAmbigStackDependent will be returned.
|
||||
///
|
||||
/// `type_implements_trait` is a convenience function for simple cases like
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// let copy_trait = infcx.tcx.require_lang_item(LangItem::Copy, span);
|
||||
/// let implements_copy = infcx.type_implements_trait(copy_trait, [ty], param_env)
|
||||
/// .must_apply_modulo_regions();
|
||||
/// ```
|
||||
///
|
||||
/// In most cases you should instead create an [Obligation] and check whether
|
||||
/// it holds via [`evaluate_obligation`] or one of its helper functions like
|
||||
/// [`predicate_must_hold_modulo_regions`], because it properly handles higher ranked traits
|
||||
/// and it is more convenient and safer when your `params` are inside a [`Binder`].
|
||||
///
|
||||
/// [Obligation]: traits::Obligation
|
||||
/// [`evaluate_obligation`]: crate::traits::query::evaluate_obligation::InferCtxtExt::evaluate_obligation
|
||||
/// [`predicate_must_hold_modulo_regions`]: crate::traits::query::evaluate_obligation::InferCtxtExt::predicate_must_hold_modulo_regions
|
||||
/// [`Binder`]: ty::Binder
|
||||
#[instrument(level = "debug", skip(self, params), ret)]
|
||||
fn type_implements_trait(
|
||||
&self,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -107,6 +107,7 @@
|
||||
//
|
||||
// Library features:
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(const_exact_div))]
|
||||
#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))]
|
||||
#![feature(array_ptr_get)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
@ -116,7 +117,6 @@
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_char_encode_utf16)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_exact_div)]
|
||||
#![feature(const_float_methods)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(const_nonnull_new)]
|
||||
|
@ -886,8 +886,8 @@ impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!("Hello world".find(&['l', 'l'] as &[_]), Some(2));
|
||||
/// assert_eq!("Hello world".find(&['l', 'l'][..]), Some(2));
|
||||
/// assert_eq!("Hello world".find(&['o', 'l'][..]), Some(2));
|
||||
/// assert_eq!("Hello world".find(&['h', 'w'][..]), Some(6));
|
||||
/// ```
|
||||
impl<'b> Pattern for &'b [char] {
|
||||
pattern_methods!('a, CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(const_three_way_compare))]
|
||||
#![cfg_attr(bootstrap, feature(strict_provenance))]
|
||||
#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
|
||||
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
@ -22,7 +23,6 @@
|
||||
#![feature(const_nonnull_new)]
|
||||
#![feature(const_option_ext)]
|
||||
#![feature(const_pin_2)]
|
||||
#![feature(const_three_way_compare)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_io_borrowed_buf)]
|
||||
|
@ -143,7 +143,7 @@ pub trait CommandExt: Sealed {
|
||||
///
|
||||
/// This function, unlike `spawn`, will **not** `fork` the process to create
|
||||
/// a new child. Like spawn, however, the default behavior for the stdio
|
||||
/// descriptors will be to inherited from the current process.
|
||||
/// descriptors will be to inherit them from the current process.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 1f07c242f8162a711a5ac5a4ea8fa7ec884ee7a9
|
||||
Subproject commit 2d482e203eb6d6e353814cf1415c5f94e590b9e0
|
@ -1 +1 @@
|
||||
Subproject commit 23ce619966541bf2c80d45fdfeecf3393e360a13
|
||||
Subproject commit da0f6dad767670da0e8cd5af8a7090db3272f626
|
@ -1 +1 @@
|
||||
Subproject commit 8bede1b919a81ab7d0c961f6bbf68d3efa297bd2
|
||||
Subproject commit 9db78608b17d5f4a6c033b8a3038466b87d63206
|
@ -1 +1 @@
|
||||
Subproject commit 59d94ea75a0b157e148af14c73c2dd60efb7b60a
|
||||
Subproject commit 6a5accdaf10255882b1e6c59dfe5f1c79ac95484
|
@ -2907,7 +2907,7 @@ fn clean_extern_crate<'tcx>(
|
||||
None => false,
|
||||
}
|
||||
})
|
||||
&& !cx.output_format.is_json();
|
||||
&& !cx.is_json_output();
|
||||
|
||||
let krate_owner_def_id = krate.owner_id.def_id;
|
||||
if please_inline {
|
||||
@ -3000,7 +3000,7 @@ fn clean_use_statement_inner<'tcx>(
|
||||
// forcefully don't inline if this is not public or if the
|
||||
// #[doc(no_inline)] attribute is present.
|
||||
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
|
||||
let mut denied = cx.output_format.is_json()
|
||||
let mut denied = cx.is_json_output()
|
||||
|| !(visibility.is_public()
|
||||
|| (cx.render_options.document_private && is_visible_from_parent_mod))
|
||||
|| pub_underscore
|
||||
|
@ -121,6 +121,13 @@ impl<'tcx> DocContext<'tcx> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the JSON output format is enabled for generating the crate content.
|
||||
///
|
||||
/// If another option like `--show-coverage` is enabled, it will return `false`.
|
||||
pub(crate) fn is_json_output(&self) -> bool {
|
||||
self.output_format.is_json() && !self.show_coverage
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `DiagCtxt` that can be used to emit warnings and errors.
|
||||
|
@ -132,6 +132,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> {
|
||||
|
||||
fn print_results(&self) {
|
||||
let output_format = self.ctx.output_format;
|
||||
// In this case we want to ensure that the `OutputFormat` is JSON and NOT the `DocContext`.
|
||||
if output_format.is_json() {
|
||||
println!("{}", self.to_json());
|
||||
return;
|
||||
|
@ -23,7 +23,7 @@ pub(crate) const STRIP_HIDDEN: Pass = Pass {
|
||||
/// Strip items marked `#[doc(hidden)]`
|
||||
pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
|
||||
let mut retained = ItemIdSet::default();
|
||||
let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
|
||||
let is_json_output = cx.is_json_output();
|
||||
|
||||
// strip all #[doc(hidden)] items
|
||||
let krate = {
|
||||
|
@ -13,7 +13,7 @@ pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass {
|
||||
};
|
||||
|
||||
pub(crate) fn strip_priv_imports(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
|
||||
let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
|
||||
let is_json_output = cx.is_json_output();
|
||||
ImportStripper {
|
||||
tcx: cx.tcx,
|
||||
is_json_output,
|
||||
|
@ -18,7 +18,7 @@ pub(crate) const STRIP_PRIVATE: Pass = Pass {
|
||||
pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
|
||||
// This stripper collects all *retained* nodes.
|
||||
let mut retained = ItemIdSet::default();
|
||||
let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
|
||||
let is_json_output = cx.is_json_output();
|
||||
|
||||
// strip all private items
|
||||
{
|
||||
|
@ -235,7 +235,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.cx.output_format.is_json() {
|
||||
if self.cx.is_json_output() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,11 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use rustc_ast::{AttrStyle, Attribute};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
||||
// Separate each crate's features.
|
||||
pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
|
||||
pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) {
|
||||
if !in_external_macro(cx.sess(), attr.span)
|
||||
&& let AttrStyle::Outer = attr.style
|
||||
&& let Some(ident) = attr.ident()
|
||||
|
@ -2,12 +2,12 @@ use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use rustc_ast::{MetaItemInner, MetaItemKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
|
||||
pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
|
||||
// Check if the reason is present
|
||||
if let Some(item) = items.last().and_then(MetaItemInner::meta_item)
|
||||
&& let MetaItemKind::NameValue(_) = &item.kind
|
||||
|
@ -2,11 +2,11 @@ use super::BLANKET_CLIPPY_RESTRICTION_LINTS;
|
||||
use super::utils::extract_clippy_lint;
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_lint::{LateContext, Level, LintContext};
|
||||
use rustc_lint::{EarlyContext, Level, LintContext};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{DUMMY_SP, sym};
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
for lint in items {
|
||||
if let Some(lint_name) = extract_clippy_lint(lint) {
|
||||
if lint_name.as_str() == "restriction" && name != sym::allow {
|
||||
@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner])
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_command_line(cx: &LateContext<'_>) {
|
||||
pub(super) fn check_command_line(cx: &EarlyContext<'_>) {
|
||||
for (name, level) in &cx.sess().opts.lint_opts {
|
||||
if name == "clippy::restriction" && *level > Level::Allow {
|
||||
span_lint_and_then(
|
||||
|
@ -1,11 +1,11 @@
|
||||
use super::DEPRECATED_SEMVER;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::{LitKind, MetaItemLit};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
use semver::Version;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
if let LitKind::Str(is, _) = lit.kind {
|
||||
if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
|
||||
return;
|
||||
|
@ -2,12 +2,12 @@ use super::DUPLICATED_ATTRIBUTES;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::{Attribute, MetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::{Span, sym};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
fn emit_if_duplicated(
|
||||
cx: &LateContext<'_>,
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
complete_path: String,
|
||||
@ -26,7 +26,7 @@ fn emit_if_duplicated(
|
||||
}
|
||||
|
||||
fn check_duplicated_attr(
|
||||
cx: &LateContext<'_>,
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
parent: &mut Vec<String>,
|
||||
@ -65,7 +65,7 @@ fn check_duplicated_attr(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attr_paths = FxHashMap::default();
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{SourceFile, Span, Symbol};
|
||||
|
||||
@ -32,7 +32,7 @@ impl From<&AttrKind> for SimpleAttrKind {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
|
||||
@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute])
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
fn lint_mixed_attrs(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
|
||||
let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
|
||||
first.span.with_hi(last.span.hi())
|
||||
|
@ -14,8 +14,8 @@ mod utils;
|
||||
|
||||
use clippy_config::Conf;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind};
|
||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind, self as ast};
|
||||
use rustc_hir::{ImplItem, Item, TraitItem};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
@ -414,15 +414,7 @@ pub struct Attributes {
|
||||
}
|
||||
|
||||
impl_lint_pass!(Attributes => [
|
||||
ALLOW_ATTRIBUTES,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
INLINE_ALWAYS,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl Attributes {
|
||||
@ -434,53 +426,11 @@ impl Attributes {
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||
duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
if let Some(ident) = attr.ident() {
|
||||
if is_lint_level(ident.name, attr.id) {
|
||||
blanket_clippy_restriction_lints::check(cx, ident.name, items);
|
||||
}
|
||||
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes::check(cx, attr);
|
||||
}
|
||||
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
|
||||
{
|
||||
allow_attributes_without_reason::check(cx, ident.name, items, attr);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if let MetaItemInner::MetaItem(mi) = &item
|
||||
&& let MetaItemKind::NameValue(lit) = &mi.kind
|
||||
&& mi.has_name(sym::since)
|
||||
{
|
||||
deprecated_semver::check(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if attr.has_name(sym::should_panic) {
|
||||
should_panic_without_expect::check(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if is_relevant_item(cx, item) {
|
||||
inline_always::check(cx, item.span, item.ident.name, attrs);
|
||||
}
|
||||
match item.kind {
|
||||
ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
|
||||
_ => {},
|
||||
}
|
||||
mixed_attributes_style::check(cx, item.span, attrs);
|
||||
duplicated_attributes::check(cx, attrs);
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
@ -526,3 +476,77 @@ impl EarlyLintPass for EarlyAttributes {
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
||||
pub struct PostExpansionEarlyAttributes {
|
||||
msrv: Msrv,
|
||||
}
|
||||
|
||||
impl PostExpansionEarlyAttributes {
|
||||
pub fn new(conf: &'static Conf) -> Self {
|
||||
Self {
|
||||
msrv: conf.msrv.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(PostExpansionEarlyAttributes => [
|
||||
ALLOW_ATTRIBUTES,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl EarlyLintPass for PostExpansionEarlyAttributes {
|
||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
|
||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||
duplicated_attributes::check(cx, &krate.attrs);
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
if let Some(ident) = attr.ident() {
|
||||
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes::check(cx, attr);
|
||||
}
|
||||
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
|
||||
{
|
||||
allow_attributes_without_reason::check(cx, ident.name, items, attr);
|
||||
}
|
||||
if is_lint_level(ident.name, attr.id) {
|
||||
blanket_clippy_restriction_lints::check(cx, ident.name, items);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if let MetaItemInner::MetaItem(mi) = &item
|
||||
&& let MetaItemKind::NameValue(lit) = &mi.kind
|
||||
&& mi.has_name(sym::since)
|
||||
{
|
||||
deprecated_semver::check(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if attr.has_name(sym::should_panic) {
|
||||
should_panic_without_expect::check(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) {
|
||||
match item.kind {
|
||||
ast::ItemKind::ExternCrate(..) | ast::ItemKind::Use(..) => useless_attribute::check(cx, item, &item.attrs),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
mixed_attributes_style::check(cx, item.span, &item.attrs);
|
||||
duplicated_attributes::check(cx, &item.attrs);
|
||||
}
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ use rustc_ast::token::{Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenTree;
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
|
||||
use super::{Attribute, USELESS_ATTRIBUTE};
|
||||
use super::USELESS_ATTRIBUTE;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_ast::{Item, ItemKind, Attribute};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -412,6 +412,8 @@ use rustc_lint::{Lint, LintId};
|
||||
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
// NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
|
||||
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
|
||||
|
||||
store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -21,7 +21,7 @@ use rustc_hir::{
|
||||
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
|
||||
TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
|
||||
};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{LateContext, LintContext, EarlyContext};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
@ -429,11 +429,12 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: ImplItem<'_>) => impl_item_
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: FieldDef<'_>) => field_def_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Variant<'_>) => variant_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Attribute) => attr_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
|
||||
|
||||
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
|
||||
|
||||
impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
|
||||
type Context = LateContext<'cx>;
|
||||
|
||||
|
@ -19,13 +19,5 @@ error: #[allow] attribute found
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
||||
error: #[allow] attribute found
|
||||
--> tests/ui/allow_attributes.rs:52:7
|
||||
|
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -43,14 +43,5 @@ LL | #[allow(unused)]
|
||||
|
|
||||
= help: try adding a reason at the end with `, reason = ".."`
|
||||
|
||||
error: `allow` attribute without specifying a reason
|
||||
--> tests/ui/allow_attributes_without_reason.rs:46:5
|
||||
|
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try adding a reason at the end with `, reason = ".."`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,12 +1,3 @@
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> tests/ui/attrs.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
|
||||
|
||||
error: the since field must contain a semver-compliant version
|
||||
--> tests/ui/attrs.rs:27:14
|
||||
|
|
||||
@ -22,5 +13,14 @@ error: the since field must contain a semver-compliant version
|
||||
LL | #[deprecated(since = "1")]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> tests/ui/attrs.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
|
|
||||
= note: because of the command line `--warn clippy::restriction`
|
||||
= help: enable the restriction lints you need individually
|
||||
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
--> tests/ui/blanket_clippy_restriction_lints.rs:6:9
|
||||
|
|
||||
@ -5,8 +12,6 @@ LL | #![warn(clippy::restriction)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: enable the restriction lints you need individually
|
||||
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
--> tests/ui/blanket_clippy_restriction_lints.rs:8:9
|
||||
@ -24,10 +29,5 @@ LL | #![forbid(clippy::restriction)]
|
||||
|
|
||||
= help: enable the restriction lints you need individually
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
|
|
||||
= note: because of the command line `--warn clippy::restriction`
|
||||
= help: enable the restriction lints you need individually
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
13
tests/rustdoc-ui/show-coverage-json.rs
Normal file
13
tests/rustdoc-ui/show-coverage-json.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//@ compile-flags: -Z unstable-options --show-coverage --output-format=json
|
||||
//@ check-pass
|
||||
|
||||
mod bar {
|
||||
/// a
|
||||
///
|
||||
/// ```
|
||||
/// let x = 0;
|
||||
/// ```
|
||||
pub struct Foo;
|
||||
}
|
||||
|
||||
pub use bar::Foo;
|
1
tests/rustdoc-ui/show-coverage-json.stdout
Normal file
1
tests/rustdoc-ui/show-coverage-json.stdout
Normal file
@ -0,0 +1 @@
|
||||
{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":2,"with_examples":1}}
|
13
tests/rustdoc-ui/show-coverage.rs
Normal file
13
tests/rustdoc-ui/show-coverage.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//@ compile-flags: -Z unstable-options --show-coverage
|
||||
//@ check-pass
|
||||
|
||||
mod bar {
|
||||
/// a
|
||||
///
|
||||
/// ```
|
||||
/// let x = 0;
|
||||
/// ```
|
||||
pub struct Foo;
|
||||
}
|
||||
|
||||
pub use bar::Foo;
|
7
tests/rustdoc-ui/show-coverage.stdout
Normal file
7
tests/rustdoc-ui/show-coverage.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+------------+
|
||||
| File | Documented | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+
|
||||
| ...ests/rustdoc-ui/show-coverage.rs | 1 | 50.0% | 1 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+
|
||||
| Total | 1 | 50.0% | 1 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+
|
@ -1,20 +1,26 @@
|
||||
#![feature(intrinsics)]
|
||||
#![feature(intrinsics, rustc_attrs)]
|
||||
#![feature(staged_api)]
|
||||
|
||||
#![crate_name = "foo"]
|
||||
#![stable(since="1.0.0", feature="rust1")]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
//@ has 'foo/fn.transmute.html'
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
|
||||
#[stable(since="1.0.0", feature="rust1")]
|
||||
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
|
||||
pub fn transmute<T, U>(_: T) -> U;
|
||||
//@ has 'foo/fn.transmute.html'
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe fn transmute<T, U>(_: T) -> U'
|
||||
#[stable(since="1.0.0", feature="rust1")]
|
||||
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub const unsafe fn transmute<T, U>(_: T) -> U {
|
||||
loop {}
|
||||
}
|
||||
|
||||
//@ has 'foo/fn.unreachable.html'
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
|
||||
#[stable(since="1.0.0", feature="rust1")]
|
||||
pub fn unreachable() -> !;
|
||||
//@ has 'foo/fn.unreachable.html'
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !'
|
||||
#[stable(since="1.0.0", feature="rust1")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub unsafe fn unreachable() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||
--> $DIR/coerce-unsafe-to-closure.rs:2:44
|
||||
|
|
||||
LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
|
||||
@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||
= help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
note: required by a bound in `Option::<T>::map`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
@ -1,26 +1,13 @@
|
||||
#![feature(staged_api, rustc_attrs, intrinsics)]
|
||||
#![stable(since="1.0.0", feature = "stable")]
|
||||
|
||||
#[stable(since="1.0.0", feature = "stable")]
|
||||
pub mod old_way {
|
||||
extern "rust-intrinsic" {
|
||||
#[unstable(feature = "unstable", issue = "42")]
|
||||
pub fn size_of_val<T>(x: *const T) -> usize;
|
||||
#[unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||
|
||||
#[unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_const_unstable(feature = "unstable", issue = "42")]
|
||||
pub fn min_align_of_val<T>(x: *const T) -> usize;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since="1.0.0", feature = "stable")]
|
||||
pub mod new_way {
|
||||
#[unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||
|
||||
#[unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_const_unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
|
||||
}
|
||||
#[unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_const_unstable(feature = "unstable", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
|
||||
|
@ -1,7 +1,6 @@
|
||||
//@ check-fail
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_intrinsic_compare_bytes)]
|
||||
use std::intrinsics::compare_bytes;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
|
@ -1,47 +1,47 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:10:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:9:9
|
||||
|
|
||||
LL | compare_bytes(0 as *const u8, 2 as *const u8, 1)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got a null pointer
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:14:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:13:9
|
||||
|
|
||||
LL | compare_bytes(1 as *const u8, 0 as *const u8, 1)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:18:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:17:9
|
||||
|
|
||||
LL | compare_bytes(1 as *const u8, 2 as *const u8, 1)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:22:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:21:9
|
||||
|
|
||||
LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 which is only 3 bytes from the end of the allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:26:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:25:9
|
||||
|
|
||||
LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 which is only 3 bytes from the end of the allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:30:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:29:9
|
||||
|
|
||||
LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:34:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:33:9
|
||||
|
|
||||
LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-compare-bytes-ub.rs:38:9
|
||||
--> $DIR/const-compare-bytes-ub.rs:37:9
|
||||
|
|
||||
LL | compare_bytes([&1].as_ptr().cast(), [&2].as_ptr().cast(), std::mem::size_of::<usize>())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
@ -1,7 +1,6 @@
|
||||
//@ run-pass
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_intrinsic_compare_bytes)]
|
||||
use std::intrinsics::compare_bytes;
|
||||
|
||||
fn main() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
//@ run-pass
|
||||
#![feature(repr_simd)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(intrinsics, rustc_attrs)]
|
||||
#![feature(staged_api)]
|
||||
#![stable(feature = "foo", since = "1.3.37")]
|
||||
#![allow(non_camel_case_types)]
|
||||
@ -10,14 +10,18 @@
|
||||
#[repr(simd)] struct u16x2([u16; 2]);
|
||||
#[repr(simd)] struct f32x4([f32; 4]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[stable(feature = "foo", since = "1.3.37")]
|
||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
|
||||
#[stable(feature = "foo", since = "1.3.37")]
|
||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[stable(feature = "foo", since = "1.3.37")]
|
||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
||||
#[stable(feature = "foo", since = "1.3.37")]
|
||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -14,63 +14,51 @@ fn main() {
|
||||
const fn const_main() {
|
||||
let x = 42;
|
||||
unsafe {
|
||||
unstable_intrinsic::old_way::size_of_val(&x);
|
||||
//~^ERROR: unstable library feature `unstable`
|
||||
//~|ERROR: cannot call non-const intrinsic
|
||||
unstable_intrinsic::old_way::min_align_of_val(&x);
|
||||
//~^ERROR: unstable library feature `unstable`
|
||||
//~|ERROR: not yet stable as a const intrinsic
|
||||
unstable_intrinsic::new_way::size_of_val(&x);
|
||||
unstable_intrinsic::size_of_val(&x);
|
||||
//~^ERROR: unstable library feature `unstable`
|
||||
//~|ERROR: cannot be (indirectly) exposed to stable
|
||||
unstable_intrinsic::new_way::min_align_of_val(&x);
|
||||
unstable_intrinsic::min_align_of_val(&x);
|
||||
//~^ERROR: unstable library feature `unstable`
|
||||
//~|ERROR: not yet stable as a const intrinsic
|
||||
|
||||
old_way::size_of_val(&x);
|
||||
//~^ERROR: cannot call non-const intrinsic
|
||||
old_way::min_align_of_val(&x);
|
||||
//~^ERROR: cannot use `#[feature(local)]`
|
||||
new_way::size_of_val(&x);
|
||||
size_of_val(&x);
|
||||
//~^ERROR: cannot be (indirectly) exposed to stable
|
||||
new_way::min_align_of_val(&x);
|
||||
min_align_of_val(&x);
|
||||
//~^ERROR: cannot use `#[feature(local)]`
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since="1.0.0", feature = "stable")]
|
||||
pub mod old_way {
|
||||
extern "rust-intrinsic" {
|
||||
#[unstable(feature = "local", issue = "42")]
|
||||
pub fn size_of_val<T>(x: *const T) -> usize;
|
||||
#[unstable(feature = "local", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||
|
||||
#[unstable(feature = "local", issue = "42")]
|
||||
#[rustc_const_unstable(feature = "local", issue = "42")]
|
||||
pub fn min_align_of_val<T>(x: *const T) -> usize;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since="1.0.0", feature = "stable")]
|
||||
pub mod new_way {
|
||||
#[unstable(feature = "local", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||
|
||||
#[unstable(feature = "local", issue = "42")]
|
||||
#[rustc_const_unstable(feature = "local", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
|
||||
}
|
||||
#[unstable(feature = "local", issue = "42")]
|
||||
#[rustc_const_unstable(feature = "local", issue = "42")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||
#[inline]
|
||||
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
// Const stability attributes are not inherited from parent items.
|
||||
extern "rust-intrinsic" {
|
||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
unsafe { copy(src, dst, count) }
|
||||
//~^ ERROR cannot call non-const intrinsic
|
||||
//~^ ERROR cannot be (indirectly) exposed to stable
|
||||
}
|
||||
|
||||
// Ensure that a fallback body is recursively-const-checked.
|
||||
mod fallback {
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
|
||||
super::size_of_val(src);
|
||||
//~^ ERROR cannot be (indirectly) exposed to stable
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0658]: use of unstable library feature `unstable`
|
||||
--> $DIR/const-unstable-intrinsic.rs:17:9
|
||||
|
|
||||
LL | unstable_intrinsic::old_way::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | unstable_intrinsic::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
@ -11,74 +11,42 @@ LL | unstable_intrinsic::old_way::size_of_val(&x);
|
||||
error[E0658]: use of unstable library feature `unstable`
|
||||
--> $DIR/const-unstable-intrinsic.rs:20:9
|
||||
|
|
||||
LL | unstable_intrinsic::old_way::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | unstable_intrinsic::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `unstable`
|
||||
--> $DIR/const-unstable-intrinsic.rs:23:9
|
||||
|
|
||||
LL | unstable_intrinsic::new_way::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature `unstable`
|
||||
--> $DIR/const-unstable-intrinsic.rs:26:9
|
||||
|
|
||||
LL | unstable_intrinsic::new_way::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: cannot call non-const intrinsic `size_of_val` in constant functions
|
||||
error: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/const-unstable-intrinsic.rs:17:9
|
||||
|
|
||||
LL | unstable_intrinsic::old_way::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | unstable_intrinsic::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
|
||||
error: `min_align_of_val` is not yet stable as a const intrinsic
|
||||
--> $DIR/const-unstable-intrinsic.rs:20:9
|
||||
|
|
||||
LL | unstable_intrinsic::old_way::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | unstable_intrinsic::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
|
||||
error: intrinsic `unstable_intrinsic::new_way::size_of_val` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/const-unstable-intrinsic.rs:23:9
|
||||
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/const-unstable-intrinsic.rs:24:9
|
||||
|
|
||||
LL | unstable_intrinsic::new_way::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
|
||||
|
||||
error: `min_align_of_val` is not yet stable as a const intrinsic
|
||||
--> $DIR/const-unstable-intrinsic.rs:26:9
|
||||
|
|
||||
LL | unstable_intrinsic::new_way::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
|
||||
error: cannot call non-const intrinsic `size_of_val` in constant functions
|
||||
--> $DIR/const-unstable-intrinsic.rs:30:9
|
||||
|
|
||||
LL | old_way::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||
--> $DIR/const-unstable-intrinsic.rs:32:9
|
||||
--> $DIR/const-unstable-intrinsic.rs:26:9
|
||||
|
|
||||
LL | old_way::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
@ -91,37 +59,22 @@ LL + #[rustc_allow_const_fn_unstable(local)]
|
||||
LL | const fn const_main() {
|
||||
|
|
||||
|
||||
error: intrinsic `new_way::size_of_val` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/const-unstable-intrinsic.rs:34:9
|
||||
|
|
||||
LL | new_way::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
|
||||
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||
--> $DIR/const-unstable-intrinsic.rs:36:9
|
||||
|
|
||||
LL | new_way::min_align_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||
LL | const fn const_main() {
|
||||
|
|
||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||
|
|
||||
LL + #[rustc_allow_const_fn_unstable(local)]
|
||||
LL | const fn const_main() {
|
||||
|
|
||||
|
||||
error: cannot call non-const intrinsic `copy` in constant functions
|
||||
--> $DIR/const-unstable-intrinsic.rs:74:14
|
||||
error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/const-unstable-intrinsic.rs:53:14
|
||||
|
|
||||
LL | unsafe { copy(src, dst, count) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/const-unstable-intrinsic.rs:61:9
|
||||
|
|
||||
LL | super::size_of_val(src);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -1,17 +1,21 @@
|
||||
#![stable(feature = "dummy", since = "1.0.0")]
|
||||
|
||||
// ignore-tidy-linelength
|
||||
#![feature(intrinsics, staged_api)]
|
||||
#![feature(intrinsics, staged_api, rustc_attrs)]
|
||||
use std::mem;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[stable(feature = "dummy", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||
#[stable(feature = "dummy", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[stable(feature = "dummy", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
#[stable(feature = "dummy", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
const COPY_ZERO: () = unsafe {
|
||||
|
@ -1,23 +1,23 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/copy-intrinsic.rs:30:5
|
||||
--> $DIR/copy-intrinsic.rs:34:5
|
||||
|
|
||||
LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/copy-intrinsic.rs:39:5
|
||||
--> $DIR/copy-intrinsic.rs:43:5
|
||||
|
|
||||
LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/copy-intrinsic.rs:46:5
|
||||
--> $DIR/copy-intrinsic.rs:50:5
|
||||
|
|
||||
LL | copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/copy-intrinsic.rs:52:5
|
||||
--> $DIR/copy-intrinsic.rs:56:5
|
||||
|
|
||||
LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
|
||||
|
11
tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
Normal file
11
tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Duplicate implementations of Copy/Clone should not trigger
|
||||
// borrow check warnings
|
||||
// See #131083
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone)]
|
||||
//~^ ERROR conflicting implementations of trait `Clone` for type `E`
|
||||
//~| ERROR conflicting implementations of trait `Copy` for type `E`
|
||||
enum E {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
error[E0119]: conflicting implementations of trait `Copy` for type `E`
|
||||
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:10
|
||||
|
|
||||
LL | #[derive(Copy, Clone)]
|
||||
| ---- first implementation here
|
||||
LL | #[derive(Copy, Clone)]
|
||||
| ^^^^ conflicting implementation for `E`
|
||||
|
|
||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Clone` for type `E`
|
||||
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
|
||||
|
|
||||
LL | #[derive(Copy, Clone)]
|
||||
| ----- first implementation here
|
||||
LL | #[derive(Copy, Clone)]
|
||||
| ^^^^^ conflicting implementation for `E`
|
||||
|
|
||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -41,6 +41,10 @@ LL | Struct { a, b } = Struct { a: 1, b: 2 };
|
||||
| ~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Struct { a, b: _ } = Struct { a: 1, b: 2 };
|
||||
| ~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Struct { a, .. } = Struct { a: 1, b: 2 };
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -10,6 +10,10 @@ LL | Dog { age: x, name } => {}
|
||||
| ~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Dog { age: x, name: _ } => {}
|
||||
| ~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Dog { age: x, .. } => {}
|
||||
| ~~~~~~
|
||||
|
||||
@ -25,6 +29,10 @@ LL | Dog { name: x, age } => {}
|
||||
| ~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Dog { name: x, age: _ } => {}
|
||||
| ~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Dog { name: x, .. } => {}
|
||||
| ~~~~~~
|
||||
|
||||
@ -40,6 +48,10 @@ LL | Dog { name: x, age } => {}
|
||||
| ~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Dog { name: x, age: _ } => {}
|
||||
| ~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Dog { name: x, .. } => {}
|
||||
| ~~~~~~
|
||||
|
||||
@ -55,6 +67,10 @@ LL | Dog { name, age } => {}
|
||||
| ~~~~~~~~~~~~~
|
||||
help: if you don't care about these missing fields, you can explicitly ignore them
|
||||
|
|
||||
LL | Dog { name: _, age: _ } => {}
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Dog { .. } => {}
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_intrinsic_raw_eq)]
|
||||
|
||||
const RAW_EQ_PADDING: bool = unsafe {
|
||||
std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:5:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:4:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:11:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:10:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(&0), &(&1))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
@ -14,7 +14,7 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1))
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:19:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:18:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(aref, aref)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required
|
||||
|
@ -1,7 +1,6 @@
|
||||
//@ run-pass
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_intrinsic_raw_eq)]
|
||||
|
||||
pub fn main() {
|
||||
use std::intrinsics::raw_eq;
|
||||
|
@ -7,9 +7,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
|
||||
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||
found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
|
||||
|
||||
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
|
||||
error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
|
||||
--> $DIR/reify-intrinsic.rs:11:13
|
||||
|
|
||||
LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
|
||||
|
@ -21,6 +21,10 @@ LL | let HiddenStruct { one, two, .. } = HiddenStruct::default();
|
||||
| ~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let HiddenStruct { one, two: _, .. } = HiddenStruct::default();
|
||||
| ~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let HiddenStruct { one, .. } = HiddenStruct::default();
|
||||
| ~~~~~~
|
||||
|
||||
@ -36,6 +40,10 @@ LL | let HiddenStruct { one, hide, two } = HiddenStruct::default();
|
||||
| ~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let HiddenStruct { one, hide, two: _ } = HiddenStruct::default();
|
||||
| ~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default();
|
||||
| ~~~~~~
|
||||
|
||||
@ -51,6 +59,10 @@ LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden:
|
||||
| ~~~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let InCrate { a, b, im_hidden: _ } = InCrate { a: 0, b: false, im_hidden: 0 };
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 };
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -10,6 +10,10 @@ LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
|
||||
| ~~~~~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let UnstableStruct { stable, stable2: _, .. } = UnstableStruct::default();
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -10,6 +10,10 @@ LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::defa
|
||||
| ~~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let UnstableStruct { stable, stable2, unstable: _ } = UnstableStruct::default();
|
||||
| ~~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
|
||||
| ~~~~~~
|
||||
|
||||
@ -25,6 +29,10 @@ LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::defa
|
||||
| ~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let UnstableStruct { stable, unstable, stable2: _ } = UnstableStruct::default();
|
||||
| ~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default();
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -21,11 +21,12 @@ enum Foo {
|
||||
Bar,
|
||||
}
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
|
||||
#[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
|
||||
#[rustc_safe_intrinsic]
|
||||
fn size_of<T>() -> usize;
|
||||
#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
|
||||
#[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
const fn size_of<T>() -> usize {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang="sized"]
|
||||
|
@ -38,3 +38,9 @@ pub enum NonExhaustiveCLikeEnum {
|
||||
Four = 4,
|
||||
Five = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NormalStructWithNonExhaustiveCLikeEnum {
|
||||
one: u8,
|
||||
two: NonExhaustiveCLikeEnum,
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ extern crate types;
|
||||
|
||||
use types::{
|
||||
NonExhaustiveCLikeEnum, NonExhaustiveEnum, NonExhaustiveVariants,
|
||||
NormalStruct, TupleStruct, UnitStruct,
|
||||
NormalStruct, TupleStruct, UnitStruct, NormalStructWithNonExhaustiveCLikeEnum
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
@ -27,6 +27,9 @@ extern "C" {
|
||||
// These should pass without remark, as they're C-compatible, despite being "non-exhaustive".
|
||||
extern "C" {
|
||||
pub fn non_exhaustive_c_compat_enum(_: NonExhaustiveCLikeEnum);
|
||||
pub fn non_exhaustive_c_compat_enum_ret() -> *mut NonExhaustiveCLikeEnum;
|
||||
pub fn struct_w_non_exhaustive_c_like_enum(_: NormalStructWithNonExhaustiveCLikeEnum);
|
||||
pub fn struct_w_non_exhaustive_c_like_enum_ret() -> *mut NormalStructWithNonExhaustiveCLikeEnum;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -36,10 +36,4 @@ impl const Bar for Foo {
|
||||
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||
//~^ ERROR function has missing const stability attribute
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[stable(feature = "stable", since = "1.0.0")]
|
||||
#[rustc_const_stable_indirect]
|
||||
pub fn min_align_of_val<T>(x: *const T) -> usize;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -24,6 +24,10 @@ LL | let Foo { present } = foo;
|
||||
| ~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let Foo { present: _ } = foo;
|
||||
| ~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let Foo { .. } = foo;
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -27,6 +27,10 @@ LL | let A { x, y, b, c } = self.d;
|
||||
| ~~~~~~~~
|
||||
help: if you don't care about these missing fields, you can explicitly ignore them
|
||||
|
|
||||
LL | let A { x, y, b: _, c: _ } = self.d;
|
||||
| ~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let A { x, y, .. } = self.d;
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -32,6 +32,10 @@ LL | if let E::S { 0: a, 1: _ } = x {
|
||||
| ~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | if let E::S { 0: a, 1: _ } = x {
|
||||
| ~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | if let E::S { 0: a, .. } = x {
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -19,6 +19,10 @@ LL | Foo::Bar { a, aa: 1, c, b } => (),
|
||||
| ~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Foo::Bar { a, aa: 1, c, b: _ } => (),
|
||||
| ~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Foo::Bar { a, aa: 1, c, .. } => (),
|
||||
| ~~~~~~
|
||||
|
||||
@ -43,6 +47,10 @@ LL | Foo::Baz { bb: 1.0, a } => (),
|
||||
| ~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Foo::Baz { bb: 1.0, a: _ } => (),
|
||||
| ~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Foo::Baz { bb: 1.0, .. } => (),
|
||||
| ~~~~~~
|
||||
|
||||
@ -64,6 +72,10 @@ LL | Foo::Bar { a, aa: "", c, b } => (),
|
||||
| ~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Foo::Bar { a, aa: "", c, b: _ } => (),
|
||||
| ~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Foo::Bar { a, aa: "", c, .. } => (),
|
||||
| ~~~~~~
|
||||
|
||||
@ -85,6 +97,10 @@ LL | Foo::Baz { bb: "", a } => (),
|
||||
| ~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | Foo::Baz { bb: "", a: _ } => (),
|
||||
| ~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | Foo::Baz { bb: "", .. } => (),
|
||||
| ~~~~~~
|
||||
|
||||
|
@ -18,10 +18,12 @@ trait Sized {}
|
||||
trait Copy {}
|
||||
impl Copy for bool {}
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[stable(feature = "test", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
||||
fn unreachable() -> !;
|
||||
#[stable(feature = "test", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
const unsafe fn unreachable() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
|
@ -16,10 +16,12 @@ trait Sized {}
|
||||
trait Copy {}
|
||||
impl Copy for bool {}
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[stable(feature = "test", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
||||
fn unreachable() -> !;
|
||||
#[stable(feature = "test", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
const unsafe fn unreachable() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
|
@ -10,6 +10,10 @@ LL | let foo::Foo { visible, .. } = foo::Foo::default();
|
||||
| ~~~~~~~~~~~~~~~
|
||||
help: if you don't care about this missing field, you can explicitly ignore it
|
||||
|
|
||||
LL | let foo::Foo { visible: _, .. } = foo::Foo::default();
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
help: or always ignore missing fields here
|
||||
|
|
||||
LL | let foo::Foo { .. } = foo::Foo::default();
|
||||
| ~~~~~~
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user