Auto merge of #98359 - JohnTitor:rollup-v30vyzr, r=JohnTitor
Rollup of 6 pull requests Successful merges: - #97867 (lub: don't bail out due to empty binders) - #98099 (interpret: convert_tag_add_extra: allow tagger to raise errors) - #98199 (Move some tests to more reasonable directories) - #98334 (Add a full regression test for #73727) - #98336 (Remove the unused-`#[doc(hidden)]` logic from the `unused_attributes` lint) - #98344 (This comment is out dated and misleading, the arm is about TAITs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a09c668c96
58 changed files with 248 additions and 291 deletions
|
@ -334,12 +334,14 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||||
/// allocation (because a copy had to be done to add tags or metadata), machine memory will
|
/// allocation (because a copy had to be done to add tags or metadata), machine memory will
|
||||||
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
|
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
|
||||||
/// owned allocation to the map even when the map is shared.)
|
/// owned allocation to the map even when the map is shared.)
|
||||||
|
///
|
||||||
|
/// This must only fail if `alloc` contains relocations.
|
||||||
fn init_allocation_extra<'b>(
|
fn init_allocation_extra<'b>(
|
||||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||||
id: AllocId,
|
id: AllocId,
|
||||||
alloc: Cow<'b, Allocation>,
|
alloc: Cow<'b, Allocation>,
|
||||||
kind: Option<MemoryKind<Self::MemoryKind>>,
|
kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||||
) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>;
|
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>>;
|
||||||
|
|
||||||
/// Hook for performing extra checks on a memory read access.
|
/// Hook for performing extra checks on a memory read access.
|
||||||
///
|
///
|
||||||
|
@ -485,9 +487,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||||
_id: AllocId,
|
_id: AllocId,
|
||||||
alloc: Cow<'b, Allocation>,
|
alloc: Cow<'b, Allocation>,
|
||||||
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||||
) -> Cow<'b, Allocation<Self::PointerTag>> {
|
) -> InterpResult<$tcx, Cow<'b, Allocation<Self::PointerTag>>> {
|
||||||
// We do not use a tag so we can just cheaply forward the allocation
|
// We do not use a tag so we can just cheaply forward the allocation
|
||||||
alloc
|
Ok(alloc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extern_static_base_pointer(
|
fn extern_static_base_pointer(
|
||||||
|
|
|
@ -199,7 +199,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
kind: MemoryKind<M::MemoryKind>,
|
kind: MemoryKind<M::MemoryKind>,
|
||||||
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
|
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
|
||||||
let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
|
let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
|
||||||
Ok(self.allocate_raw_ptr(alloc, kind))
|
// We can `unwrap` since `alloc` contains no pointers.
|
||||||
|
Ok(self.allocate_raw_ptr(alloc, kind).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_bytes_ptr(
|
pub fn allocate_bytes_ptr(
|
||||||
|
@ -210,23 +211,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
mutability: Mutability,
|
mutability: Mutability,
|
||||||
) -> Pointer<M::PointerTag> {
|
) -> Pointer<M::PointerTag> {
|
||||||
let alloc = Allocation::from_bytes(bytes, align, mutability);
|
let alloc = Allocation::from_bytes(bytes, align, mutability);
|
||||||
self.allocate_raw_ptr(alloc, kind)
|
// We can `unwrap` since `alloc` contains no pointers.
|
||||||
|
self.allocate_raw_ptr(alloc, kind).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This can fail only of `alloc` contains relocations.
|
||||||
pub fn allocate_raw_ptr(
|
pub fn allocate_raw_ptr(
|
||||||
&mut self,
|
&mut self,
|
||||||
alloc: Allocation,
|
alloc: Allocation,
|
||||||
kind: MemoryKind<M::MemoryKind>,
|
kind: MemoryKind<M::MemoryKind>,
|
||||||
) -> Pointer<M::PointerTag> {
|
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
|
||||||
let id = self.tcx.reserve_alloc_id();
|
let id = self.tcx.reserve_alloc_id();
|
||||||
debug_assert_ne!(
|
debug_assert_ne!(
|
||||||
Some(kind),
|
Some(kind),
|
||||||
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
||||||
"dynamically allocating global memory"
|
"dynamically allocating global memory"
|
||||||
);
|
);
|
||||||
let alloc = M::init_allocation_extra(self, id, Cow::Owned(alloc), Some(kind));
|
let alloc = M::init_allocation_extra(self, id, Cow::Owned(alloc), Some(kind))?;
|
||||||
self.memory.alloc_map.insert(id, (kind, alloc.into_owned()));
|
self.memory.alloc_map.insert(id, (kind, alloc.into_owned()));
|
||||||
M::tag_alloc_base_pointer(self, Pointer::from(id))
|
Ok(M::tag_alloc_base_pointer(self, Pointer::from(id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reallocate_ptr(
|
pub fn reallocate_ptr(
|
||||||
|
@ -510,13 +513,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
};
|
};
|
||||||
M::before_access_global(*self.tcx, &self.machine, id, alloc, def_id, is_write)?;
|
M::before_access_global(*self.tcx, &self.machine, id, alloc, def_id, is_write)?;
|
||||||
// We got tcx memory. Let the machine initialize its "extra" stuff.
|
// We got tcx memory. Let the machine initialize its "extra" stuff.
|
||||||
let alloc = M::init_allocation_extra(
|
M::init_allocation_extra(
|
||||||
self,
|
self,
|
||||||
id, // always use the ID we got as input, not the "hidden" one.
|
id, // always use the ID we got as input, not the "hidden" one.
|
||||||
Cow::Borrowed(alloc.inner()),
|
Cow::Borrowed(alloc.inner()),
|
||||||
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
||||||
);
|
)
|
||||||
Ok(alloc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
|
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
|
||||||
|
|
|
@ -95,12 +95,20 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
debug!("binders(a={:?}, b={:?})", a, b);
|
debug!("binders(a={:?}, b={:?})", a, b);
|
||||||
|
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
|
||||||
// When higher-ranked types are involved, computing the LUB is
|
// When higher-ranked types are involved, computing the GLB is
|
||||||
// very challenging, switch to invariance. This is obviously
|
// very challenging, switch to invariance. This is obviously
|
||||||
// overly conservative but works ok in practice.
|
// overly conservative but works ok in practice.
|
||||||
self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
|
self.relate_with_variance(
|
||||||
Ok(a)
|
ty::Variance::Invariant,
|
||||||
|
ty::VarianceDiagInfo::default(),
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
)?;
|
||||||
|
Ok(a)
|
||||||
|
} else {
|
||||||
|
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,20 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
||||||
T: Relate<'tcx>,
|
T: Relate<'tcx>,
|
||||||
{
|
{
|
||||||
debug!("binders(a={:?}, b={:?})", a, b);
|
debug!("binders(a={:?}, b={:?})", a, b);
|
||||||
|
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
|
||||||
// When higher-ranked types are involved, computing the LUB is
|
// When higher-ranked types are involved, computing the LUB is
|
||||||
// very challenging, switch to invariance. This is obviously
|
// very challenging, switch to invariance. This is obviously
|
||||||
// overly conservative but works ok in practice.
|
// overly conservative but works ok in practice.
|
||||||
self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
|
self.relate_with_variance(
|
||||||
Ok(a)
|
ty::Variance::Invariant,
|
||||||
|
ty::VarianceDiagInfo::default(),
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
)?;
|
||||||
|
Ok(a)
|
||||||
|
} else {
|
||||||
|
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,12 +244,12 @@ impl<Tag> Allocation<Tag> {
|
||||||
|
|
||||||
impl Allocation {
|
impl Allocation {
|
||||||
/// Convert Tag and add Extra fields
|
/// Convert Tag and add Extra fields
|
||||||
pub fn convert_tag_add_extra<Tag, Extra>(
|
pub fn convert_tag_add_extra<Tag, Extra, Err>(
|
||||||
self,
|
self,
|
||||||
cx: &impl HasDataLayout,
|
cx: &impl HasDataLayout,
|
||||||
extra: Extra,
|
extra: Extra,
|
||||||
mut tagger: impl FnMut(Pointer<AllocId>) -> Pointer<Tag>,
|
mut tagger: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Tag>, Err>,
|
||||||
) -> Allocation<Tag, Extra> {
|
) -> Result<Allocation<Tag, Extra>, Err> {
|
||||||
// Compute new pointer tags, which also adjusts the bytes.
|
// Compute new pointer tags, which also adjusts the bytes.
|
||||||
let mut bytes = self.bytes;
|
let mut bytes = self.bytes;
|
||||||
let mut new_relocations = Vec::with_capacity(self.relocations.0.len());
|
let mut new_relocations = Vec::with_capacity(self.relocations.0.len());
|
||||||
|
@ -260,19 +260,19 @@ impl Allocation {
|
||||||
let ptr_bytes = &mut bytes[idx..idx + ptr_size];
|
let ptr_bytes = &mut bytes[idx..idx + ptr_size];
|
||||||
let bits = read_target_uint(endian, ptr_bytes).unwrap();
|
let bits = read_target_uint(endian, ptr_bytes).unwrap();
|
||||||
let (ptr_tag, ptr_offset) =
|
let (ptr_tag, ptr_offset) =
|
||||||
tagger(Pointer::new(alloc_id, Size::from_bytes(bits))).into_parts();
|
tagger(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts();
|
||||||
write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap();
|
write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap();
|
||||||
new_relocations.push((offset, ptr_tag));
|
new_relocations.push((offset, ptr_tag));
|
||||||
}
|
}
|
||||||
// Create allocation.
|
// Create allocation.
|
||||||
Allocation {
|
Ok(Allocation {
|
||||||
bytes,
|
bytes,
|
||||||
relocations: Relocations::from_presorted(new_relocations),
|
relocations: Relocations::from_presorted(new_relocations),
|
||||||
init_mask: self.init_mask,
|
init_mask: self.init_mask,
|
||||||
align: self.align,
|
align: self.align,
|
||||||
mutability: self.mutability,
|
mutability: self.mutability,
|
||||||
extra,
|
extra,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
//! conflicts between multiple such attributes attached to the same
|
//! conflicts between multiple such attributes attached to the same
|
||||||
//! item.
|
//! item.
|
||||||
|
|
||||||
use rustc_ast::tokenstream::DelimSpan;
|
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
||||||
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MacArgs, MetaItemKind, NestedMetaItem};
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
|
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
|
||||||
use rustc_expand::base::resolve_path;
|
use rustc_expand::base::resolve_path;
|
||||||
|
@ -899,68 +898,6 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks `#[doc(hidden)]` attributes. Returns `true` if valid.
|
|
||||||
fn check_doc_hidden(
|
|
||||||
&self,
|
|
||||||
attr: &Attribute,
|
|
||||||
meta_index: usize,
|
|
||||||
meta: &NestedMetaItem,
|
|
||||||
hir_id: HirId,
|
|
||||||
target: Target,
|
|
||||||
) -> bool {
|
|
||||||
if let Target::AssocConst
|
|
||||||
| Target::AssocTy
|
|
||||||
| Target::Method(MethodKind::Trait { body: true }) = target
|
|
||||||
{
|
|
||||||
let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
|
|
||||||
let containing_item = self.tcx.hir().expect_item(parent_hir_id);
|
|
||||||
|
|
||||||
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = containing_item.kind {
|
|
||||||
let meta_items = attr.meta_item_list().unwrap();
|
|
||||||
|
|
||||||
let (span, replacement_span) = if meta_items.len() == 1 {
|
|
||||||
(attr.span, attr.span)
|
|
||||||
} else {
|
|
||||||
let meta_span = meta.span();
|
|
||||||
(
|
|
||||||
meta_span,
|
|
||||||
meta_span.until(match meta_items.get(meta_index + 1) {
|
|
||||||
Some(next_item) => next_item.span(),
|
|
||||||
None => match attr.get_normal_item().args {
|
|
||||||
MacArgs::Delimited(DelimSpan { close, .. }, ..) => close,
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME: #[doc(hidden)] was previously erroneously allowed on trait impl items,
|
|
||||||
// so for backward compatibility only emit a warning and do not mark it as invalid.
|
|
||||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| {
|
|
||||||
lint.build("`#[doc(hidden)]` is ignored on trait impl items")
|
|
||||||
.warn(
|
|
||||||
"this was previously accepted by the compiler but is \
|
|
||||||
being phased out; it will become a hard error in \
|
|
||||||
a future release!",
|
|
||||||
)
|
|
||||||
.note(
|
|
||||||
"whether the impl item is `doc(hidden)` or not \
|
|
||||||
entirely depends on the corresponding trait item",
|
|
||||||
)
|
|
||||||
.span_suggestion(
|
|
||||||
replacement_span,
|
|
||||||
"remove this attribute",
|
|
||||||
"",
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
|
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
|
||||||
fn check_attr_not_crate_level(
|
fn check_attr_not_crate_level(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1079,7 +1016,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
let mut is_valid = true;
|
let mut is_valid = true;
|
||||||
|
|
||||||
if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() {
|
if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() {
|
||||||
for (meta_index, meta) in list.into_iter().enumerate() {
|
for meta in list {
|
||||||
if let Some(i_meta) = meta.meta_item() {
|
if let Some(i_meta) = meta.meta_item() {
|
||||||
match i_meta.name_or_empty() {
|
match i_meta.name_or_empty() {
|
||||||
sym::alias
|
sym::alias
|
||||||
|
@ -1127,15 +1064,6 @@ impl CheckAttrVisitor<'_> {
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::hidden if !self.check_doc_hidden(attr,
|
|
||||||
meta_index,
|
|
||||||
meta,
|
|
||||||
hir_id,
|
|
||||||
target,
|
|
||||||
) => {
|
|
||||||
is_valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no_default_passes: deprecated
|
// no_default_passes: deprecated
|
||||||
// passes: deprecated
|
// passes: deprecated
|
||||||
// plugins: removed, but rustdoc warns about it itself
|
// plugins: removed, but rustdoc warns about it itself
|
||||||
|
|
|
@ -846,8 +846,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
// the opaque_ty generics
|
// the opaque_ty generics
|
||||||
let opaque_ty = self.tcx.hir().item(item_id);
|
let opaque_ty = self.tcx.hir().item(item_id);
|
||||||
let (generics, bounds) = match opaque_ty.kind {
|
let (generics, bounds) = match opaque_ty.kind {
|
||||||
// Named opaque `impl Trait` types are reached via `TyKind::Path`.
|
|
||||||
// This arm is for `impl Trait` in the types of statics, constants and locals.
|
|
||||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::TyAlias,
|
origin: hir::OpaqueTyOrigin::TyAlias,
|
||||||
..
|
..
|
||||||
|
@ -866,7 +864,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// RPIT (return position impl trait)
|
|
||||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
|
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
|
||||||
ref generics,
|
ref generics,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: `&'static [u32]` is forbidden as the type of a const generic parameter
|
error: `&'static [u32]` is forbidden as the type of a const generic parameter
|
||||||
--> $DIR/static-reference-array-const-param.rs:1:15
|
--> $DIR/issue-73727-static-reference-array-const-param.rs:9:15
|
||||||
|
|
|
|
||||||
LL | fn a<const X: &'static [u32]>() {}
|
LL | fn a<const X: &'static [u32]>() {}
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Regression test for #73727
|
||||||
|
|
||||||
|
// revisions: full min
|
||||||
|
//[full]check-pass
|
||||||
|
|
||||||
|
#![cfg_attr(full, feature(adt_const_params))]
|
||||||
|
#![cfg_attr(full, allow(incomplete_features))]
|
||||||
|
|
||||||
|
fn a<const X: &'static [u32]>() {}
|
||||||
|
//[min]~^ ERROR `&'static [u32]` is forbidden as the type of a const generic parameter
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
a::<{&[]}>();
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
fn a<const X: &'static [u32]>() {}
|
|
||||||
//~^ ERROR `&'static [u32]` is forbidden as the type of a const generic parameter
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
a::<{&[]}>();
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
#![feature(inherent_associated_types)]
|
|
||||||
#![allow(dead_code, incomplete_features)]
|
|
||||||
#![crate_type = "lib"]
|
|
||||||
#![deny(unused_attributes)]
|
|
||||||
// run-rustfix
|
|
||||||
|
|
||||||
pub trait Trait {
|
|
||||||
type It;
|
|
||||||
const IT: ();
|
|
||||||
fn it0();
|
|
||||||
fn it1();
|
|
||||||
fn it2();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Implementor;
|
|
||||||
|
|
||||||
impl Implementor {
|
|
||||||
#[doc(hidden)] // no error
|
|
||||||
type Inh = ();
|
|
||||||
|
|
||||||
#[doc(hidden)] // no error
|
|
||||||
const INH: () = ();
|
|
||||||
|
|
||||||
#[doc(hidden)] // no error
|
|
||||||
fn inh() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Trait for Implementor {
|
|
||||||
|
|
||||||
type It = ();
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
|
|
||||||
const IT: () = ();
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc(alias = "aka")]
|
|
||||||
fn it0() {}
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc(alias = "this", )]
|
|
||||||
fn it1() {}
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc()]
|
|
||||||
fn it2() {}
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
//~| ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
#![feature(inherent_associated_types)]
|
|
||||||
#![allow(dead_code, incomplete_features)]
|
|
||||||
#![crate_type = "lib"]
|
|
||||||
#![deny(unused_attributes)]
|
|
||||||
// run-rustfix
|
|
||||||
|
|
||||||
pub trait Trait {
|
|
||||||
type It;
|
|
||||||
const IT: ();
|
|
||||||
fn it0();
|
|
||||||
fn it1();
|
|
||||||
fn it2();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Implementor;
|
|
||||||
|
|
||||||
impl Implementor {
|
|
||||||
#[doc(hidden)] // no error
|
|
||||||
type Inh = ();
|
|
||||||
|
|
||||||
#[doc(hidden)] // no error
|
|
||||||
const INH: () = ();
|
|
||||||
|
|
||||||
#[doc(hidden)] // no error
|
|
||||||
fn inh() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Trait for Implementor {
|
|
||||||
#[doc(hidden)]
|
|
||||||
type It = ();
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
const IT: () = ();
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc(hidden, alias = "aka")]
|
|
||||||
fn it0() {}
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc(alias = "this", hidden,)]
|
|
||||||
fn it1() {}
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
|
|
||||||
#[doc(hidden, hidden)]
|
|
||||||
fn it2() {}
|
|
||||||
//~^^ ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
//~| ERROR `#[doc(hidden)]` is ignored
|
|
||||||
//~| WARNING this was previously accepted
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
error: `#[doc(hidden)]` is ignored on trait impl items
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:29:5
|
|
||||||
|
|
|
||||||
LL | #[doc(hidden)]
|
|
||||||
| ^^^^^^^^^^^^^^ help: remove this attribute
|
|
||||||
|
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:4:9
|
|
||||||
|
|
|
||||||
LL | #![deny(unused_attributes)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
|
|
||||||
|
|
||||||
error: `#[doc(hidden)]` is ignored on trait impl items
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:34:5
|
|
||||||
|
|
|
||||||
LL | #[doc(hidden)]
|
|
||||||
| ^^^^^^^^^^^^^^ help: remove this attribute
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
|
|
||||||
|
|
||||||
error: `#[doc(hidden)]` is ignored on trait impl items
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:39:11
|
|
||||||
|
|
|
||||||
LL | #[doc(hidden, alias = "aka")]
|
|
||||||
| ^^^^^^--
|
|
||||||
| |
|
|
||||||
| help: remove this attribute
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
|
|
||||||
|
|
||||||
error: `#[doc(hidden)]` is ignored on trait impl items
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:44:27
|
|
||||||
|
|
|
||||||
LL | #[doc(alias = "this", hidden,)]
|
|
||||||
| ^^^^^^-
|
|
||||||
| |
|
|
||||||
| help: remove this attribute
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
|
|
||||||
|
|
||||||
error: `#[doc(hidden)]` is ignored on trait impl items
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:49:11
|
|
||||||
|
|
|
||||||
LL | #[doc(hidden, hidden)]
|
|
||||||
| ^^^^^^--
|
|
||||||
| |
|
|
||||||
| help: remove this attribute
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
|
|
||||||
|
|
||||||
error: `#[doc(hidden)]` is ignored on trait impl items
|
|
||||||
--> $DIR/unused-attr-doc-hidden.rs:49:19
|
|
||||||
|
|
|
||||||
LL | #[doc(hidden, hidden)]
|
|
||||||
| ^^^^^^ help: remove this attribute
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
|
||||||
|
|
22
src/test/ui/lub-glb/empty-binder-future-compat.rs
Normal file
22
src/test/ui/lub-glb/empty-binder-future-compat.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// check-pass
|
||||||
|
fn lt_in_fn_fn<'a: 'a>() -> fn(fn(&'a ())) {
|
||||||
|
|_| ()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn foo<'a, 'b, 'lower>(v: bool)
|
||||||
|
where
|
||||||
|
'a: 'lower,
|
||||||
|
'b: 'lower,
|
||||||
|
{
|
||||||
|
// if we infer `x` to be higher ranked in the future,
|
||||||
|
// this would cause a type error.
|
||||||
|
let x = match v {
|
||||||
|
true => lt_in_fn_fn::<'a>(),
|
||||||
|
false => lt_in_fn_fn::<'b>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _: fn(fn(&'lower())) = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
55
src/test/ui/lub-glb/empty-binders-err.rs
Normal file
55
src/test/ui/lub-glb/empty-binders-err.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
fn lt<'a: 'a>() -> &'a () {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lt_in_fn<'a: 'a>() -> fn(&'a ()) {
|
||||||
|
|_| ()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Contra<'a>(fn(&'a ()));
|
||||||
|
fn lt_in_contra<'a: 'a>() -> Contra<'a> {
|
||||||
|
Contra(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn covariance<'a, 'b, 'upper>(v: bool)
|
||||||
|
where
|
||||||
|
'upper: 'a,
|
||||||
|
'upper: 'b,
|
||||||
|
|
||||||
|
{
|
||||||
|
let _: &'upper () = match v {
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
//~| ERROR lifetime may not live long enough
|
||||||
|
true => lt::<'a>(),
|
||||||
|
false => lt::<'b>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contra_fn<'a, 'b, 'lower>(v: bool)
|
||||||
|
where
|
||||||
|
'a: 'lower,
|
||||||
|
'b: 'lower,
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
let _: fn(&'lower ()) = match v {
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
true => lt_in_fn::<'a>(),
|
||||||
|
false => lt_in_fn::<'b>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contra_struct<'a, 'b, 'lower>(v: bool)
|
||||||
|
where
|
||||||
|
'a: 'lower,
|
||||||
|
'b: 'lower,
|
||||||
|
|
||||||
|
{
|
||||||
|
let _: Contra<'lower> = match v {
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
true => lt_in_contra::<'a>(),
|
||||||
|
false => lt_in_contra::<'b>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
59
src/test/ui/lub-glb/empty-binders-err.stderr
Normal file
59
src/test/ui/lub-glb/empty-binders-err.stderr
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/empty-binders-err.rs:20:12
|
||||||
|
|
|
||||||
|
LL | fn covariance<'a, 'b, 'upper>(v: bool)
|
||||||
|
| -- ------ lifetime `'upper` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | let _: &'upper () = match v {
|
||||||
|
| ^^^^^^^^^^ type annotation requires that `'a` must outlive `'upper`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'a: 'upper`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/empty-binders-err.rs:20:12
|
||||||
|
|
|
||||||
|
LL | fn covariance<'a, 'b, 'upper>(v: bool)
|
||||||
|
| -- ------ lifetime `'upper` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'b` defined here
|
||||||
|
...
|
||||||
|
LL | let _: &'upper () = match v {
|
||||||
|
| ^^^^^^^^^^ type annotation requires that `'b` must outlive `'upper`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'b: 'upper`
|
||||||
|
|
||||||
|
help: the following changes may resolve your lifetime errors
|
||||||
|
|
|
||||||
|
= help: add bound `'a: 'upper`
|
||||||
|
= help: add bound `'b: 'upper`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/empty-binders-err.rs:35:12
|
||||||
|
|
|
||||||
|
LL | fn contra_fn<'a, 'b, 'lower>(v: bool)
|
||||||
|
| -- ------ lifetime `'lower` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | let _: fn(&'lower ()) = match v {
|
||||||
|
| ^^^^^^^^^^^^^^ type annotation requires that `'lower` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'lower: 'a`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/empty-binders-err.rs:48:12
|
||||||
|
|
|
||||||
|
LL | fn contra_struct<'a, 'b, 'lower>(v: bool)
|
||||||
|
| -- ------ lifetime `'lower` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | let _: Contra<'lower> = match v {
|
||||||
|
| ^^^^^^^^^^^^^^ type annotation requires that `'lower` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'lower: 'a`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
45
src/test/ui/lub-glb/empty-binders.rs
Normal file
45
src/test/ui/lub-glb/empty-binders.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// check-pass
|
||||||
|
//
|
||||||
|
// Check that computing the lub works even for empty binders.
|
||||||
|
fn lt<'a: 'a>() -> &'a () {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lt_in_fn<'a: 'a>() -> fn(&'a ()) {
|
||||||
|
|_| ()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Contra<'a>(fn(&'a ()));
|
||||||
|
fn lt_in_contra<'a: 'a>() -> Contra<'a> {
|
||||||
|
Contra(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ok<'a, 'b, 'upper, 'lower>(v: bool)
|
||||||
|
where
|
||||||
|
'upper: 'a,
|
||||||
|
'upper: 'b,
|
||||||
|
'a: 'lower,
|
||||||
|
'b: 'lower,
|
||||||
|
|
||||||
|
{
|
||||||
|
let _: &'lower () = match v {
|
||||||
|
true => lt::<'a>(),
|
||||||
|
false => lt::<'b>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// This errored in the past because LUB and GLB always
|
||||||
|
// bailed out when encountering binders, even if they were
|
||||||
|
// empty.
|
||||||
|
let _: fn(&'upper ()) = match v {
|
||||||
|
true => lt_in_fn::<'a>(),
|
||||||
|
false => lt_in_fn::<'b>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// This was already accepted, as relate didn't encounter any binders.
|
||||||
|
let _: Contra<'upper> = match v {
|
||||||
|
true => lt_in_contra::<'a>(),
|
||||||
|
false => lt_in_contra::<'b>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -8,7 +8,7 @@ use std::path::Path;
|
||||||
const ENTRY_LIMIT: usize = 1000;
|
const ENTRY_LIMIT: usize = 1000;
|
||||||
// FIXME: The following limits should be reduced eventually.
|
// FIXME: The following limits should be reduced eventually.
|
||||||
const ROOT_ENTRY_LIMIT: usize = 968;
|
const ROOT_ENTRY_LIMIT: usize = 968;
|
||||||
const ISSUES_ENTRY_LIMIT: usize = 2179;
|
const ISSUES_ENTRY_LIMIT: usize = 2147;
|
||||||
|
|
||||||
fn check_entries(path: &Path, bad: &mut bool) {
|
fn check_entries(path: &Path, bad: &mut bool) {
|
||||||
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
|
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue