mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
Auto merge of #118602 - TaKO8Ki:rollup-njcouns, r=TaKO8Ki
Rollup of 5 pull requests Successful merges: - #118495 (Restrict what symbols can be used in `#[diagnostic::on_unimplemented]` format strings) - #118540 (codegen, miri: fix computing the offset of an unsized field in a packed struct) - #118551 (more targeted errors when extern types end up in places they should not) - #118573 (rustc: Harmonize `DefKind` and `DefPathData`) - #118586 (Improve example in `slice::windows()` doc) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e281163dc8
@ -14,8 +14,8 @@ use rustc_ast::*;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::asm;
|
||||
use std::collections::hash_map::Entry;
|
||||
@ -227,7 +227,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
*op_sp,
|
||||
);
|
||||
|
@ -13,10 +13,9 @@ use rustc_ast::*;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{DesugaringKind, Span};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
@ -376,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
f.span,
|
||||
);
|
||||
|
@ -3,7 +3,6 @@ use super::ResolverAstLoweringExt;
|
||||
use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
|
||||
use super::{FnDeclKind, LoweringContext, ParamMode};
|
||||
|
||||
use hir::definitions::DefPathData;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::AssocCtxt;
|
||||
use rustc_ast::*;
|
||||
@ -1367,7 +1366,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let def_id = self.create_def(
|
||||
self.local_def_id(parent_node_id),
|
||||
param_node_id,
|
||||
DefPathData::TypeNs(sym::host),
|
||||
sym::host,
|
||||
DefKind::ConstParam,
|
||||
span,
|
||||
);
|
||||
@ -1427,13 +1426,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
if let Some((span, hir_id, def_id)) = host_param_parts {
|
||||
let const_node_id = self.next_node_id();
|
||||
let anon_const = self.create_def(
|
||||
def_id,
|
||||
const_node_id,
|
||||
DefPathData::AnonConst,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
let anon_const =
|
||||
self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
|
||||
let const_id = self.next_id();
|
||||
let const_expr_id = self.next_id();
|
||||
|
@ -58,7 +58,6 @@ use rustc_errors::{DiagnosticArgFromDisplay, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::{
|
||||
@ -499,20 +498,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
&mut self,
|
||||
parent: LocalDefId,
|
||||
node_id: ast::NodeId,
|
||||
data: DefPathData,
|
||||
name: Symbol,
|
||||
def_kind: DefKind,
|
||||
span: Span,
|
||||
) -> LocalDefId {
|
||||
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
|
||||
assert!(
|
||||
self.opt_local_def_id(node_id).is_none(),
|
||||
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
|
||||
"adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
|
||||
node_id,
|
||||
data,
|
||||
def_kind,
|
||||
self.tcx.hir().def_key(self.local_def_id(node_id)),
|
||||
);
|
||||
|
||||
let def_id = self.tcx.at(span).create_def(parent, data, def_kind).def_id();
|
||||
let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
|
||||
|
||||
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
|
||||
self.resolver.node_id_to_def_id.insert(node_id, def_id);
|
||||
@ -809,7 +808,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let _def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
param,
|
||||
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
||||
kw::UnderscoreLifetime,
|
||||
DefKind::LifetimeParam,
|
||||
ident.span,
|
||||
);
|
||||
@ -1227,7 +1226,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let def_id = self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
@ -1465,7 +1464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
*def_node_id,
|
||||
DefPathData::TypeNs(ident.name),
|
||||
ident.name,
|
||||
DefKind::TyParam,
|
||||
span,
|
||||
);
|
||||
@ -1619,7 +1618,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let opaque_ty_def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
opaque_ty_node_id,
|
||||
DefPathData::ImplTrait,
|
||||
kw::Empty,
|
||||
DefKind::OpaqueTy,
|
||||
opaque_ty_span,
|
||||
);
|
||||
@ -1674,7 +1673,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let duplicated_lifetime_def_id = self.create_def(
|
||||
opaque_ty_def_id,
|
||||
duplicated_lifetime_node_id,
|
||||
DefPathData::LifetimeNs(lifetime.ident.name),
|
||||
lifetime.ident.name,
|
||||
DefKind::LifetimeParam,
|
||||
lifetime.ident.span,
|
||||
);
|
||||
@ -2549,7 +2548,7 @@ impl<'hir> GenericArgsCtor<'hir> {
|
||||
let def_id = lcx.create_def(
|
||||
lcx.current_hir_id_owner.def_id,
|
||||
id,
|
||||
DefPathData::AnonConst,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
|
@ -489,6 +489,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
|
||||
if place.layout.is_unsized() {
|
||||
let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {});
|
||||
if matches!(tail.kind(), ty::Foreign(..)) {
|
||||
// Unsized locals and, at least conceptually, even unsized arguments must be copied
|
||||
// around, which requires dynamically determining their size. Therefore, we cannot
|
||||
// allow `extern` types here. Consult t-opsem before removing this check.
|
||||
panic!("unsized locals must not be `extern` types");
|
||||
}
|
||||
}
|
||||
assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
|
||||
|
||||
if place.layout.is_zst() {
|
||||
|
@ -594,7 +594,7 @@ fn push_unqualified_item_name(
|
||||
DefPathData::CrateRoot => {
|
||||
output.push_str(tcx.crate_name(def_id.krate).as_str());
|
||||
}
|
||||
DefPathData::ClosureExpr => {
|
||||
DefPathData::Closure => {
|
||||
let label = coroutine_kind_label(tcx.coroutine_kind(def_id));
|
||||
|
||||
push_disambiguated_special_name(
|
||||
|
@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
||||
// value is through `undef`/`poison`, and the store itself is useless.
|
||||
}
|
||||
OperandValue::Ref(r, None, source_align) => {
|
||||
assert!(dest.layout.is_sized(), "cannot directly store unsized values");
|
||||
if flags.contains(MemFlags::NONTEMPORAL) {
|
||||
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
||||
let ty = bx.backend_type(dest.layout);
|
||||
|
@ -143,7 +143,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
// Simple cases, which don't need DST adjustment:
|
||||
// * no metadata available - just log the case
|
||||
// * known alignment - sized types, `[T]`, `str` or a foreign type
|
||||
// * packed struct - there is no alignment padding
|
||||
// Note that looking at `field.align` is incorrect since that is not necessarily equal
|
||||
// to the dynamic alignment of the type.
|
||||
match field.ty.kind() {
|
||||
_ if self.llextra.is_none() => {
|
||||
debug!(
|
||||
@ -154,14 +155,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
}
|
||||
_ if field.is_sized() => return simple(),
|
||||
ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
|
||||
ty::Adt(def, _) => {
|
||||
if def.repr().packed() {
|
||||
// FIXME(eddyb) generalize the adjustment when we
|
||||
// start supporting packing to larger alignments.
|
||||
assert_eq!(self.layout.align.abi.bytes(), 1);
|
||||
return simple();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -186,7 +179,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
let unaligned_offset = bx.cx().const_usize(offset.bytes());
|
||||
|
||||
// Get the alignment of the field
|
||||
let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
|
||||
let (_, mut unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
|
||||
|
||||
// For packed types, we need to cap alignment.
|
||||
if let ty::Adt(def, _) = self.layout.ty.kind()
|
||||
&& let Some(packed) = def.repr().pack
|
||||
{
|
||||
let packed = bx.const_usize(packed.bytes());
|
||||
let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed);
|
||||
unsized_align = bx.select(cmp, unsized_align, packed)
|
||||
}
|
||||
|
||||
// Bump the unaligned offset up to the appropriate alignment
|
||||
let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
|
||||
|
@ -282,9 +282,7 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
|
||||
impl<'tcx> fmt::Display for FrameInfo<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ty::tls::with(|tcx| {
|
||||
if tcx.def_key(self.instance.def_id()).disambiguated_data.data
|
||||
== DefPathData::ClosureExpr
|
||||
{
|
||||
if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
|
||||
write!(f, "inside closure")
|
||||
} else {
|
||||
// Note: this triggers a `good_path_delayed_bug` state, which means that if we ever
|
||||
@ -299,7 +297,7 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
|
||||
impl<'tcx> FrameInfo<'tcx> {
|
||||
pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
|
||||
let span = self.span;
|
||||
if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr {
|
||||
if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
|
||||
errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
|
||||
} else {
|
||||
let instance = format!("{}", self.instance);
|
||||
|
@ -163,7 +163,17 @@ where
|
||||
// With custom DSTS, this *will* execute user-defined code, but the same
|
||||
// happens at run-time so that's okay.
|
||||
match self.size_and_align_of(&base_meta, &field_layout)? {
|
||||
Some((_, align)) => (base_meta, offset.align_to(align)),
|
||||
Some((_, align)) => {
|
||||
// For packed types, we need to cap alignment.
|
||||
let align = if let ty::Adt(def, _) = base.layout().ty.kind()
|
||||
&& let Some(packed) = def.repr().pack
|
||||
{
|
||||
align.min(packed)
|
||||
} else {
|
||||
align
|
||||
};
|
||||
(base_meta, offset.align_to(align))
|
||||
}
|
||||
None => {
|
||||
// For unsized types with an extern type tail we perform no adjustments.
|
||||
// NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend.
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::definitions::DefPathData;
|
||||
use crate::hir;
|
||||
|
||||
use rustc_ast as ast;
|
||||
@ -45,6 +46,7 @@ pub enum NonMacroAttrKind {
|
||||
}
|
||||
|
||||
/// What kind of definition something is; e.g., `mod` vs `struct`.
|
||||
/// `enum DefPathData` may need to be updated if a new variant is added here.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
|
||||
pub enum DefKind {
|
||||
// Type namespace
|
||||
@ -221,6 +223,41 @@ impl DefKind {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_path_data(self, name: Symbol) -> DefPathData {
|
||||
match self {
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::TyParam
|
||||
| DefKind::ExternCrate => DefPathData::TypeNs(name),
|
||||
DefKind::Fn
|
||||
| DefKind::Const
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Static(..)
|
||||
| DefKind::AssocFn
|
||||
| DefKind::AssocConst
|
||||
| DefKind::Field => DefPathData::ValueNs(name),
|
||||
DefKind::Macro(..) => DefPathData::MacroNs(name),
|
||||
DefKind::LifetimeParam => DefPathData::LifetimeNs(name),
|
||||
DefKind::Ctor(..) => DefPathData::Ctor,
|
||||
DefKind::Use => DefPathData::Use,
|
||||
DefKind::ForeignMod => DefPathData::ForeignMod,
|
||||
DefKind::AnonConst => DefPathData::AnonConst,
|
||||
DefKind::InlineConst => DefPathData::AnonConst,
|
||||
DefKind::OpaqueTy => DefPathData::OpaqueTy,
|
||||
DefKind::GlobalAsm => DefPathData::GlobalAsm,
|
||||
DefKind::Impl { .. } => DefPathData::Impl,
|
||||
DefKind::Closure => DefPathData::Closure,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_fn_like(self) -> bool {
|
||||
matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure)
|
||||
|
@ -246,6 +246,7 @@ impl DefPath {
|
||||
}
|
||||
}
|
||||
|
||||
/// New variants should only be added in synchronization with `enum DefKind`.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
pub enum DefPathData {
|
||||
// Root: these should only be used for the root nodes, because
|
||||
@ -271,7 +272,7 @@ pub enum DefPathData {
|
||||
/// Something in the lifetime namespace.
|
||||
LifetimeNs(Symbol),
|
||||
/// A closure expression.
|
||||
ClosureExpr,
|
||||
Closure,
|
||||
|
||||
// Subportions of items:
|
||||
/// Implicit constructor for a unit or tuple-like struct or enum variant.
|
||||
@ -280,9 +281,7 @@ pub enum DefPathData {
|
||||
AnonConst,
|
||||
/// An existential `impl Trait` type node.
|
||||
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
|
||||
ImplTrait,
|
||||
/// `impl Trait` generated associated type node.
|
||||
ImplTraitAssocTy,
|
||||
OpaqueTy,
|
||||
}
|
||||
|
||||
impl Definitions {
|
||||
@ -403,16 +402,17 @@ impl DefPathData {
|
||||
pub fn get_opt_name(&self) -> Option<Symbol> {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) if name == kw::Empty => None,
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
|
||||
|
||||
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
|
||||
| ImplTrait | ImplTraitAssocTy => None,
|
||||
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
|
||||
| OpaqueTy => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> DefPathDataName {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) if name == kw::Empty => DefPathDataName::Anon { namespace: sym::opaque },
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
|
||||
DefPathDataName::Named(name)
|
||||
}
|
||||
@ -422,10 +422,10 @@ impl DefPathData {
|
||||
ForeignMod => DefPathDataName::Anon { namespace: kw::Extern },
|
||||
Use => DefPathDataName::Anon { namespace: kw::Use },
|
||||
GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm },
|
||||
ClosureExpr => DefPathDataName::Anon { namespace: sym::closure },
|
||||
Closure => DefPathDataName::Anon { namespace: sym::closure },
|
||||
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
|
||||
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
|
||||
ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque },
|
||||
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -977,7 +977,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
||||
pub fn create_def(
|
||||
self,
|
||||
parent: LocalDefId,
|
||||
data: hir::definitions::DefPathData,
|
||||
name: Symbol,
|
||||
def_kind: DefKind,
|
||||
) -> TyCtxtFeed<'tcx, LocalDefId> {
|
||||
// This function modifies `self.definitions` using a side-effect.
|
||||
@ -1000,6 +1000,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
||||
// This is fine because:
|
||||
// - those queries are `eval_always` so we won't miss their result changing;
|
||||
// - this write will have happened before these queries are called.
|
||||
let data = def_kind.def_path_data(name);
|
||||
let key = self.untracked.definitions.write().create_def(parent, data);
|
||||
|
||||
let feed = TyCtxtFeed { tcx: self.tcx, key };
|
||||
|
@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||
};
|
||||
matches!(
|
||||
tcx.def_key(def_id).disambiguated_data.data,
|
||||
DefPathData::Ctor | DefPathData::ClosureExpr
|
||||
DefPathData::Ctor | DefPathData::Closure
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized {
|
||||
|
||||
match key.disambiguated_data.data {
|
||||
// Closures' own generics are only captures, don't print them.
|
||||
DefPathData::ClosureExpr => {}
|
||||
DefPathData::Closure => {}
|
||||
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
|
||||
// Anon consts doesn't have their own generics, and inline consts' own
|
||||
// generics are their inferred types, so don't print them.
|
||||
|
@ -1804,13 +1804,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
||||
// (but also some things just print a `DefId` generally so maybe we need this?)
|
||||
fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
|
||||
match tcx.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
|
||||
DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => {
|
||||
Namespace::TypeNS
|
||||
}
|
||||
|
||||
DefPathData::ValueNs(..)
|
||||
| DefPathData::AnonConst
|
||||
| DefPathData::ClosureExpr
|
||||
| DefPathData::Closure
|
||||
| DefPathData::Ctor => Namespace::ValueNS,
|
||||
|
||||
DefPathData::MacroNs(..) => Namespace::MacroNS,
|
||||
|
@ -4,9 +4,8 @@ use rustc_ast::*;
|
||||
use rustc_expand::expand::AstFragment;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::definitions::*;
|
||||
use rustc_span::hygiene::LocalExpnId;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub(crate) fn collect_definitions(
|
||||
@ -30,16 +29,19 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
|
||||
fn create_def(
|
||||
&mut self,
|
||||
node_id: NodeId,
|
||||
data: DefPathData,
|
||||
name: Symbol,
|
||||
def_kind: DefKind,
|
||||
span: Span,
|
||||
) -> LocalDefId {
|
||||
let parent_def = self.parent_def;
|
||||
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
|
||||
debug!(
|
||||
"create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
|
||||
node_id, def_kind, parent_def
|
||||
);
|
||||
self.resolver.create_def(
|
||||
parent_def,
|
||||
node_id,
|
||||
data,
|
||||
name,
|
||||
def_kind,
|
||||
self.expansion.to_expn_id(),
|
||||
span.with_parent(None),
|
||||
@ -76,8 +78,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
|
||||
self.visit_macro_invoc(field.id);
|
||||
} else {
|
||||
let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
|
||||
let def =
|
||||
self.create_def(field.id, DefPathData::ValueNs(name), DefKind::Field, field.span);
|
||||
let def = self.create_def(field.id, name, DefKind::Field, field.span);
|
||||
self.with_parent(def, |this| visit::walk_field_def(this, field));
|
||||
}
|
||||
}
|
||||
@ -97,40 +98,36 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
// Pick the def data. This need not be unique, but the more
|
||||
// information we encapsulate into, the better
|
||||
let mut opt_macro_data = None;
|
||||
let ty_data = DefPathData::TypeNs(i.ident.name);
|
||||
let value_data = DefPathData::ValueNs(i.ident.name);
|
||||
let (def_data, def_kind) = match &i.kind {
|
||||
ItemKind::Impl(i) => {
|
||||
(DefPathData::Impl, DefKind::Impl { of_trait: i.of_trait.is_some() })
|
||||
}
|
||||
ItemKind::ForeignMod(..) => (DefPathData::ForeignMod, DefKind::ForeignMod),
|
||||
ItemKind::Mod(..) => (ty_data, DefKind::Mod),
|
||||
ItemKind::Trait(..) => (ty_data, DefKind::Trait),
|
||||
ItemKind::TraitAlias(..) => (ty_data, DefKind::TraitAlias),
|
||||
ItemKind::Enum(..) => (ty_data, DefKind::Enum),
|
||||
ItemKind::Struct(..) => (ty_data, DefKind::Struct),
|
||||
ItemKind::Union(..) => (ty_data, DefKind::Union),
|
||||
ItemKind::ExternCrate(..) => (ty_data, DefKind::ExternCrate),
|
||||
ItemKind::TyAlias(..) => (ty_data, DefKind::TyAlias),
|
||||
ItemKind::Static(s) => (value_data, DefKind::Static(s.mutability)),
|
||||
ItemKind::Const(..) => (value_data, DefKind::Const),
|
||||
ItemKind::Fn(..) => (value_data, DefKind::Fn),
|
||||
let def_kind = match &i.kind {
|
||||
ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() },
|
||||
ItemKind::ForeignMod(..) => DefKind::ForeignMod,
|
||||
ItemKind::Mod(..) => DefKind::Mod,
|
||||
ItemKind::Trait(..) => DefKind::Trait,
|
||||
ItemKind::TraitAlias(..) => DefKind::TraitAlias,
|
||||
ItemKind::Enum(..) => DefKind::Enum,
|
||||
ItemKind::Struct(..) => DefKind::Struct,
|
||||
ItemKind::Union(..) => DefKind::Union,
|
||||
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
|
||||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||
ItemKind::Static(s) => DefKind::Static(s.mutability),
|
||||
ItemKind::Const(..) => DefKind::Const,
|
||||
ItemKind::Fn(..) => DefKind::Fn,
|
||||
ItemKind::MacroDef(..) => {
|
||||
let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
|
||||
let macro_kind = macro_data.ext.macro_kind();
|
||||
opt_macro_data = Some(macro_data);
|
||||
(DefPathData::MacroNs(i.ident.name), DefKind::Macro(macro_kind))
|
||||
DefKind::Macro(macro_kind)
|
||||
}
|
||||
ItemKind::MacCall(..) => {
|
||||
visit::walk_item(self, i);
|
||||
return self.visit_macro_invoc(i.id);
|
||||
}
|
||||
ItemKind::GlobalAsm(..) => (DefPathData::GlobalAsm, DefKind::GlobalAsm),
|
||||
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
|
||||
ItemKind::Use(..) => {
|
||||
return visit::walk_item(self, i);
|
||||
}
|
||||
};
|
||||
let def_id = self.create_def(i.id, def_data, def_kind, i.span);
|
||||
let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
|
||||
|
||||
if let Some(macro_data) = opt_macro_data {
|
||||
self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
|
||||
@ -144,7 +141,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
|
||||
this.create_def(
|
||||
ctor_node_id,
|
||||
DefPathData::Ctor,
|
||||
kw::Empty,
|
||||
DefKind::Ctor(CtorOf::Struct, ctor_kind),
|
||||
i.span,
|
||||
);
|
||||
@ -174,12 +171,8 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
// then the closure_def will never be used, and we should avoid generating a
|
||||
// def-id for it.
|
||||
if let Some(body) = body {
|
||||
let closure_def = self.create_def(
|
||||
closure_id,
|
||||
DefPathData::ClosureExpr,
|
||||
DefKind::Closure,
|
||||
span,
|
||||
);
|
||||
let closure_def =
|
||||
self.create_def(closure_id, kw::Empty, DefKind::Closure, span);
|
||||
self.with_parent(closure_def, |this| this.visit_block(body));
|
||||
}
|
||||
return;
|
||||
@ -190,21 +183,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
|
||||
self.create_def(id, DefPathData::Use, DefKind::Use, use_tree.span);
|
||||
self.create_def(id, kw::Empty, DefKind::Use, use_tree.span);
|
||||
visit::walk_use_tree(self, use_tree, id);
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||
let (def_data, def_kind) = match fi.kind {
|
||||
ForeignItemKind::Static(_, mt, _) => {
|
||||
(DefPathData::ValueNs(fi.ident.name), DefKind::Static(mt))
|
||||
}
|
||||
ForeignItemKind::Fn(_) => (DefPathData::ValueNs(fi.ident.name), DefKind::Fn),
|
||||
ForeignItemKind::TyAlias(_) => (DefPathData::TypeNs(fi.ident.name), DefKind::ForeignTy),
|
||||
let def_kind = match fi.kind {
|
||||
ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt),
|
||||
ForeignItemKind::Fn(_) => DefKind::Fn,
|
||||
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
|
||||
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
|
||||
};
|
||||
|
||||
let def = self.create_def(fi.id, def_data, def_kind, fi.span);
|
||||
let def = self.create_def(fi.id, fi.ident.name, def_kind, fi.span);
|
||||
|
||||
self.with_parent(def, |this| visit::walk_foreign_item(this, fi));
|
||||
}
|
||||
@ -213,13 +204,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
if v.is_placeholder {
|
||||
return self.visit_macro_invoc(v.id);
|
||||
}
|
||||
let def =
|
||||
self.create_def(v.id, DefPathData::TypeNs(v.ident.name), DefKind::Variant, v.span);
|
||||
let def = self.create_def(v.id, v.ident.name, DefKind::Variant, v.span);
|
||||
self.with_parent(def, |this| {
|
||||
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&v.data) {
|
||||
this.create_def(
|
||||
ctor_node_id,
|
||||
DefPathData::Ctor,
|
||||
kw::Empty,
|
||||
DefKind::Ctor(CtorOf::Variant, ctor_kind),
|
||||
v.span,
|
||||
);
|
||||
@ -242,15 +232,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
self.visit_macro_invoc(param.id);
|
||||
return;
|
||||
}
|
||||
let name = param.ident.name;
|
||||
let (def_path_data, def_kind) = match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
(DefPathData::LifetimeNs(name), DefKind::LifetimeParam)
|
||||
}
|
||||
GenericParamKind::Type { .. } => (DefPathData::TypeNs(name), DefKind::TyParam),
|
||||
GenericParamKind::Const { .. } => (DefPathData::ValueNs(name), DefKind::ConstParam),
|
||||
let def_kind = match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
|
||||
GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||
};
|
||||
self.create_def(param.id, def_path_data, def_kind, param.ident.span);
|
||||
self.create_def(param.id, param.ident.name, def_kind, param.ident.span);
|
||||
|
||||
// impl-Trait can happen inside generic parameters, like
|
||||
// ```
|
||||
@ -264,14 +251,14 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
|
||||
let (def_data, def_kind) = match &i.kind {
|
||||
AssocItemKind::Fn(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocFn),
|
||||
AssocItemKind::Const(..) => (DefPathData::ValueNs(i.ident.name), DefKind::AssocConst),
|
||||
AssocItemKind::Type(..) => (DefPathData::TypeNs(i.ident.name), DefKind::AssocTy),
|
||||
let def_kind = match &i.kind {
|
||||
AssocItemKind::Fn(..) => DefKind::AssocFn,
|
||||
AssocItemKind::Const(..) => DefKind::AssocConst,
|
||||
AssocItemKind::Type(..) => DefKind::AssocTy,
|
||||
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
|
||||
};
|
||||
|
||||
let def = self.create_def(i.id, def_data, def_kind, i.span);
|
||||
let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
|
||||
self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
|
||||
}
|
||||
|
||||
@ -283,12 +270,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
|
||||
let def = self.create_def(
|
||||
constant.id,
|
||||
DefPathData::AnonConst,
|
||||
DefKind::AnonConst,
|
||||
constant.value.span,
|
||||
);
|
||||
let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
|
||||
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
|
||||
}
|
||||
|
||||
@ -298,25 +280,21 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
ExprKind::Closure(ref closure) => {
|
||||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
let closure_def =
|
||||
self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span);
|
||||
let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
|
||||
match closure.asyncness {
|
||||
Async::Yes { closure_id, .. } => self.create_def(
|
||||
closure_id,
|
||||
DefPathData::ClosureExpr,
|
||||
DefKind::Closure,
|
||||
expr.span,
|
||||
),
|
||||
Async::Yes { closure_id, .. } => {
|
||||
self.create_def(closure_id, kw::Empty, DefKind::Closure, expr.span)
|
||||
}
|
||||
Async::No => closure_def,
|
||||
}
|
||||
}
|
||||
ExprKind::Gen(_, _, _) => {
|
||||
self.create_def(expr.id, DefPathData::ClosureExpr, DefKind::Closure, expr.span)
|
||||
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
|
||||
}
|
||||
ExprKind::ConstBlock(ref constant) => {
|
||||
let def = self.create_def(
|
||||
constant.id,
|
||||
DefPathData::AnonConst,
|
||||
kw::Empty,
|
||||
DefKind::InlineConst,
|
||||
constant.value.span,
|
||||
);
|
||||
|
@ -45,7 +45,6 @@ use rustc_hir::def::NonMacroAttrKind;
|
||||
use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::{PrimTy, TraitCandidate};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_metadata::creader::{CStore, CrateLoader};
|
||||
@ -1212,11 +1211,12 @@ impl<'tcx> Resolver<'_, 'tcx> {
|
||||
&mut self,
|
||||
parent: LocalDefId,
|
||||
node_id: ast::NodeId,
|
||||
data: DefPathData,
|
||||
name: Symbol,
|
||||
def_kind: DefKind,
|
||||
expn_id: ExpnId,
|
||||
span: Span,
|
||||
) -> LocalDefId {
|
||||
let data = def_kind.def_path_data(name);
|
||||
assert!(
|
||||
!self.node_id_to_def_id.contains_key(&node_id),
|
||||
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
|
||||
|
@ -379,14 +379,13 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
|
||||
hir::definitions::DefPathData::ForeignMod => "F", // Not specified in v0's <namespace>
|
||||
hir::definitions::DefPathData::TypeNs(..) => "t",
|
||||
hir::definitions::DefPathData::ValueNs(..) => "v",
|
||||
hir::definitions::DefPathData::ClosureExpr => "C",
|
||||
hir::definitions::DefPathData::Closure => "C",
|
||||
hir::definitions::DefPathData::Ctor => "c",
|
||||
hir::definitions::DefPathData::AnonConst => "k",
|
||||
hir::definitions::DefPathData::ImplTrait => "i",
|
||||
hir::definitions::DefPathData::OpaqueTy => "i",
|
||||
hir::definitions::DefPathData::CrateRoot
|
||||
| hir::definitions::DefPathData::Use
|
||||
| hir::definitions::DefPathData::GlobalAsm
|
||||
| hir::definitions::DefPathData::ImplTraitAssocTy
|
||||
| hir::definitions::DefPathData::MacroNs(..)
|
||||
| hir::definitions::DefPathData::LifetimeNs(..) => {
|
||||
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
|
||||
|
@ -770,17 +770,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
// Uppercase categories are more stable than lowercase ones.
|
||||
DefPathData::TypeNs(_) => 't',
|
||||
DefPathData::ValueNs(_) => 'v',
|
||||
DefPathData::ClosureExpr => 'C',
|
||||
DefPathData::Closure => 'C',
|
||||
DefPathData::Ctor => 'c',
|
||||
DefPathData::AnonConst => 'k',
|
||||
DefPathData::ImplTrait => 'i',
|
||||
DefPathData::OpaqueTy => 'i',
|
||||
|
||||
// These should never show up as `path_append` arguments.
|
||||
DefPathData::CrateRoot
|
||||
| DefPathData::Use
|
||||
| DefPathData::GlobalAsm
|
||||
| DefPathData::Impl
|
||||
| DefPathData::ImplTraitAssocTy
|
||||
| DefPathData::MacroNs(_)
|
||||
| DefPathData::LifetimeNs(_) => {
|
||||
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
|
||||
|
@ -55,3 +55,6 @@ trait_selection_trait_has_no_impls = this trait has no implementations, consider
|
||||
|
||||
trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
|
||||
|
||||
trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}`
|
||||
.help = expect either a generic argument name or {"`{Self}`"} as format argument
|
||||
|
@ -321,7 +321,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OnUnimplementedFormatString(Symbol, Span);
|
||||
pub struct OnUnimplementedFormatString {
|
||||
symbol: Symbol,
|
||||
span: Span,
|
||||
is_diagnostic_namespace_variant: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OnUnimplementedDirective {
|
||||
@ -401,6 +405,14 @@ impl IgnoredDiagnosticOption {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)]
|
||||
#[help]
|
||||
pub struct UnknownFormatParameterForOnUnimplementedAttr {
|
||||
argument_name: Symbol,
|
||||
trait_name: Symbol,
|
||||
}
|
||||
|
||||
impl<'tcx> OnUnimplementedDirective {
|
||||
fn parse(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -414,8 +426,14 @@ impl<'tcx> OnUnimplementedDirective {
|
||||
let mut item_iter = items.iter();
|
||||
|
||||
let parse_value = |value_str, value_span| {
|
||||
OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span, value_span)
|
||||
.map(Some)
|
||||
OnUnimplementedFormatString::try_parse(
|
||||
tcx,
|
||||
item_def_id,
|
||||
value_str,
|
||||
value_span,
|
||||
is_diagnostic_namespace_variant,
|
||||
)
|
||||
.map(Some)
|
||||
};
|
||||
|
||||
let condition = if is_root {
|
||||
@ -552,15 +570,15 @@ impl<'tcx> OnUnimplementedDirective {
|
||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
tcx,
|
||||
item_def_id,
|
||||
directive.message.as_ref().map(|f| f.1),
|
||||
aggr.message.as_ref().map(|f| f.1),
|
||||
directive.message.as_ref().map(|f| f.span),
|
||||
aggr.message.as_ref().map(|f| f.span),
|
||||
"message",
|
||||
);
|
||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
tcx,
|
||||
item_def_id,
|
||||
directive.label.as_ref().map(|f| f.1),
|
||||
aggr.label.as_ref().map(|f| f.1),
|
||||
directive.label.as_ref().map(|f| f.span),
|
||||
aggr.label.as_ref().map(|f| f.span),
|
||||
"label",
|
||||
);
|
||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
@ -573,8 +591,8 @@ impl<'tcx> OnUnimplementedDirective {
|
||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
tcx,
|
||||
item_def_id,
|
||||
directive.parent_label.as_ref().map(|f| f.1),
|
||||
aggr.parent_label.as_ref().map(|f| f.1),
|
||||
directive.parent_label.as_ref().map(|f| f.span),
|
||||
aggr.parent_label.as_ref().map(|f| f.span),
|
||||
"parent_label",
|
||||
);
|
||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
@ -634,7 +652,7 @@ impl<'tcx> OnUnimplementedDirective {
|
||||
item_def_id,
|
||||
value,
|
||||
attr.span,
|
||||
attr.span,
|
||||
is_diagnostic_namespace_variant,
|
||||
)?),
|
||||
notes: Vec::new(),
|
||||
parent_label: None,
|
||||
@ -713,7 +731,12 @@ impl<'tcx> OnUnimplementedDirective {
|
||||
// `with_no_visible_paths` is also used when generating the options,
|
||||
// so we need to match it here.
|
||||
ty::print::with_no_visible_paths!(
|
||||
OnUnimplementedFormatString(v, cfg.span).format(
|
||||
OnUnimplementedFormatString {
|
||||
symbol: v,
|
||||
span: cfg.span,
|
||||
is_diagnostic_namespace_variant: false
|
||||
}
|
||||
.format(
|
||||
tcx,
|
||||
trait_ref,
|
||||
&options_map
|
||||
@ -761,20 +784,19 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item_def_id: DefId,
|
||||
from: Symbol,
|
||||
err_sp: Span,
|
||||
value_span: Span,
|
||||
is_diagnostic_namespace_variant: bool,
|
||||
) -> Result<Self, ErrorGuaranteed> {
|
||||
let result = OnUnimplementedFormatString(from, value_span);
|
||||
result.verify(tcx, item_def_id, err_sp)?;
|
||||
let result = OnUnimplementedFormatString {
|
||||
symbol: from,
|
||||
span: value_span,
|
||||
is_diagnostic_namespace_variant,
|
||||
};
|
||||
result.verify(tcx, item_def_id)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn verify(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item_def_id: DefId,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
fn verify(&self, tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<(), ErrorGuaranteed> {
|
||||
let trait_def_id = if tcx.is_trait(item_def_id) {
|
||||
item_def_id
|
||||
} else {
|
||||
@ -783,7 +805,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
};
|
||||
let trait_name = tcx.item_name(trait_def_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let s = self.0.as_str();
|
||||
let s = self.symbol.as_str();
|
||||
let parser = Parser::new(s, None, None, false, ParseMode::Format);
|
||||
let mut result = Ok(());
|
||||
for token in parser {
|
||||
@ -793,24 +815,40 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
Position::ArgumentNamed(s) => {
|
||||
match Symbol::intern(s) {
|
||||
// `{ThisTraitsName}` is allowed
|
||||
s if s == trait_name => (),
|
||||
s if ALLOWED_FORMAT_SYMBOLS.contains(&s) => (),
|
||||
s if s == trait_name && !self.is_diagnostic_namespace_variant => (),
|
||||
s if ALLOWED_FORMAT_SYMBOLS.contains(&s)
|
||||
&& !self.is_diagnostic_namespace_variant =>
|
||||
{
|
||||
()
|
||||
}
|
||||
// So is `{A}` if A is a type parameter
|
||||
s if generics.params.iter().any(|param| param.name == s) => (),
|
||||
s => {
|
||||
result = Err(struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0230,
|
||||
"there is no parameter `{}` on {}",
|
||||
s,
|
||||
if trait_def_id == item_def_id {
|
||||
format!("trait `{trait_name}`")
|
||||
} else {
|
||||
"impl".to_string()
|
||||
}
|
||||
)
|
||||
.emit());
|
||||
if self.is_diagnostic_namespace_variant {
|
||||
tcx.emit_spanned_lint(
|
||||
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
|
||||
self.span,
|
||||
UnknownFormatParameterForOnUnimplementedAttr {
|
||||
argument_name: s,
|
||||
trait_name,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
result = Err(struct_span_err!(
|
||||
tcx.sess,
|
||||
self.span,
|
||||
E0230,
|
||||
"there is no parameter `{}` on {}",
|
||||
s,
|
||||
if trait_def_id == item_def_id {
|
||||
format!("trait `{trait_name}`")
|
||||
} else {
|
||||
"impl".to_string()
|
||||
}
|
||||
)
|
||||
.emit());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -818,7 +856,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => {
|
||||
let reported = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
self.span,
|
||||
E0231,
|
||||
"only named substitution parameters are allowed"
|
||||
)
|
||||
@ -857,37 +895,42 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
.collect::<FxHashMap<Symbol, String>>();
|
||||
let empty_string = String::new();
|
||||
|
||||
let s = self.0.as_str();
|
||||
let s = self.symbol.as_str();
|
||||
let parser = Parser::new(s, None, None, false, ParseMode::Format);
|
||||
let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string);
|
||||
parser
|
||||
.map(|p| match p {
|
||||
Piece::String(s) => s,
|
||||
Piece::String(s) => s.to_owned(),
|
||||
Piece::NextArgument(a) => match a.position {
|
||||
Position::ArgumentNamed(s) => {
|
||||
let s = Symbol::intern(s);
|
||||
Position::ArgumentNamed(arg) => {
|
||||
let s = Symbol::intern(arg);
|
||||
match generic_map.get(&s) {
|
||||
Some(val) => val,
|
||||
None if s == name => &trait_str,
|
||||
Some(val) => val.to_string(),
|
||||
None if self.is_diagnostic_namespace_variant => {
|
||||
format!("{{{arg}}}")
|
||||
}
|
||||
None if s == name => trait_str.clone(),
|
||||
None => {
|
||||
if let Some(val) = options.get(&s) {
|
||||
val
|
||||
val.clone()
|
||||
} else if s == sym::from_desugaring {
|
||||
// don't break messages using these two arguments incorrectly
|
||||
&empty_string
|
||||
} else if s == sym::ItemContext {
|
||||
item_context
|
||||
String::new()
|
||||
} else if s == sym::ItemContext
|
||||
&& !self.is_diagnostic_namespace_variant
|
||||
{
|
||||
item_context.clone()
|
||||
} else if s == sym::integral {
|
||||
"{integral}"
|
||||
String::from("{integral}")
|
||||
} else if s == sym::integer_ {
|
||||
"{integer}"
|
||||
String::from("{integer}")
|
||||
} else if s == sym::float {
|
||||
"{float}"
|
||||
String::from("{float}")
|
||||
} else {
|
||||
bug!(
|
||||
"broken on_unimplemented {:?} for {:?}: \
|
||||
no argument matching {:?}",
|
||||
self.0,
|
||||
self.symbol,
|
||||
trait_ref,
|
||||
s
|
||||
)
|
||||
@ -895,7 +938,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
|
||||
_ => bug!("broken on_unimplemented {:?} - bad format arg", self.symbol),
|
||||
},
|
||||
})
|
||||
.collect()
|
||||
|
@ -424,11 +424,23 @@ fn fn_abi_sanity_check<'tcx>(
|
||||
}
|
||||
PassMode::Indirect { meta_attrs: None, .. } => {
|
||||
// No metadata, must be sized.
|
||||
// Conceptually, unsized arguments must be copied around, which requires dynamically
|
||||
// determining their size, which we cannot do without metadata. Consult
|
||||
// t-opsem before removing this check.
|
||||
assert!(arg.layout.is_sized());
|
||||
}
|
||||
PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => {
|
||||
// With metadata. Must be unsized and not on the stack.
|
||||
assert!(arg.layout.is_unsized() && !on_stack);
|
||||
// Also, must not be `extern` type.
|
||||
let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {});
|
||||
if matches!(tail.kind(), ty::Foreign(..)) {
|
||||
// These types do not have metadata, so having `meta_attrs` is bogus.
|
||||
// Conceptually, unsized arguments must be copied around, which requires dynamically
|
||||
// determining their size. Therefore, we cannot allow `extern` types here. Consult
|
||||
// t-opsem before removing this check.
|
||||
panic!("unsized arguments must not be `extern` types");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
|
||||
@ -254,8 +253,7 @@ fn associated_type_for_impl_trait_in_trait(
|
||||
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
|
||||
|
||||
let span = tcx.def_span(opaque_ty_def_id);
|
||||
let trait_assoc_ty =
|
||||
tcx.at(span).create_def(trait_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy);
|
||||
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
|
||||
|
||||
let local_def_id = trait_assoc_ty.def_id();
|
||||
let def_id = local_def_id.to_def_id();
|
||||
@ -356,8 +354,7 @@ fn associated_type_for_impl_trait_in_impl(
|
||||
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
|
||||
hir::FnRetTy::Return(ty) => ty.span,
|
||||
};
|
||||
let impl_assoc_ty =
|
||||
tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy, DefKind::AssocTy);
|
||||
let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, kw::Empty, DefKind::AssocTy);
|
||||
|
||||
let local_def_id = impl_assoc_ty.def_id();
|
||||
let def_id = local_def_id.to_def_id();
|
||||
|
@ -1045,11 +1045,11 @@ impl<T> [T] {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let slice = ['r', 'u', 's', 't'];
|
||||
/// let mut iter = slice.windows(2);
|
||||
/// assert_eq!(iter.next().unwrap(), &['r', 'u']);
|
||||
/// assert_eq!(iter.next().unwrap(), &['u', 's']);
|
||||
/// assert_eq!(iter.next().unwrap(), &['s', 't']);
|
||||
/// let slice = ['l', 'o', 'r', 'e', 'm'];
|
||||
/// let mut iter = slice.windows(3);
|
||||
/// assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']);
|
||||
/// assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']);
|
||||
/// assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']);
|
||||
/// assert!(iter.next().is_none());
|
||||
/// ```
|
||||
///
|
||||
|
@ -0,0 +1,35 @@
|
||||
#![feature(layout_for_ptr)]
|
||||
use std::mem;
|
||||
|
||||
#[repr(packed, C)]
|
||||
struct PackedSized {
|
||||
f: u8,
|
||||
d: [u32; 4],
|
||||
}
|
||||
|
||||
#[repr(packed, C)]
|
||||
struct PackedUnsized {
|
||||
f: u8,
|
||||
d: [u32],
|
||||
}
|
||||
|
||||
impl PackedSized {
|
||||
fn unsize(&self) -> &PackedUnsized {
|
||||
// We can't unsize via a generic type since then we get the error
|
||||
// that packed structs with unsized tail don't work if the tail
|
||||
// might need dropping.
|
||||
let len = 4usize;
|
||||
unsafe { mem::transmute((self, len)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { unsafe {
|
||||
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
|
||||
let p = p.unsize() as *const PackedUnsized;
|
||||
// Make sure the size computation does *not* think there is
|
||||
// any padding in front of the `d` field.
|
||||
assert_eq!(mem::size_of_val_raw(p), 1 + 4*4);
|
||||
// And likewise for the offset computation.
|
||||
let d = std::ptr::addr_of!((*p).d);
|
||||
assert_eq!(d.cast::<u32>().read_unaligned(), 1);
|
||||
} }
|
@ -0,0 +1,38 @@
|
||||
#![feature(layout_for_ptr)]
|
||||
use std::mem;
|
||||
|
||||
#[repr(packed(4))]
|
||||
struct Slice([u32]);
|
||||
|
||||
#[repr(packed(2), C)]
|
||||
struct PackedSized {
|
||||
f: u8,
|
||||
d: [u32; 4],
|
||||
}
|
||||
|
||||
#[repr(packed(2), C)]
|
||||
struct PackedUnsized {
|
||||
f: u8,
|
||||
d: Slice,
|
||||
}
|
||||
|
||||
impl PackedSized {
|
||||
fn unsize(&self) -> &PackedUnsized {
|
||||
// We can't unsize via a generic type since then we get the error
|
||||
// that packed structs with unsized tail don't work if the tail
|
||||
// might need dropping.
|
||||
let len = 4usize;
|
||||
unsafe { mem::transmute((self, len)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { unsafe {
|
||||
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
|
||||
let p = p.unsize() as *const PackedUnsized;
|
||||
// Make sure the size computation correctly adds exact 1 byte of padding
|
||||
// in front of the `d` field.
|
||||
assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4);
|
||||
// And likewise for the offset computation.
|
||||
let d = std::ptr::addr_of!((*p).d);
|
||||
assert_eq!(d.cast::<u32>().read_unaligned(), 1);
|
||||
} }
|
@ -0,0 +1,67 @@
|
||||
#![feature(diagnostic_namespace)]
|
||||
|
||||
#[diagnostic::on_unimplemented(
|
||||
on(_Self = "&str"),
|
||||
//~^WARN malformed `on_unimplemented` attribute
|
||||
//~|WARN malformed `on_unimplemented` attribute
|
||||
message = "trait has `{Self}` and `{T}` as params",
|
||||
label = "trait has `{Self}` and `{T}` as params",
|
||||
note = "trait has `{Self}` and `{T}` as params",
|
||||
parent_label = "in this scope",
|
||||
//~^WARN malformed `on_unimplemented` attribute
|
||||
//~|WARN malformed `on_unimplemented` attribute
|
||||
append_const_msg
|
||||
//~^WARN malformed `on_unimplemented` attribute
|
||||
//~|WARN malformed `on_unimplemented` attribute
|
||||
)]
|
||||
trait Foo<T> {}
|
||||
|
||||
#[diagnostic::on_unimplemented = "Message"]
|
||||
//~^WARN malformed `on_unimplemented` attribute
|
||||
//~|WARN malformed `on_unimplemented` attribute
|
||||
trait Bar {}
|
||||
|
||||
#[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
|
||||
//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions
|
||||
impl Bar for i32 {}
|
||||
|
||||
// cannot use special rustc_on_unimplement symbols
|
||||
// in the format string
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
//~^WARN there is no parameter `from_desugaring` on trait `Baz`
|
||||
//~|WARN there is no parameter `from_desugaring` on trait `Baz`
|
||||
//~|WARN there is no parameter `direct` on trait `Baz`
|
||||
//~|WARN there is no parameter `direct` on trait `Baz`
|
||||
//~|WARN there is no parameter `cause` on trait `Baz`
|
||||
//~|WARN there is no parameter `cause` on trait `Baz`
|
||||
//~|WARN there is no parameter `integral` on trait `Baz`
|
||||
//~|WARN there is no parameter `integral` on trait `Baz`
|
||||
//~|WARN there is no parameter `integer` on trait `Baz`
|
||||
//~|WARN there is no parameter `integer` on trait `Baz`
|
||||
label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
//~^WARN there is no parameter `float` on trait `Baz`
|
||||
//~|WARN there is no parameter `float` on trait `Baz`
|
||||
//~|WARN there is no parameter `_Self` on trait `Baz`
|
||||
//~|WARN there is no parameter `_Self` on trait `Baz`
|
||||
//~|WARN there is no parameter `crate_local` on trait `Baz`
|
||||
//~|WARN there is no parameter `crate_local` on trait `Baz`
|
||||
//~|WARN there is no parameter `Trait` on trait `Baz`
|
||||
//~|WARN there is no parameter `Trait` on trait `Baz`
|
||||
//~|WARN there is no parameter `ItemContext` on trait `Baz`
|
||||
//~|WARN there is no parameter `ItemContext` on trait `Baz`
|
||||
)]
|
||||
trait Baz {}
|
||||
|
||||
fn takes_foo(_: impl Foo<i32>) {}
|
||||
fn takes_bar(_: impl Bar) {}
|
||||
fn takes_baz(_: impl Baz) {}
|
||||
|
||||
fn main() {
|
||||
takes_foo(());
|
||||
//~^ERROR trait has `()` and `i32` as params
|
||||
takes_bar(());
|
||||
//~^ERROR the trait bound `(): Bar` is not satisfied
|
||||
takes_baz(());
|
||||
//~^ERROR {from_desugaring}{direct}{cause}{integral}{integer}
|
||||
}
|
@ -0,0 +1,305 @@
|
||||
warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
|
||||
|
|
||||
LL | on(_Self = "&str"),
|
||||
| ^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
|
||||
|
|
||||
LL | parent_label = "in this scope",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
|
||||
|
|
||||
LL | append_const_msg
|
||||
| ^^^^^^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented = "Message"]
|
||||
| ^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
|
||||
warning: there is no parameter `from_desugaring` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `direct` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `cause` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `integral` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `integer` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `float` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `_Self` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `crate_local` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `Trait` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: there is no parameter `ItemContext` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
|
||||
|
|
||||
LL | on(_Self = "&str"),
|
||||
| ^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
|
||||
|
|
||||
LL | parent_label = "in this scope",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
|
||||
|
|
||||
LL | append_const_msg
|
||||
| ^^^^^^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: trait has `()` and `i32` as params
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
|
||||
|
|
||||
LL | takes_foo(());
|
||||
| --------- ^^ trait has `()` and `i32` as params
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Foo<i32>` is not implemented for `()`
|
||||
= note: trait has `()` and `i32` as params
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1
|
||||
|
|
||||
LL | trait Foo<T> {}
|
||||
| ^^^^^^^^^^^^
|
||||
note: required by a bound in `takes_foo`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
|
||||
|
|
||||
LL | fn takes_foo(_: impl Foo<i32>) {}
|
||||
| ^^^^^^^^ required by this bound in `takes_foo`
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented = "Message"]
|
||||
| ^^^^^^^^^^^ invalid option found here
|
||||
|
|
||||
= help: only `message`, `note` and `label` are allowed as options
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the trait bound `(): Bar` is not satisfied
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
|
||||
|
|
||||
LL | takes_bar(());
|
||||
| --------- ^^ the trait `Bar` is not implemented for `()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Bar` is implemented for `i32`
|
||||
note: required by a bound in `takes_bar`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22
|
||||
|
|
||||
LL | fn takes_bar(_: impl Bar) {}
|
||||
| ^^^ required by this bound in `takes_bar`
|
||||
|
||||
warning: there is no parameter `from_desugaring` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `direct` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `cause` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `integral` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `integer` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
|
||||
|
|
||||
LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `float` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `_Self` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `crate_local` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `Trait` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: there is no parameter `ItemContext` on trait `Baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
|
||||
|
|
||||
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
|
||||
|
|
||||
LL | takes_baz(());
|
||||
| --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Baz` is not implemented for `()`
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1
|
||||
|
|
||||
LL | trait Baz {}
|
||||
| ^^^^^^^^^
|
||||
note: required by a bound in `takes_baz`
|
||||
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22
|
||||
|
|
||||
LL | fn takes_baz(_: impl Baz) {}
|
||||
| ^^^ required by this bound in `takes_baz`
|
||||
|
||||
error: aborting due to 3 previous errors; 29 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -28,10 +28,16 @@ trait Doom {}
|
||||
//~|WARN missing options for `on_unimplemented` attribute
|
||||
trait Whatever {}
|
||||
|
||||
#[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
//~^WARN there is no parameter `DoesNotExist` on trait `Test`
|
||||
//~|WARN there is no parameter `DoesNotExist` on trait `Test`
|
||||
trait Test {}
|
||||
|
||||
fn take_foo(_: impl Foo) {}
|
||||
fn take_baz(_: impl Baz) {}
|
||||
fn take_boom(_: impl Boom) {}
|
||||
fn take_whatever(_: impl Whatever) {}
|
||||
fn take_test(_: impl Test) {}
|
||||
|
||||
fn main() {
|
||||
take_foo(1_i32);
|
||||
@ -42,4 +48,6 @@ fn main() {
|
||||
//~^ERROR Boom
|
||||
take_whatever(1_i32);
|
||||
//~^ERROR the trait bound `i32: Whatever` is not satisfied
|
||||
take_test(());
|
||||
//~^ERROR {DoesNotExist}
|
||||
}
|
||||
|
@ -46,6 +46,14 @@ LL | #[diagnostic::on_unimplemented]
|
||||
|
|
||||
= help: at least one of the `message`, `note` and `label` options are expected
|
||||
|
||||
warning: there is no parameter `DoesNotExist` on trait `Test`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
|
||||
warning: malformed `on_unimplemented` attribute
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
|
||||
|
|
||||
@ -56,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the trait bound `i32: Foo` is not satisfied
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:14
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
|
||||
|
|
||||
LL | take_foo(1_i32);
|
||||
| -------- ^^^^^ the trait `Foo` is not implemented for `i32`
|
||||
@ -69,7 +77,7 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait Foo {}
|
||||
| ^^^^^^^^^
|
||||
note: required by a bound in `take_foo`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:21
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21
|
||||
|
|
||||
LL | fn take_foo(_: impl Foo) {}
|
||||
| ^^^ required by this bound in `take_foo`
|
||||
@ -84,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Boom
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:14
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14
|
||||
|
|
||||
LL | take_baz(1_i32);
|
||||
| -------- ^^^^^ the trait `Baz` is not implemented for `i32`
|
||||
@ -97,7 +105,7 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait Baz {}
|
||||
| ^^^^^^^^^
|
||||
note: required by a bound in `take_baz`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:21
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21
|
||||
|
|
||||
LL | fn take_baz(_: impl Baz) {}
|
||||
| ^^^ required by this bound in `take_baz`
|
||||
@ -112,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: Boom
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:15
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15
|
||||
|
|
||||
LL | take_boom(1_i32);
|
||||
| --------- ^^^^^ the trait `Boom` is not implemented for `i32`
|
||||
@ -125,7 +133,7 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait Boom {}
|
||||
| ^^^^^^^^^^
|
||||
note: required by a bound in `take_boom`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:22
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
|
||||
|
|
||||
LL | fn take_boom(_: impl Boom) {}
|
||||
| ^^^^ required by this bound in `take_boom`
|
||||
@ -140,7 +148,7 @@ LL | #[diagnostic::on_unimplemented]
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the trait bound `i32: Whatever` is not satisfied
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:19
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19
|
||||
|
|
||||
LL | take_whatever(1_i32);
|
||||
| ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
|
||||
@ -153,11 +161,39 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait Whatever {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: required by a bound in `take_whatever`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:26
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26
|
||||
|
|
||||
LL | fn take_whatever(_: impl Whatever) {}
|
||||
| ^^^^^^^^ required by this bound in `take_whatever`
|
||||
|
||||
error: aborting due to 4 previous errors; 10 warnings emitted
|
||||
warning: there is no parameter `DoesNotExist` on trait `Test`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
|
||||
|
|
||||
LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expect either a generic argument name or `{Self}` as format argument
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: {DoesNotExist}
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
|
||||
|
|
||||
LL | take_test(());
|
||||
| --------- ^^ the trait `Test` is not implemented for `()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1
|
||||
|
|
||||
LL | trait Test {}
|
||||
| ^^^^^^^^^^
|
||||
note: required by a bound in `take_test`
|
||||
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22
|
||||
|
|
||||
LL | fn take_test(_: impl Test) {}
|
||||
| ^^^^ required by this bound in `take_test`
|
||||
|
||||
error: aborting due to 5 previous errors; 12 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
39
tests/ui/packed/issue-118537-field-offset-ice.rs
Normal file
39
tests/ui/packed/issue-118537-field-offset-ice.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// run-pass
|
||||
#![feature(layout_for_ptr)]
|
||||
use std::mem;
|
||||
|
||||
#[repr(packed(4))]
|
||||
struct Slice([u32]);
|
||||
|
||||
#[repr(packed(2), C)]
|
||||
struct PackedSized {
|
||||
f: u8,
|
||||
d: [u32; 4],
|
||||
}
|
||||
|
||||
#[repr(packed(2), C)]
|
||||
struct PackedUnsized {
|
||||
f: u8,
|
||||
d: Slice,
|
||||
}
|
||||
|
||||
impl PackedSized {
|
||||
fn unsize(&self) -> &PackedUnsized {
|
||||
// We can't unsize via a generic type since then we get the error
|
||||
// that packed structs with unsized tail don't work if the tail
|
||||
// might need dropping.
|
||||
let len = 4usize;
|
||||
unsafe { mem::transmute((self, len)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { unsafe {
|
||||
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
|
||||
let p = p.unsize() as *const PackedUnsized;
|
||||
// Make sure the size computation correctly adds exact 1 byte of padding
|
||||
// in front of the `d` field.
|
||||
assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4);
|
||||
// And likewise for the offset computation.
|
||||
let d = std::ptr::addr_of!((*p).d);
|
||||
assert_eq!(d.cast::<u32>().read_unaligned(), 1);
|
||||
} }
|
36
tests/ui/packed/issue-118537-field-offset.rs
Normal file
36
tests/ui/packed/issue-118537-field-offset.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// run-pass
|
||||
#![feature(layout_for_ptr)]
|
||||
use std::mem;
|
||||
|
||||
#[repr(packed, C)]
|
||||
struct PackedSized {
|
||||
f: u8,
|
||||
d: [u32; 4],
|
||||
}
|
||||
|
||||
#[repr(packed, C)]
|
||||
struct PackedUnsized {
|
||||
f: u8,
|
||||
d: [u32],
|
||||
}
|
||||
|
||||
impl PackedSized {
|
||||
fn unsize(&self) -> &PackedUnsized {
|
||||
// We can't unsize via a generic type since then we get the error
|
||||
// that packed structs with unsized tail don't work if the tail
|
||||
// might need dropping.
|
||||
let len = 4usize;
|
||||
unsafe { mem::transmute((self, len)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { unsafe {
|
||||
let p = PackedSized { f: 0, d: [1, 2, 3, 4] };
|
||||
let p = p.unsize() as *const PackedUnsized;
|
||||
// Make sure the size computation does *not* think there is
|
||||
// any padding in front of the `d` field.
|
||||
assert_eq!(mem::size_of_val_raw(p), 1 + 4*4);
|
||||
// And likewise for the offset computation.
|
||||
let d = std::ptr::addr_of!((*p).d);
|
||||
assert_eq!(d.cast::<u32>().read_unaligned(), 1);
|
||||
} }
|
Loading…
Reference in New Issue
Block a user