mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 09:44:08 +00:00
Auto merge of #77606 - JohnTitor:rollup-7rgahdt, r=JohnTitor
Rollup of 13 pull requests Successful merges: - #76388 (Add a note about the panic behavior of math operations on time objects) - #76855 (Revamp rustdoc docs about documentation using `cfg`) - #76995 (Reduce boilerplate with the matches! macro) - #77228 (Add missing examples for MaybeUninit) - #77528 (Avoid unchecked casts in net parser) - #77534 (Disallow overriding forbid in same scope) - #77555 (Allow anyone to set regression labels) - #77558 (Rename bootstrap/defaults/{config.toml.PROFILE => config.PROFILE.toml}) - #77559 (Fix rustdoc warnings about invalid Rust syntax) - #77560 (Fix LitKind's byte buffer to use refcounted slice) - #77573 (Hint doc use convert::identity relative link) - #77587 (Fix span for unicode escape suggestion.) - #77591 (Record `expansion_that_defined` into crate metadata) Failed merges: r? `@ghost`
This commit is contained in:
commit
5ded394553
@ -1606,7 +1606,7 @@ pub enum LitKind {
|
||||
/// A string literal (`"foo"`).
|
||||
Str(Symbol, StrStyle),
|
||||
/// A byte string (`b"foo"`).
|
||||
ByteStr(Lrc<Vec<u8>>),
|
||||
ByteStr(Lrc<[u8]>),
|
||||
/// A byte char (`b'f'`).
|
||||
Byte(u8),
|
||||
/// A character literal (`'a'`).
|
||||
|
@ -4,7 +4,6 @@ use crate::ast::{self, Lit, LitKind};
|
||||
use crate::token::{self, Token};
|
||||
use crate::tokenstream::TokenTree;
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_lexer::unescape::{unescape_byte, unescape_char};
|
||||
use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
@ -108,7 +107,7 @@ impl LitKind {
|
||||
});
|
||||
error?;
|
||||
buf.shrink_to_fit();
|
||||
LitKind::ByteStr(Lrc::new(buf))
|
||||
LitKind::ByteStr(buf.into())
|
||||
}
|
||||
token::ByteStrRaw(_) => {
|
||||
let s = symbol.as_str();
|
||||
@ -128,7 +127,7 @@ impl LitKind {
|
||||
symbol.to_string().into_bytes()
|
||||
};
|
||||
|
||||
LitKind::ByteStr(Lrc::new(bytes))
|
||||
LitKind::ByteStr(bytes.into())
|
||||
}
|
||||
token::Err => LitKind::Err(symbol),
|
||||
})
|
||||
|
@ -13,8 +13,6 @@ use rustc_span::{self, Pos, Span};
|
||||
use smallvec::SmallVec;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
// These macros all relate to the file system; they either return
|
||||
// the column/row/filename of the expression, or they include
|
||||
// a given file into the current one.
|
||||
@ -216,7 +214,7 @@ pub fn expand_include_bytes(
|
||||
}
|
||||
};
|
||||
match cx.source_map().load_binary_file(&file) {
|
||||
Ok(bytes) => base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))),
|
||||
Ok(bytes) => base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(bytes.into()))),
|
||||
Err(e) => {
|
||||
cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
|
||||
DummyResult::any(sp)
|
||||
|
@ -10,6 +10,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_hir::{intravisit, HirId};
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::lint::LevelSource;
|
||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||
use rustc_middle::lint::{struct_lint_level, LintLevelMap, LintLevelSets, LintSet, LintSource};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
@ -95,6 +96,44 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
self.sets.list.push(LintSet::CommandLine { specs });
|
||||
}
|
||||
|
||||
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
|
||||
/// (e.g. if a forbid was already inserted on the same scope), then emits a
|
||||
/// diagnostic with no change to `specs`.
|
||||
fn insert_spec(
|
||||
&mut self,
|
||||
specs: &mut FxHashMap<LintId, LevelSource>,
|
||||
id: LintId,
|
||||
(level, src): LevelSource,
|
||||
) {
|
||||
if let Some((old_level, old_src)) = specs.get(&id) {
|
||||
if old_level == &Level::Forbid && level != Level::Forbid {
|
||||
let mut diag_builder = struct_span_err!(
|
||||
self.sess,
|
||||
src.span(),
|
||||
E0453,
|
||||
"{}({}) incompatible with previous forbid in same scope",
|
||||
level.as_str(),
|
||||
src.name(),
|
||||
);
|
||||
match *old_src {
|
||||
LintSource::Default => {}
|
||||
LintSource::Node(_, forbid_source_span, reason) => {
|
||||
diag_builder.span_label(forbid_source_span, "`forbid` level set here");
|
||||
if let Some(rationale) = reason {
|
||||
diag_builder.note(&rationale.as_str());
|
||||
}
|
||||
}
|
||||
LintSource::CommandLine(_) => {
|
||||
diag_builder.note("`forbid` lint level was set on command line");
|
||||
}
|
||||
}
|
||||
diag_builder.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
specs.insert(id, (level, src));
|
||||
}
|
||||
|
||||
/// Pushes a list of AST lint attributes onto this context.
|
||||
///
|
||||
/// This function will return a `BuilderPush` object which should be passed
|
||||
@ -109,7 +148,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
/// `#[allow]`
|
||||
///
|
||||
/// Don't forget to call `pop`!
|
||||
pub fn push(
|
||||
pub(crate) fn push(
|
||||
&mut self,
|
||||
attrs: &[ast::Attribute],
|
||||
store: &LintStore,
|
||||
@ -221,7 +260,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
let src = LintSource::Node(name, li.span(), reason);
|
||||
for &id in ids {
|
||||
self.check_gated_lint(id, attr.span);
|
||||
specs.insert(id, (level, src));
|
||||
self.insert_spec(&mut specs, id, (level, src));
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +274,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
reason,
|
||||
);
|
||||
for id in ids {
|
||||
specs.insert(*id, (level, src));
|
||||
self.insert_spec(&mut specs, *id, (level, src));
|
||||
}
|
||||
}
|
||||
Err((Some(ids), new_lint_name)) => {
|
||||
@ -272,7 +311,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
reason,
|
||||
);
|
||||
for id in ids {
|
||||
specs.insert(*id, (level, src));
|
||||
self.insert_spec(&mut specs, *id, (level, src));
|
||||
}
|
||||
}
|
||||
Err((None, _)) => {
|
||||
|
@ -1011,6 +1011,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
|
||||
}
|
||||
|
||||
fn get_expn_that_defined(&self, id: DefIndex, sess: &Session) -> ExpnId {
|
||||
self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess))
|
||||
}
|
||||
|
||||
/// Iterates over all the stability attributes in the given crate.
|
||||
fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option<Symbol>)] {
|
||||
// FIXME: For a proc macro crate, not sure whether we should return the "host"
|
||||
|
@ -238,6 +238,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
}
|
||||
|
||||
crate_extern_paths => { cdata.source().paths().cloned().collect() }
|
||||
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
@ -747,6 +747,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
ty::Visibility::from_hir(enum_vis, enum_id, self.tcx));
|
||||
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
|
||||
record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
|
||||
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
|
||||
record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
|
||||
assert!(f.did.is_local());
|
||||
f.did.index
|
||||
@ -883,6 +884,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
record!(self.tables.visibility[def_id] <- field.vis);
|
||||
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
|
||||
record!(self.tables.attributes[def_id] <- variant_data.fields()[field_index].attrs);
|
||||
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
|
||||
self.encode_ident_span(def_id, field.ident);
|
||||
self.encode_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
@ -924,6 +926,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
|
||||
record!(self.tables.visibility[def_id] <- ctor_vis);
|
||||
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
|
||||
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
|
||||
self.encode_stability(def_id);
|
||||
self.encode_deprecation(def_id);
|
||||
self.encode_item_type(def_id);
|
||||
@ -1339,6 +1342,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
|
||||
record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
|
||||
record!(self.tables.attributes[def_id] <- item.attrs);
|
||||
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
|
||||
// FIXME(eddyb) there should be a nicer way to do this.
|
||||
match item.kind {
|
||||
hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <-
|
||||
|
@ -294,6 +294,7 @@ define_tables! {
|
||||
variances: Table<DefIndex, Lazy<[ty::Variance]>>,
|
||||
generics: Table<DefIndex, Lazy<ty::Generics>>,
|
||||
explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
|
||||
expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
|
||||
// FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
|
||||
// doesn't handle shorthands in its own (de)serialization impls,
|
||||
// as it's an `enum` for which we want to derive (de)serialization,
|
||||
|
@ -535,15 +535,15 @@ impl<'hir> Map<'hir> {
|
||||
Some(Node::Binding(_)) => (),
|
||||
_ => return false,
|
||||
}
|
||||
match self.find(self.get_parent_node(id)) {
|
||||
matches!(
|
||||
self.find(self.get_parent_node(id)),
|
||||
Some(
|
||||
Node::Item(_)
|
||||
| Node::TraitItem(_)
|
||||
| Node::ImplItem(_)
|
||||
| Node::Expr(Expr { kind: ExprKind::Closure(..), .. }),
|
||||
) => true,
|
||||
_ => false,
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
|
||||
@ -554,10 +554,10 @@ impl<'hir> Map<'hir> {
|
||||
|
||||
/// Whether `hir_id` corresponds to a `mod` or a crate.
|
||||
pub fn is_hir_id_module(&self, hir_id: HirId) -> bool {
|
||||
match self.get_entry(hir_id).node {
|
||||
Node::Item(Item { kind: ItemKind::Mod(_), .. }) | Node::Crate(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self.get_entry(hir_id).node,
|
||||
Node::Item(Item { kind: ItemKind::Mod(_), .. }) | Node::Crate(..)
|
||||
)
|
||||
}
|
||||
|
||||
/// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
|
||||
|
@ -9,7 +9,7 @@ use rustc_session::lint::{builtin, Level, Lint, LintId};
|
||||
use rustc_session::{DiagnosticMessageId, Session};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
|
||||
|
||||
/// How a lint level was set.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
|
||||
@ -25,6 +25,24 @@ pub enum LintSource {
|
||||
CommandLine(Symbol),
|
||||
}
|
||||
|
||||
impl LintSource {
|
||||
pub fn name(&self) -> Symbol {
|
||||
match *self {
|
||||
LintSource::Default => symbol::kw::Default,
|
||||
LintSource::Node(name, _, _) => name,
|
||||
LintSource::CommandLine(name) => name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
match *self {
|
||||
LintSource::Default => DUMMY_SP,
|
||||
LintSource::Node(_, span, _) => span,
|
||||
LintSource::CommandLine(_) => DUMMY_SP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type LevelSource = (Level, LintSource);
|
||||
|
||||
pub struct LintLevelSets {
|
||||
|
@ -486,10 +486,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
// `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true.
|
||||
// However, formatting code relies on function identity (see #58320), so we only do
|
||||
// this for generic functions. Lifetime parameters are ignored.
|
||||
let is_generic = instance.substs.into_iter().any(|kind| match kind.unpack() {
|
||||
GenericArgKind::Lifetime(_) => false,
|
||||
_ => true,
|
||||
});
|
||||
let is_generic = instance
|
||||
.substs
|
||||
.into_iter()
|
||||
.any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_)));
|
||||
if is_generic {
|
||||
// Get a fresh ID.
|
||||
let mut alloc_map = self.alloc_map.lock();
|
||||
|
@ -445,19 +445,13 @@ impl<'tcx, Tag> Scalar<Tag> {
|
||||
/// Do not call this method! Dispatch based on the type instead.
|
||||
#[inline]
|
||||
pub fn is_bits(self) -> bool {
|
||||
match self {
|
||||
Scalar::Raw { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, Scalar::Raw { .. })
|
||||
}
|
||||
|
||||
/// Do not call this method! Dispatch based on the type instead.
|
||||
#[inline]
|
||||
pub fn is_ptr(self) -> bool {
|
||||
match self {
|
||||
Scalar::Ptr(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, Scalar::Ptr(_))
|
||||
}
|
||||
|
||||
pub fn to_bool(self) -> InterpResult<'tcx, bool> {
|
||||
|
@ -971,67 +971,59 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
/// - `let x = ...`,
|
||||
/// - or `match ... { C(x) => ... }`
|
||||
pub fn can_be_made_mutable(&self) -> bool {
|
||||
match self.local_info {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
})))) => true,
|
||||
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
ImplicitSelfKind::Imm,
|
||||
)))) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(
|
||||
BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
})
|
||||
| BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if local is definitely not a `ref ident` or
|
||||
/// `ref mut ident` binding. (Such bindings cannot be made into
|
||||
/// mutable bindings, but the inverse does not necessarily hold).
|
||||
pub fn is_nonref_binding(&self) -> bool {
|
||||
match self.local_info {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
})))) => true,
|
||||
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(
|
||||
BindingForm::Var(VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info: _,
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
})
|
||||
| BindingForm::ImplicitSelf(_),
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if this variable is a named variable or function
|
||||
/// parameter declared by the user.
|
||||
#[inline]
|
||||
pub fn is_user_variable(&self) -> bool {
|
||||
match self.local_info {
|
||||
Some(box LocalInfo::User(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.local_info, Some(box LocalInfo::User(_)))
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a reference to a variable bound in a `match`
|
||||
/// expression that is used to access said variable for the guard of the
|
||||
/// match arm.
|
||||
pub fn is_ref_for_guard(&self) -> bool {
|
||||
match self.local_info {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)))
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `Some` if this is a reference to a static item that is used to
|
||||
/// access that static
|
||||
pub fn is_ref_to_static(&self) -> bool {
|
||||
match self.local_info {
|
||||
Some(box LocalInfo::StaticRef { .. }) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.local_info, Some(box LocalInfo::StaticRef { .. }))
|
||||
}
|
||||
|
||||
/// Returns `Some` if this is a reference to a static item that is used to
|
||||
@ -2164,10 +2156,7 @@ pub enum BinOp {
|
||||
impl BinOp {
|
||||
pub fn is_checkable(self) -> bool {
|
||||
use self::BinOp::*;
|
||||
match self {
|
||||
Add | Sub | Mul | Shl | Shr => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, Add | Sub | Mul | Shl | Shr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1164,82 +1164,63 @@ pub enum PlaceContext {
|
||||
impl PlaceContext {
|
||||
/// Returns `true` if this place context represents a drop.
|
||||
pub fn is_drop(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a borrow.
|
||||
pub fn is_borrow(&self) -> bool {
|
||||
match *self {
|
||||
matches!(
|
||||
self,
|
||||
PlaceContext::NonMutatingUse(
|
||||
NonMutatingUseContext::SharedBorrow
|
||||
| NonMutatingUseContext::ShallowBorrow
|
||||
| NonMutatingUseContext::UniqueBorrow,
|
||||
)
|
||||
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true,
|
||||
_ => false,
|
||||
}
|
||||
| NonMutatingUseContext::ShallowBorrow
|
||||
| NonMutatingUseContext::UniqueBorrow
|
||||
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a storage live or storage dead marker.
|
||||
pub fn is_storage_marker(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self,
|
||||
PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a storage live marker.
|
||||
pub fn is_storage_live_marker(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::NonUse(NonUseContext::StorageLive) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, PlaceContext::NonUse(NonUseContext::StorageLive))
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a storage dead marker.
|
||||
pub fn is_storage_dead_marker(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::NonUse(NonUseContext::StorageDead) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, PlaceContext::NonUse(NonUseContext::StorageDead))
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a use that potentially changes the value.
|
||||
pub fn is_mutating_use(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::MutatingUse(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, PlaceContext::MutatingUse(..))
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a use that does not change the value.
|
||||
pub fn is_nonmutating_use(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::NonMutatingUse(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, PlaceContext::NonMutatingUse(..))
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents a use.
|
||||
pub fn is_use(&self) -> bool {
|
||||
match *self {
|
||||
PlaceContext::NonUse(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
!matches!(self, PlaceContext::NonUse(..))
|
||||
}
|
||||
|
||||
/// Returns `true` if this place context represents an assignment statement.
|
||||
pub fn is_place_assignment(&self) -> bool {
|
||||
match *self {
|
||||
matches!(
|
||||
self,
|
||||
PlaceContext::MutatingUse(
|
||||
MutatingUseContext::Store
|
||||
| MutatingUseContext::Call
|
||||
| MutatingUseContext::AsmOutput,
|
||||
) => true,
|
||||
_ => false,
|
||||
}
|
||||
| MutatingUseContext::Call
|
||||
| MutatingUseContext::AsmOutput,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -191,6 +191,11 @@ rustc_queries! {
|
||||
eval_always
|
||||
desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
}
|
||||
|
||||
/// Internal helper query. Use `tcx.expansion_that_defined` instead
|
||||
query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
|
||||
desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
}
|
||||
|
||||
Codegen {
|
||||
|
@ -79,10 +79,7 @@ pub enum Node {
|
||||
|
||||
impl<'tcx> Node {
|
||||
pub fn is_from_trait(&self) -> bool {
|
||||
match *self {
|
||||
Node::Trait(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, Node::Trait(..))
|
||||
}
|
||||
|
||||
/// Iterate over the items defined directly by the given (impl or trait) node.
|
||||
|
@ -85,10 +85,7 @@ pub struct Adjustment<'tcx> {
|
||||
|
||||
impl Adjustment<'tcx> {
|
||||
pub fn is_region_borrow(&self) -> bool {
|
||||
match self.kind {
|
||||
Adjust::Borrow(AutoBorrow::Ref(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,10 +588,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
match self.type_dependent_defs().get(expr.hir_id) {
|
||||
Some(Ok((DefKind::AssocFn, _))) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
|
||||
}
|
||||
|
||||
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
|
||||
|
@ -11,21 +11,16 @@ use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
|
||||
impl<'tcx> TyS<'tcx> {
|
||||
/// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive.
|
||||
pub fn is_primitive_ty(&self) -> bool {
|
||||
match self.kind() {
|
||||
Bool
|
||||
| Char
|
||||
| Str
|
||||
| Int(_)
|
||||
| Uint(_)
|
||||
| Float(_)
|
||||
matches!(
|
||||
self.kind(),
|
||||
Bool | Char | Str | Int(_) | Uint(_) | Float(_)
|
||||
| Infer(
|
||||
InferTy::IntVar(_)
|
||||
| InferTy::FloatVar(_)
|
||||
| InferTy::FreshIntTy(_)
|
||||
| InferTy::FreshFloatTy(_),
|
||||
) => true,
|
||||
_ => false,
|
||||
}
|
||||
| InferTy::FreshFloatTy(_)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether the type is succinctly representable as a type instead of just referred to with a
|
||||
@ -64,11 +59,16 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
/// Whether the type can be safely suggested during error recovery.
|
||||
pub fn is_suggestable(&self) -> bool {
|
||||
match self.kind() {
|
||||
Opaque(..) | FnDef(..) | FnPtr(..) | Dynamic(..) | Closure(..) | Infer(..)
|
||||
| Projection(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
!matches!(
|
||||
self.kind(),
|
||||
Opaque(..)
|
||||
| FnDef(..)
|
||||
| FnPtr(..)
|
||||
| Dynamic(..)
|
||||
| Closure(..)
|
||||
| Infer(..)
|
||||
| Projection(..)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,10 +184,10 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
|
||||
_ => return true,
|
||||
};
|
||||
match tcx.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::Ctor | DefPathData::ClosureExpr => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
tcx.def_key(def_id).disambiguated_data.data,
|
||||
DefPathData::Ctor | DefPathData::ClosureExpr
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if the machine code for this instance is instantiated in
|
||||
|
@ -2610,10 +2610,7 @@ where
|
||||
target.target_os == "linux" && target.arch == "sparc64" && target_env_gnu_like;
|
||||
let linux_powerpc_gnu_like =
|
||||
target.target_os == "linux" && target.arch == "powerpc" && target_env_gnu_like;
|
||||
let rust_abi = match sig.abi {
|
||||
RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true,
|
||||
_ => false,
|
||||
};
|
||||
let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
|
||||
|
||||
// Handle safe Rust thin and fat pointers.
|
||||
let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
|
||||
|
@ -2681,15 +2681,15 @@ impl<'tcx> ClosureKind {
|
||||
/// Returns `true` if a type that impls this closure kind
|
||||
/// must also implement `other`.
|
||||
pub fn extends(self, other: ty::ClosureKind) -> bool {
|
||||
match (self, other) {
|
||||
(ClosureKind::Fn, ClosureKind::Fn) => true,
|
||||
(ClosureKind::Fn, ClosureKind::FnMut) => true,
|
||||
(ClosureKind::Fn, ClosureKind::FnOnce) => true,
|
||||
(ClosureKind::FnMut, ClosureKind::FnMut) => true,
|
||||
(ClosureKind::FnMut, ClosureKind::FnOnce) => true,
|
||||
(ClosureKind::FnOnce, ClosureKind::FnOnce) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
(self, other),
|
||||
(ClosureKind::Fn, ClosureKind::Fn)
|
||||
| (ClosureKind::Fn, ClosureKind::FnMut)
|
||||
| (ClosureKind::Fn, ClosureKind::FnOnce)
|
||||
| (ClosureKind::FnMut, ClosureKind::FnMut)
|
||||
| (ClosureKind::FnMut, ClosureKind::FnOnce)
|
||||
| (ClosureKind::FnOnce, ClosureKind::FnOnce)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the representative scalar type for this closure kind.
|
||||
@ -2815,15 +2815,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
|
||||
let is_associated_item = if let Some(def_id) = def_id.as_local() {
|
||||
match self.hir().get(self.hir().local_def_id_to_hir_id(def_id)) {
|
||||
Node::TraitItem(_) | Node::ImplItem(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self.hir().get(self.hir().local_def_id_to_hir_id(def_id)),
|
||||
Node::TraitItem(_) | Node::ImplItem(_)
|
||||
)
|
||||
} else {
|
||||
match self.def_kind(def_id) {
|
||||
DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
self.def_kind(def_id),
|
||||
DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy
|
||||
)
|
||||
};
|
||||
|
||||
is_associated_item.then(|| self.associated_item(def_id))
|
||||
@ -3034,10 +3034,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
.hygienic_eq(def_name.span.ctxt(), self.expansion_that_defined(def_parent_def_id))
|
||||
}
|
||||
|
||||
fn expansion_that_defined(self, scope: DefId) -> ExpnId {
|
||||
pub fn expansion_that_defined(self, scope: DefId) -> ExpnId {
|
||||
match scope.as_local() {
|
||||
// Parsing and expansion aren't incremental, so we don't
|
||||
// need to go through a query for the same-crate case.
|
||||
Some(scope) => self.hir().definitions().expansion_that_defined(scope),
|
||||
None => ExpnId::root(),
|
||||
None => self.expn_that_defined(scope),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1763,10 +1763,7 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_never(&self) -> bool {
|
||||
match self.kind() {
|
||||
Never => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Never)
|
||||
}
|
||||
|
||||
/// Checks whether a type is definitely uninhabited. This is
|
||||
@ -1823,34 +1820,22 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_adt(&self) -> bool {
|
||||
match self.kind() {
|
||||
Adt(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Adt(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ref(&self) -> bool {
|
||||
match self.kind() {
|
||||
Ref(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Ref(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ty_var(&self) -> bool {
|
||||
match self.kind() {
|
||||
Infer(TyVar(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Infer(TyVar(_)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ty_infer(&self) -> bool {
|
||||
match self.kind() {
|
||||
Infer(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Infer(_))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1880,20 +1865,14 @@ impl<'tcx> TyS<'tcx> {
|
||||
#[inline]
|
||||
pub fn is_slice(&self) -> bool {
|
||||
match self.kind() {
|
||||
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.kind() {
|
||||
Slice(_) | Str => true,
|
||||
_ => false,
|
||||
},
|
||||
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_) | Str),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_array(&self) -> bool {
|
||||
match self.kind() {
|
||||
Array(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Array(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1940,27 +1919,21 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_region_ptr(&self) -> bool {
|
||||
match self.kind() {
|
||||
Ref(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Ref(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_mutable_ptr(&self) -> bool {
|
||||
match self.kind() {
|
||||
matches!(
|
||||
self.kind(),
|
||||
RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. })
|
||||
| Ref(_, _, hir::Mutability::Mut) => true,
|
||||
_ => false,
|
||||
}
|
||||
| Ref(_, _, hir::Mutability::Mut)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_unsafe_ptr(&self) -> bool {
|
||||
match self.kind() {
|
||||
RawPtr(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), RawPtr(_))
|
||||
}
|
||||
|
||||
/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
|
||||
@ -1990,35 +1963,22 @@ impl<'tcx> TyS<'tcx> {
|
||||
/// contents are abstract to rustc.)
|
||||
#[inline]
|
||||
pub fn is_scalar(&self) -> bool {
|
||||
match self.kind() {
|
||||
Bool
|
||||
| Char
|
||||
| Int(_)
|
||||
| Float(_)
|
||||
| Uint(_)
|
||||
matches!(
|
||||
self.kind(),
|
||||
Bool | Char | Int(_) | Float(_) | Uint(_) | FnDef(..) | FnPtr(_) | RawPtr(_)
|
||||
| Infer(IntVar(_) | FloatVar(_))
|
||||
| FnDef(..)
|
||||
| FnPtr(_)
|
||||
| RawPtr(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `true` if this type is a floating point type.
|
||||
#[inline]
|
||||
pub fn is_floating_point(&self) -> bool {
|
||||
match self.kind() {
|
||||
Float(_) | Infer(FloatVar(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Float(_) | Infer(FloatVar(_)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_trait(&self) -> bool {
|
||||
match self.kind() {
|
||||
Dynamic(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Dynamic(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -2031,52 +1991,32 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_closure(&self) -> bool {
|
||||
match self.kind() {
|
||||
Closure(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Closure(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_generator(&self) -> bool {
|
||||
match self.kind() {
|
||||
Generator(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Generator(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_integral(&self) -> bool {
|
||||
match self.kind() {
|
||||
Infer(IntVar(_)) | Int(_) | Uint(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_fresh_ty(&self) -> bool {
|
||||
match self.kind() {
|
||||
Infer(FreshTy(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Infer(FreshTy(_)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_fresh(&self) -> bool {
|
||||
match self.kind() {
|
||||
Infer(FreshTy(_)) => true,
|
||||
Infer(FreshIntTy(_)) => true,
|
||||
Infer(FreshFloatTy(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_char(&self) -> bool {
|
||||
match self.kind() {
|
||||
Char => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Char)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -2086,34 +2026,22 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_signed(&self) -> bool {
|
||||
match self.kind() {
|
||||
Int(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Int(_))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ptr_sized_integral(&self) -> bool {
|
||||
match self.kind() {
|
||||
Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_machine(&self) -> bool {
|
||||
match self.kind() {
|
||||
Int(..) | Uint(..) | Float(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Int(..) | Uint(..) | Float(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_concrete_skeleton(&self) -> bool {
|
||||
match self.kind() {
|
||||
Param(_) | Infer(_) | Error(_) => false,
|
||||
_ => true,
|
||||
}
|
||||
!matches!(self.kind(), Param(_) | Infer(_) | Error(_))
|
||||
}
|
||||
|
||||
/// Returns the type and mutability of `*ty`.
|
||||
@ -2156,26 +2084,17 @@ impl<'tcx> TyS<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_fn(&self) -> bool {
|
||||
match self.kind() {
|
||||
FnDef(..) | FnPtr(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), FnDef(..) | FnPtr(_))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_fn_ptr(&self) -> bool {
|
||||
match self.kind() {
|
||||
FnPtr(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), FnPtr(_))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_impl_trait(&self) -> bool {
|
||||
match self.kind() {
|
||||
Opaque(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.kind(), Opaque(..))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1225,7 +1225,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// it. However, it works pretty well in practice. In particular,
|
||||
/// this is needed to deal with projection outlives bounds like
|
||||
///
|
||||
/// <T as Foo<'0>>::Item: '1
|
||||
/// ```ignore (internal compiler representation so lifetime syntax is invalid)
|
||||
/// <T as Foo<'0>>::Item: '1
|
||||
/// ```
|
||||
///
|
||||
/// In particular, this routine winds up being important when
|
||||
/// there are bounds like `where <T as Foo<'a>>::Item: 'b` in the
|
||||
|
@ -671,7 +671,8 @@ pub fn write_allocations<'tcx>(
|
||||
/// Dumps the size and metadata and content of an allocation to the given writer.
|
||||
/// The expectation is that the caller first prints other relevant metadata, so the exact
|
||||
/// format of this function is (*without* leading or trailing newline):
|
||||
/// ```
|
||||
///
|
||||
/// ```text
|
||||
/// size: {}, align: {}) {
|
||||
/// <bytes>
|
||||
/// }
|
||||
|
@ -31,7 +31,7 @@ crate fn lit_to_const<'tcx>(
|
||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
||||
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
||||
{
|
||||
let allocation = Allocation::from_byte_aligned_bytes(data as &Vec<u8>);
|
||||
let allocation = Allocation::from_byte_aligned_bytes(data as &[u8]);
|
||||
let allocation = tcx.intern_const_alloc(allocation);
|
||||
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
||||
}
|
||||
|
@ -181,10 +181,9 @@ pub(crate) fn emit_unescape_error(
|
||||
|
||||
if suggestion_len > 0 {
|
||||
suggestion.push('}');
|
||||
let lo = char_span.lo();
|
||||
let hi = lo + BytePos(suggestion_len as u32);
|
||||
let hi = char_span.lo() + BytePos(suggestion_len as u32);
|
||||
diag.span_suggestion(
|
||||
span.with_lo(lo).with_hi(hi),
|
||||
span.with_hi(hi),
|
||||
"format of unicode escape sequences uses braces",
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -38,13 +38,13 @@ pub struct OpaqueTypeDecl<'tcx> {
|
||||
/// then `substs` would be `['a, T]`.
|
||||
pub substs: SubstsRef<'tcx>,
|
||||
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
/// for example:
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore (incomplete snippet)
|
||||
/// type Foo = impl Baz;
|
||||
/// fn bar() -> Foo {
|
||||
/// ^^^ This is the span we are looking for!
|
||||
/// // ^^^ This is the span we are looking for!
|
||||
/// ```
|
||||
///
|
||||
/// In cases where the fn returns `(impl Trait, impl Trait)` or
|
||||
|
@ -1275,7 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
/// Report an error for a struct field expression when there are fields which aren't provided.
|
||||
///
|
||||
/// ```ignore (diagnostic)
|
||||
/// ```text
|
||||
/// error: missing field `you_can_use_this_field` in initializer of `foo::Foo`
|
||||
/// --> src/main.rs:8:5
|
||||
/// |
|
||||
@ -1327,7 +1327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
/// Report an error for a struct field expression when there are no visible fields.
|
||||
///
|
||||
/// ```ignore (diagnostic)
|
||||
/// ```text
|
||||
/// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields
|
||||
/// --> src/main.rs:8:5
|
||||
/// |
|
||||
|
@ -1381,7 +1381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Returns a diagnostic reporting a struct pattern which is missing an `..` due to
|
||||
/// inaccessible fields.
|
||||
///
|
||||
/// ```ignore (diagnostic)
|
||||
/// ```text
|
||||
/// error: pattern requires `..` due to inaccessible fields
|
||||
/// --> src/main.rs:10:9
|
||||
/// |
|
||||
@ -1431,7 +1431,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
/// Returns a diagnostic reporting a struct pattern which does not mention some fields.
|
||||
///
|
||||
/// ```ignore (diagnostic)
|
||||
/// ```text
|
||||
/// error[E0027]: pattern does not mention field `you_cant_use_this_field`
|
||||
/// --> src/main.rs:15:9
|
||||
/// |
|
||||
|
@ -98,8 +98,6 @@ pub fn spin_loop() {
|
||||
/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
|
||||
/// `black_box` could do.
|
||||
///
|
||||
/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
|
||||
///
|
||||
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
|
||||
/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
|
||||
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
|
||||
@ -108,6 +106,8 @@ pub fn spin_loop() {
|
||||
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
|
||||
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
|
||||
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
|
||||
///
|
||||
/// [`std::convert::identity`]: crate::convert::identity
|
||||
#[cfg_attr(not(miri), inline)]
|
||||
#[cfg_attr(miri, inline(never))]
|
||||
#[unstable(feature = "test", issue = "50297")]
|
||||
|
@ -246,6 +246,14 @@ impl<T> MaybeUninit<T> {
|
||||
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
|
||||
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let v: MaybeUninit<Vec<u8>> = MaybeUninit::new(vec![42]);
|
||||
/// ```
|
||||
///
|
||||
/// [`assume_init`]: MaybeUninit::assume_init
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
|
||||
@ -259,9 +267,15 @@ impl<T> MaybeUninit<T> {
|
||||
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
|
||||
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
|
||||
///
|
||||
/// See the [type-level documentation][type] for some examples.
|
||||
/// See the [type-level documentation][MaybeUninit] for some examples.
|
||||
///
|
||||
/// [type]: union.MaybeUninit.html
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let v: MaybeUninit<String> = MaybeUninit::uninit();
|
||||
/// ```
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
|
||||
#[inline(always)]
|
||||
|
@ -6,11 +6,34 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::convert::TryInto as _;
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
use crate::str::FromStr;
|
||||
|
||||
trait ReadNumberHelper: crate::marker::Sized {
|
||||
const ZERO: Self;
|
||||
fn checked_mul(&self, other: u32) -> Option<Self>;
|
||||
fn checked_add(&self, other: u32) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! impl_helper {
|
||||
($($t:ty)*) => ($(impl ReadNumberHelper for $t {
|
||||
const ZERO: Self = 0;
|
||||
#[inline]
|
||||
fn checked_mul(&self, other: u32) -> Option<Self> {
|
||||
Self::checked_mul(*self, other.try_into().ok()?)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_add(&self, other: u32) -> Option<Self> {
|
||||
Self::checked_add(*self, other.try_into().ok()?)
|
||||
}
|
||||
})*)
|
||||
}
|
||||
|
||||
impl_helper! { u8 u16 }
|
||||
|
||||
struct Parser<'a> {
|
||||
// parsing as ASCII, so can use byte array
|
||||
state: &'a [u8],
|
||||
@ -21,10 +44,6 @@ impl<'a> Parser<'a> {
|
||||
Parser { state: input.as_bytes() }
|
||||
}
|
||||
|
||||
fn is_eof(&self) -> bool {
|
||||
self.state.is_empty()
|
||||
}
|
||||
|
||||
/// Run a parser, and restore the pre-parse state if it fails
|
||||
fn read_atomically<T, F>(&mut self, inner: F) -> Option<T>
|
||||
where
|
||||
@ -40,26 +59,19 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Run a parser, but fail if the entire input wasn't consumed.
|
||||
/// Doesn't run atomically.
|
||||
fn read_till_eof<T, F>(&mut self, inner: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(&mut Parser<'_>) -> Option<T>,
|
||||
{
|
||||
inner(self).filter(|_| self.is_eof())
|
||||
}
|
||||
|
||||
/// Same as read_till_eof, but returns a Result<AddrParseError> on failure
|
||||
fn parse_with<T, F>(&mut self, inner: F) -> Result<T, AddrParseError>
|
||||
where
|
||||
F: FnOnce(&mut Parser<'_>) -> Option<T>,
|
||||
{
|
||||
self.read_till_eof(inner).ok_or(AddrParseError(()))
|
||||
let result = inner(self);
|
||||
if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(()))
|
||||
}
|
||||
|
||||
/// Read the next character from the input
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
self.state.split_first().map(|(&b, tail)| {
|
||||
self.state = tail;
|
||||
b as char
|
||||
char::from(b)
|
||||
})
|
||||
}
|
||||
|
||||
@ -84,25 +96,26 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
// Read a single digit in the given radix. For instance, 0-9 in radix 10;
|
||||
// 0-9A-F in radix 16.
|
||||
fn read_digit(&mut self, radix: u32) -> Option<u32> {
|
||||
self.read_atomically(move |p| p.read_char()?.to_digit(radix))
|
||||
}
|
||||
|
||||
// Read a number off the front of the input in the given radix, stopping
|
||||
// at the first non-digit character or eof. Fails if the number has more
|
||||
// digits than max_digits, or the value is >= upto, or if there is no number.
|
||||
fn read_number(&mut self, radix: u32, max_digits: u32, upto: u32) -> Option<u32> {
|
||||
// digits than max_digits or if there is no number.
|
||||
fn read_number<T: ReadNumberHelper>(
|
||||
&mut self,
|
||||
radix: u32,
|
||||
max_digits: Option<usize>,
|
||||
) -> Option<T> {
|
||||
self.read_atomically(move |p| {
|
||||
let mut result = 0;
|
||||
let mut result = T::ZERO;
|
||||
let mut digit_count = 0;
|
||||
|
||||
while let Some(digit) = p.read_digit(radix) {
|
||||
result = (result * radix) + digit;
|
||||
while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
|
||||
result = result.checked_mul(radix)?;
|
||||
result = result.checked_add(digit)?;
|
||||
digit_count += 1;
|
||||
if digit_count > max_digits || result >= upto {
|
||||
return None;
|
||||
if let Some(max_digits) = max_digits {
|
||||
if digit_count > max_digits {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,7 +129,7 @@ impl<'a> Parser<'a> {
|
||||
let mut groups = [0; 4];
|
||||
|
||||
for (i, slot) in groups.iter_mut().enumerate() {
|
||||
*slot = p.read_separator('.', i, |p| p.read_number(10, 3, 0x100))? as u8;
|
||||
*slot = p.read_separator('.', i, |p| p.read_number(10, None))?;
|
||||
}
|
||||
|
||||
Some(groups.into())
|
||||
@ -140,17 +153,17 @@ impl<'a> Parser<'a> {
|
||||
let ipv4 = p.read_separator(':', i, |p| p.read_ipv4_addr());
|
||||
|
||||
if let Some(v4_addr) = ipv4 {
|
||||
let octets = v4_addr.octets();
|
||||
groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
|
||||
groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
|
||||
let [one, two, three, four] = v4_addr.octets();
|
||||
groups[i + 0] = u16::from_be_bytes([one, two]);
|
||||
groups[i + 1] = u16::from_be_bytes([three, four]);
|
||||
return (i + 2, true);
|
||||
}
|
||||
}
|
||||
|
||||
let group = p.read_separator(':', i, |p| p.read_number(16, 4, 0x10000));
|
||||
let group = p.read_separator(':', i, |p| p.read_number(16, Some(4)));
|
||||
|
||||
match group {
|
||||
Some(g) => *slot = g as u16,
|
||||
Some(g) => *slot = g,
|
||||
None => return (i, false),
|
||||
}
|
||||
}
|
||||
@ -195,12 +208,11 @@ impl<'a> Parser<'a> {
|
||||
self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6))
|
||||
}
|
||||
|
||||
/// Read a : followed by a port in base 10
|
||||
/// Read a : followed by a port in base 10.
|
||||
fn read_port(&mut self) -> Option<u16> {
|
||||
self.read_atomically(|p| {
|
||||
let _ = p.read_given_char(':')?;
|
||||
let port = p.read_number(10, 5, 0x10000)?;
|
||||
Some(port as u16)
|
||||
p.read_number(10, None)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,11 @@ pub use core::time::Duration;
|
||||
/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
|
||||
///
|
||||
/// **Disclaimer:** These system calls might change over time.
|
||||
///
|
||||
/// > Note: mathematical operations like [`add`] may panic if the underlying
|
||||
/// > structure cannot represent the new point in time.
|
||||
///
|
||||
/// [`add`]: Instant::add
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub struct Instant(time::Instant);
|
||||
@ -174,6 +179,11 @@ pub struct Instant(time::Instant);
|
||||
/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime
|
||||
///
|
||||
/// **Disclaimer:** These system calls might change over time.
|
||||
///
|
||||
/// > Note: mathematical operations like [`add`] may panic if the underlying
|
||||
/// > structure cannot represent the new point in time.
|
||||
///
|
||||
/// [`add`]: SystemTime::add
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub struct SystemTime(time::SystemTime);
|
||||
|
@ -7,6 +7,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
## [Non-breaking changes since the last major version]
|
||||
|
||||
- `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473)
|
||||
- The default bootstrap profiles are now located at `bootstrap/defaults/config.$PROFILE.toml` (previously they were located at `bootstrap/defaults/config.toml.$PROFILE`) [#77558](https://github.com/rust-lang/rust/pull/77558)
|
||||
|
||||
|
||||
## [Version 2] - 2020-09-25
|
||||
|
||||
|
@ -574,7 +574,7 @@ impl Config {
|
||||
include_path.push("src");
|
||||
include_path.push("bootstrap");
|
||||
include_path.push("defaults");
|
||||
include_path.push(format!("config.toml.{}", include));
|
||||
include_path.push(format!("config.{}.toml", include));
|
||||
let included_toml = get_toml(&include_path);
|
||||
toml.merge(included_toml);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn setup(src_path: &Path, include_name: &str) {
|
||||
file.display()
|
||||
);
|
||||
println!(
|
||||
"note: this will use the configuration in {}/src/bootstrap/defaults/config.toml.{}",
|
||||
"note: this will use the configuration in {}/src/bootstrap/defaults/config.{}.toml",
|
||||
src_path.display(),
|
||||
include_name
|
||||
);
|
||||
@ -36,7 +36,7 @@ pub fn setup(src_path: &Path, include_name: &str) {
|
||||
t!(fs::write(path, settings));
|
||||
|
||||
let include_path =
|
||||
format!("{}/src/bootstrap/defaults/config.toml.{}", src_path.display(), include_name);
|
||||
format!("{}/src/bootstrap/defaults/config.{}.toml", src_path.display(), include_name);
|
||||
println!("`x.py` will now use the configuration at {}", include_path);
|
||||
|
||||
let suggestions = match include_name {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
The features listed on this page fall outside the rest of the main categories.
|
||||
|
||||
## `#[cfg(doc)]`: Documenting platform-/feature-specific information
|
||||
## `#[cfg(doc)]`: Documenting platform-specific or feature-specific information
|
||||
|
||||
For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things
|
||||
from the host target are available (or from the given `--target` if present), and everything else is
|
||||
@ -17,7 +17,7 @@ with other `#[cfg]` filters on it, you can write something like `#[cfg(any(windo
|
||||
This will preserve the item either when built normally on Windows, or when being documented
|
||||
anywhere.
|
||||
|
||||
Please note that this feature is not passed to doctests.
|
||||
Please note that this `cfg` is not passed to doctests.
|
||||
|
||||
Example:
|
||||
|
||||
@ -33,6 +33,40 @@ pub struct UnixToken;
|
||||
Here, the respective tokens can only be used by dependent crates on their respective platforms, but
|
||||
they will both appear in documentation.
|
||||
|
||||
### Interactions between platform-specific docs
|
||||
|
||||
Rustdoc does not have a magic way to compile documentation 'as-if' you'd run it once for each
|
||||
platform (such a magic wand has been called the ['holy grail of rustdoc'][#1998]). Instead,
|
||||
it sees *all* of your code at once, the same way the Rust compiler would if you passed it
|
||||
`--cfg doc`. However, Rustdoc has a trick up its sleeve to handle platform-specific code if it
|
||||
*does* receive it.
|
||||
|
||||
To document your crate, Rustdoc only needs to know the public signature of your functions.
|
||||
In particular, it doesn't have to know how any of your functions are implemented, so it ignores
|
||||
all type errors and name resolution errors with function bodies. Note that this does *not*
|
||||
work for anything outside a function body: since Rustdoc documents your types, it has to
|
||||
know what those types are! For example, this code will work regardless of the platform:
|
||||
|
||||
<!-- `ignore` because doc-tests are run with `rustc`, not `rustdoc` -->
|
||||
```ignore
|
||||
pub fn f() {
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
}
|
||||
```
|
||||
|
||||
but this will not, because the unknown type is part of the function signature:
|
||||
|
||||
```ignore
|
||||
pub fn f() -> std::os::windows::ffi::EncodeWide<'static> {
|
||||
unimplemented!()
|
||||
}
|
||||
```
|
||||
|
||||
For a more realistic example of code this allows, see [the rustdoc test suite][realistic-async].
|
||||
|
||||
[#1998]: https://github.com/rust-lang/rust/issues/1998
|
||||
[realistic-async]: https://github.com/rust-lang/rust/blob/b146000e910ccd60bdcde89363cb6aa14ecc0d95/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs
|
||||
|
||||
## Add aliases for an item in documentation search
|
||||
|
||||
This feature allows you to add alias(es) to an item when using the `rustdoc` search through the
|
||||
|
@ -43,28 +43,16 @@ plain text.
|
||||
These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler
|
||||
and enabled with a `#![feature(...)]` attribute in your crate.
|
||||
|
||||
### Documenting platform-/feature-specific information
|
||||
### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present
|
||||
|
||||
Because of the way Rustdoc documents a crate, the documentation it creates is specific to the target
|
||||
rustc compiles for. Anything that's specific to any other target is dropped via `#[cfg]` attribute
|
||||
processing early in the compilation process. However, Rustdoc has a trick up its sleeve to handle
|
||||
platform-specific code if it *does* receive it.
|
||||
You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on.
|
||||
This has two effects:
|
||||
|
||||
Because Rustdoc doesn't need to fully compile a crate to binary, it replaces function bodies with
|
||||
`loop {}` to prevent having to process more than necessary. This means that any code within a
|
||||
function that requires platform-specific pieces is ignored. Combined with a special attribute,
|
||||
`#[doc(cfg(...))]`, you can tell Rustdoc exactly which platform something is supposed to run on,
|
||||
ensuring that doctests are only run on the appropriate platforms.
|
||||
|
||||
The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders documentation for that
|
||||
item, it will be accompanied by a banner explaining that the item is only available on certain
|
||||
platforms.
|
||||
|
||||
For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently
|
||||
running on. To aid this, Rustdoc sets the flag `#[cfg(doc)]` when running on your crate.
|
||||
Combining this with the target platform of a given item allows it to appear when building your crate
|
||||
normally on that platform, as well as when building documentation anywhere.
|
||||
1. doctests will only run on the appropriate platforms, and
|
||||
2. When Rustdoc renders documentation for that item, it will be accompanied by a banner explaining
|
||||
that the item is only available on certain platforms.
|
||||
|
||||
`#[doc(cfg)]` is intended to be used alongside [`#[cfg(doc)]`][cfg-doc].
|
||||
For example, `#[cfg(any(windows, doc))]` will preserve the item either on Windows or during the
|
||||
documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that
|
||||
the item is supposed to be used on Windows. For example:
|
||||
@ -81,6 +69,12 @@ pub struct WindowsToken;
|
||||
#[cfg(any(unix, doc))]
|
||||
#[doc(cfg(unix))]
|
||||
pub struct UnixToken;
|
||||
|
||||
/// Token struct that is only available with the `serde` feature
|
||||
#[cfg(feature = "serde")]
|
||||
#[doc(cfg(feature = "serde"))]
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct SerdeToken;
|
||||
```
|
||||
|
||||
In this sample, the tokens will only appear on their respective platforms, but they will both appear
|
||||
@ -90,6 +84,7 @@ in documentation.
|
||||
`#![feature(doc_cfg)]` feature gate. For more information, see [its chapter in the Unstable
|
||||
Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
|
||||
|
||||
[cfg-doc]: ./advanced-features.md
|
||||
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
|
||||
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
|
||||
|
||||
|
@ -2,9 +2,7 @@ error: incorrect unicode escape sequence
|
||||
--> $DIR/format-string-error-2.rs:77:20
|
||||
|
|
||||
LL | println!("\x7B}\u8 {", 1);
|
||||
| ^^-
|
||||
| |
|
||||
| help: format of unicode escape sequences uses braces: `\u{8}`
|
||||
| ^^^ help: format of unicode escape sequences uses braces: `\u{8}`
|
||||
|
||||
error: invalid format string: expected `'}'`, found `'a'`
|
||||
--> $DIR/format-string-error-2.rs:5:5
|
||||
|
7
src/test/ui/hygiene/auxiliary/def-site-async-await.rs
Normal file
7
src/test/ui/hygiene/auxiliary/def-site-async-await.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// edition:2018
|
||||
|
||||
extern crate opaque_hygiene;
|
||||
|
||||
pub async fn serve() {
|
||||
opaque_hygiene::make_it!();
|
||||
}
|
21
src/test/ui/hygiene/auxiliary/opaque-hygiene.rs
Normal file
21
src/test/ui/hygiene/auxiliary/opaque-hygiene.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// force-host
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![feature(proc_macro_quote)]
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::{TokenStream, quote};
|
||||
|
||||
#[proc_macro]
|
||||
pub fn make_it(input: TokenStream) -> TokenStream {
|
||||
// `quote!` applies def-site hygiene
|
||||
quote! {
|
||||
trait Foo {
|
||||
fn my_fn(&self) {}
|
||||
}
|
||||
|
||||
impl<T> Foo for T {}
|
||||
"a".my_fn();
|
||||
}
|
||||
}
|
19
src/test/ui/hygiene/issue-77523-def-site-async-await.rs
Normal file
19
src/test/ui/hygiene/issue-77523-def-site-async-await.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// build-pass
|
||||
// aux-build:opaque-hygiene.rs
|
||||
// aux-build:def-site-async-await.rs
|
||||
|
||||
// Regression test for issue #77523
|
||||
// Tests that we don't ICE when an unusual combination
|
||||
// of def-site hygiene and cross-crate monomorphization occurs.
|
||||
|
||||
extern crate def_site_async_await;
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
fn mk_ctxt() -> std::task::Context<'static> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Box::pin(def_site_async_await::serve()).as_mut().poll(&mut mk_ctxt());
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
// This test is checking that you cannot override a `forbid` by adding in other
|
||||
// attributes later in the same scope. (We already ensure that you cannot
|
||||
// override it in nested scopes).
|
||||
|
||||
// If you turn off deduplicate diagnostics (which rustc turns on by default but
|
||||
// compiletest turns off when it runs ui tests), then the errors are
|
||||
// (unfortunately) repeated here because the checking is done as we read in the
|
||||
// errors, and curretly that happens two or three different times, depending on
|
||||
// compiler flags.
|
||||
//
|
||||
// I decided avoiding the redundant output was not worth the time in engineering
|
||||
// effort for bug like this, which 1. end users are unlikely to run into in the
|
||||
// first place, and 2. they won't see the redundant output anyway.
|
||||
|
||||
// compile-flags: -Z deduplicate-diagnostics=yes
|
||||
|
||||
fn forbid_first(num: i32) -> i32 {
|
||||
#![forbid(unused)]
|
||||
#![deny(unused)]
|
||||
//~^ ERROR: deny(unused) incompatible with previous forbid in same scope [E0453]
|
||||
#![warn(unused)]
|
||||
//~^ ERROR: warn(unused) incompatible with previous forbid in same scope [E0453]
|
||||
#![allow(unused)]
|
||||
//~^ ERROR: allow(unused) incompatible with previous forbid in same scope [E0453]
|
||||
|
||||
num * num
|
||||
}
|
||||
|
||||
fn forbid_last(num: i32) -> i32 {
|
||||
#![deny(unused)]
|
||||
#![warn(unused)]
|
||||
#![allow(unused)]
|
||||
#![forbid(unused)]
|
||||
|
||||
num * num
|
||||
}
|
||||
|
||||
fn forbid_multiple(num: i32) -> i32 {
|
||||
#![forbid(unused)]
|
||||
#![forbid(unused)]
|
||||
|
||||
num * num
|
||||
}
|
||||
|
||||
fn main() {
|
||||
forbid_first(10);
|
||||
forbid_last(10);
|
||||
forbid_multiple(10);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
error[E0453]: deny(unused) incompatible with previous forbid in same scope
|
||||
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:19:13
|
||||
|
|
||||
LL | #![forbid(unused)]
|
||||
| ------ `forbid` level set here
|
||||
LL | #![deny(unused)]
|
||||
| ^^^^^^
|
||||
|
||||
error[E0453]: warn(unused) incompatible with previous forbid in same scope
|
||||
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
|
||||
|
|
||||
LL | #![forbid(unused)]
|
||||
| ------ `forbid` level set here
|
||||
...
|
||||
LL | #![warn(unused)]
|
||||
| ^^^^^^
|
||||
|
||||
error[E0453]: allow(unused) incompatible with previous forbid in same scope
|
||||
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:23:14
|
||||
|
|
||||
LL | #![forbid(unused)]
|
||||
| ------ `forbid` level set here
|
||||
...
|
||||
LL | #![allow(unused)]
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0453`.
|
@ -80,9 +80,9 @@ error: incorrect unicode escape sequence
|
||||
--> $DIR/issue-23620-invalid-escapes.rs:32:14
|
||||
|
|
||||
LL | let _ = "\u8f";
|
||||
| ^^--
|
||||
| |
|
||||
| help: format of unicode escape sequences uses braces: `\u{8f}`
|
||||
| ^^^-
|
||||
| |
|
||||
| help: format of unicode escape sequences uses braces: `\u{8f}`
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
|
@ -8,8 +8,8 @@ extern "C" {
|
||||
#[allow(unused_mut)] a: i32,
|
||||
#[cfg(something)] b: i32,
|
||||
#[cfg_attr(something, cfg(nothing))] c: i32,
|
||||
#[deny(unused_mut)] d: i32,
|
||||
#[forbid(unused_mut)] #[warn(unused_mut)] ...
|
||||
#[forbid(unused_mut)] d: i32,
|
||||
#[deny(unused_mut)] #[warn(unused_mut)] ...
|
||||
);
|
||||
}
|
||||
|
||||
@ -17,16 +17,16 @@ type FnType = fn(
|
||||
#[allow(unused_mut)] a: i32,
|
||||
#[cfg(something)] b: i32,
|
||||
#[cfg_attr(something, cfg(nothing))] c: i32,
|
||||
#[deny(unused_mut)] d: i32,
|
||||
#[forbid(unused_mut)] #[warn(unused_mut)] e: i32
|
||||
#[forbid(unused_mut)] d: i32,
|
||||
#[deny(unused_mut)] #[warn(unused_mut)] e: i32
|
||||
);
|
||||
|
||||
pub fn foo(
|
||||
#[allow(unused_mut)] a: i32,
|
||||
#[cfg(something)] b: i32,
|
||||
#[cfg_attr(something, cfg(nothing))] c: i32,
|
||||
#[deny(unused_mut)] d: i32,
|
||||
#[forbid(unused_mut)] #[warn(unused_mut)] _e: i32
|
||||
#[forbid(unused_mut)] d: i32,
|
||||
#[deny(unused_mut)] #[warn(unused_mut)] _e: i32
|
||||
) {}
|
||||
|
||||
// self
|
||||
|
@ -155,7 +155,7 @@ pub fn lit_to_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
|
||||
match *lit {
|
||||
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
|
||||
LitKind::Byte(b) => Constant::Int(u128::from(b)),
|
||||
LitKind::ByteStr(ref s) => Constant::Binary(Lrc::from(s.as_slice())),
|
||||
LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)),
|
||||
LitKind::Char(c) => Constant::Char(c),
|
||||
LitKind::Int(n, _) => Constant::Int(n),
|
||||
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
|
||||
|
@ -3,7 +3,6 @@
|
||||
// Test that the whole restriction group is not enabled
|
||||
#![warn(clippy::restriction)]
|
||||
#![deny(clippy::restriction)]
|
||||
#![forbid(clippy::restriction)]
|
||||
#![allow(clippy::missing_docs_in_private_items, clippy::panic, clippy::unreachable)]
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> $DIR/attrs.rs:9:1
|
||||
--> $DIR/attrs.rs:8:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | #[inline(always)]
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
|
||||
error: the since field must contain a semver-compliant version
|
||||
--> $DIR/attrs.rs:29:14
|
||||
--> $DIR/attrs.rs:28:14
|
||||
|
|
||||
LL | #[deprecated(since = "forever")]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -15,7 +15,7 @@ LL | #[deprecated(since = "forever")]
|
||||
= note: `-D clippy::deprecated-semver` implied by `-D warnings`
|
||||
|
||||
error: the since field must contain a semver-compliant version
|
||||
--> $DIR/attrs.rs:32:14
|
||||
--> $DIR/attrs.rs:31:14
|
||||
|
|
||||
LL | #[deprecated(since = "1")]
|
||||
| ^^^^^^^^^^^
|
||||
@ -37,13 +37,5 @@ LL | #![deny(clippy::restriction)]
|
||||
|
|
||||
= help: try enabling only the lints you really need
|
||||
|
||||
error: restriction lints are not meant to be all enabled
|
||||
--> $DIR/attrs.rs:6:11
|
||||
|
|
||||
LL | #![forbid(clippy::restriction)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try enabling only the lints you really need
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -3,6 +3,7 @@ allow-unauthenticated = [
|
||||
"C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*",
|
||||
"D-*",
|
||||
"requires-nightly",
|
||||
"regression-*",
|
||||
# I-* without I-nominated
|
||||
"I-*", "!I-nominated",
|
||||
"AsyncAwait-OnDeck",
|
||||
|
Loading…
Reference in New Issue
Block a user