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
|
||||
/// 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.)
|
||||
///
|
||||
/// This must only fail if `alloc` contains relocations.
|
||||
fn init_allocation_extra<'b>(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
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.
|
||||
///
|
||||
|
@ -485,9 +487,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
|||
_id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
_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
|
||||
alloc
|
||||
Ok(alloc)
|
||||
}
|
||||
|
||||
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>,
|
||||
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
|
||||
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(
|
||||
|
@ -210,23 +211,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
mutability: Mutability,
|
||||
) -> Pointer<M::PointerTag> {
|
||||
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(
|
||||
&mut self,
|
||||
alloc: Allocation,
|
||||
kind: MemoryKind<M::MemoryKind>,
|
||||
) -> Pointer<M::PointerTag> {
|
||||
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
|
||||
let id = self.tcx.reserve_alloc_id();
|
||||
debug_assert_ne!(
|
||||
Some(kind),
|
||||
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
||||
"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()));
|
||||
M::tag_alloc_base_pointer(self, Pointer::from(id))
|
||||
Ok(M::tag_alloc_base_pointer(self, Pointer::from(id)))
|
||||
}
|
||||
|
||||
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)?;
|
||||
// We got tcx memory. Let the machine initialize its "extra" stuff.
|
||||
let alloc = M::init_allocation_extra(
|
||||
M::init_allocation_extra(
|
||||
self,
|
||||
id, // always use the ID we got as input, not the "hidden" one.
|
||||
Cow::Borrowed(alloc.inner()),
|
||||
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
||||
);
|
||||
Ok(alloc)
|
||||
)
|
||||
}
|
||||
|
||||
/// 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>,
|
||||
{
|
||||
debug!("binders(a={:?}, b={:?})", a, b);
|
||||
|
||||
// When higher-ranked types are involved, computing the LUB is
|
||||
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
|
||||
// When higher-ranked types are involved, computing the GLB is
|
||||
// very challenging, switch to invariance. This is obviously
|
||||
// overly conservative but works ok in practice.
|
||||
self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
|
||||
self.relate_with_variance(
|
||||
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>,
|
||||
{
|
||||
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
|
||||
// very challenging, switch to invariance. This is obviously
|
||||
// overly conservative but works ok in practice.
|
||||
self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
|
||||
self.relate_with_variance(
|
||||
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 {
|
||||
/// Convert Tag and add Extra fields
|
||||
pub fn convert_tag_add_extra<Tag, Extra>(
|
||||
pub fn convert_tag_add_extra<Tag, Extra, Err>(
|
||||
self,
|
||||
cx: &impl HasDataLayout,
|
||||
extra: Extra,
|
||||
mut tagger: impl FnMut(Pointer<AllocId>) -> Pointer<Tag>,
|
||||
) -> Allocation<Tag, Extra> {
|
||||
mut tagger: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Tag>, Err>,
|
||||
) -> Result<Allocation<Tag, Extra>, Err> {
|
||||
// Compute new pointer tags, which also adjusts the bytes.
|
||||
let mut bytes = self.bytes;
|
||||
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 bits = read_target_uint(endian, ptr_bytes).unwrap();
|
||||
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();
|
||||
new_relocations.push((offset, ptr_tag));
|
||||
}
|
||||
// Create allocation.
|
||||
Allocation {
|
||||
Ok(Allocation {
|
||||
bytes,
|
||||
relocations: Relocations::from_presorted(new_relocations),
|
||||
init_mask: self.init_mask,
|
||||
align: self.align,
|
||||
mutability: self.mutability,
|
||||
extra,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
//! conflicts between multiple such attributes attached to the same
|
||||
//! item.
|
||||
|
||||
use rustc_ast::tokenstream::DelimSpan;
|
||||
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MacArgs, MetaItemKind, NestedMetaItem};
|
||||
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
|
||||
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.
|
||||
fn check_attr_not_crate_level(
|
||||
&self,
|
||||
|
@ -1079,7 +1016,7 @@ impl CheckAttrVisitor<'_> {
|
|||
let mut is_valid = true;
|
||||
|
||||
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() {
|
||||
match i_meta.name_or_empty() {
|
||||
sym::alias
|
||||
|
@ -1127,15 +1064,6 @@ impl CheckAttrVisitor<'_> {
|
|||
is_valid = false;
|
||||
}
|
||||
|
||||
sym::hidden if !self.check_doc_hidden(attr,
|
||||
meta_index,
|
||||
meta,
|
||||
hir_id,
|
||||
target,
|
||||
) => {
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
// no_default_passes: deprecated
|
||||
// passes: deprecated
|
||||
// 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
|
||||
let opaque_ty = self.tcx.hir().item(item_id);
|
||||
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 {
|
||||
origin: hir::OpaqueTyOrigin::TyAlias,
|
||||
..
|
||||
|
@ -866,7 +864,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
|
||||
return;
|
||||
}
|
||||
// RPIT (return position impl trait)
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
|
||||
ref generics,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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]>() {}
|
||||
| ^^^^^^^^^^^^^^
|
|
@ -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;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
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) {
|
||||
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
|
||||
|
|
Loading…
Add table
Reference in a new issue