Auto merge of #102324 - matthiaskrgr:rollup-6l70oz3, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #101875 (Allow more `!Copy` impls) - #101996 (Don't duplicate region names for late-bound regions in print of Binder) - #102181 (Add regression test) - #102273 (Allow `~const` bounds on non-const functions) - #102286 (Recover some items that expect braces and don't take semicolons) Failed merges: - #102314 (Add a label to struct/enum/union ident name) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8b705839cd
132 changed files with 544 additions and 309 deletions
|
@ -1415,7 +1415,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
if !self.is_tilde_const_allowed {
|
||||
self.err_handler()
|
||||
.struct_span_err(bound.span(), "`~const` is not allowed here")
|
||||
.note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
|
||||
.note("only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -1523,9 +1523,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
let tilde_const_allowed =
|
||||
matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
|
||||
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
|
||||
let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { .. }))
|
||||
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
|
||||
|
||||
self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
|
||||
}
|
||||
|
|
|
@ -158,3 +158,6 @@ parser_remove_let = expected pattern, found `let`
|
|||
|
||||
parser_use_eq_instead = unexpected `==`
|
||||
.suggestion = try using `=` instead
|
||||
|
||||
parser_use_empty_block_not_semi = expected { "`{}`" }, found `;`
|
||||
.suggestion = try using { "`{}`" } instead
|
||||
|
|
|
@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
|
|||
in_value: bool,
|
||||
pub print_alloc_ids: bool,
|
||||
|
||||
// set of all named (non-anonymous) region names
|
||||
used_region_names: FxHashSet<Symbol>,
|
||||
|
||||
region_index: usize,
|
||||
binder_depth: usize,
|
||||
printed_type_count: usize,
|
||||
|
@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
where
|
||||
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
|
||||
{
|
||||
fn name_by_region_index(index: usize) -> Symbol {
|
||||
match index {
|
||||
0 => Symbol::intern("'r"),
|
||||
1 => Symbol::intern("'s"),
|
||||
i => Symbol::intern(&format!("'t{}", i - 2)),
|
||||
fn name_by_region_index(
|
||||
index: usize,
|
||||
available_names: &mut Vec<Symbol>,
|
||||
num_available: usize,
|
||||
) -> Symbol {
|
||||
if let Some(name) = available_names.pop() {
|
||||
name
|
||||
} else {
|
||||
Symbol::intern(&format!("'z{}", index - num_available))
|
||||
}
|
||||
}
|
||||
|
||||
debug!("name_all_regions");
|
||||
|
||||
// Replace any anonymous late-bound regions with named
|
||||
// variants, using new unique identifiers, so that we can
|
||||
// clearly differentiate between named and unnamed regions in
|
||||
// the output. We'll probably want to tweak this over time to
|
||||
// decide just how much information to give.
|
||||
if self.binder_depth == 0 {
|
||||
self.prepare_late_bound_region_info(value);
|
||||
self.prepare_region_info(value);
|
||||
}
|
||||
|
||||
debug!("self.used_region_names: {:?}", &self.used_region_names);
|
||||
|
||||
let mut empty = true;
|
||||
let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
|
||||
let w = if empty {
|
||||
|
@ -2151,13 +2161,24 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
|
||||
define_scoped_cx!(self);
|
||||
|
||||
let possible_names =
|
||||
('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))).collect::<Vec<_>>();
|
||||
|
||||
let mut available_names = possible_names
|
||||
.into_iter()
|
||||
.filter(|name| !self.used_region_names.contains(&name))
|
||||
.collect::<Vec<_>>();
|
||||
debug!(?available_names);
|
||||
let num_available = available_names.len();
|
||||
|
||||
let mut region_index = self.region_index;
|
||||
let mut next_name = |this: &Self| loop {
|
||||
let name = name_by_region_index(region_index);
|
||||
let mut next_name = |this: &Self| {
|
||||
let name = name_by_region_index(region_index, &mut available_names, num_available);
|
||||
debug!(?name);
|
||||
region_index += 1;
|
||||
if !this.used_region_names.contains(&name) {
|
||||
break name;
|
||||
}
|
||||
assert!(!this.used_region_names.contains(&name));
|
||||
|
||||
name
|
||||
};
|
||||
|
||||
// If we want to print verbosely, then print *all* binders, even if they
|
||||
|
@ -2178,6 +2199,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
ty::BrAnon(_) | ty::BrEnv => {
|
||||
start_or_continue(&mut self, "for<", ", ");
|
||||
let name = next_name(&self);
|
||||
debug!(?name);
|
||||
do_continue(&mut self, name);
|
||||
ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
|
||||
}
|
||||
|
@ -2271,29 +2293,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
Ok(inner)
|
||||
}
|
||||
|
||||
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
|
||||
fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
|
||||
where
|
||||
T: TypeVisitable<'tcx>,
|
||||
{
|
||||
struct LateBoundRegionNameCollector<'a, 'tcx> {
|
||||
used_region_names: &'a mut FxHashSet<Symbol>,
|
||||
struct RegionNameCollector<'tcx> {
|
||||
used_region_names: FxHashSet<Symbol>,
|
||||
type_collector: SsoHashSet<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
|
||||
impl<'tcx> RegionNameCollector<'tcx> {
|
||||
fn new() -> Self {
|
||||
RegionNameCollector {
|
||||
used_region_names: Default::default(),
|
||||
type_collector: SsoHashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
trace!("address: {:p}", r.0.0);
|
||||
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
|
||||
self.used_region_names.insert(name);
|
||||
} else if let ty::RePlaceholder(ty::PlaceholderRegion {
|
||||
name: ty::BrNamed(_, name),
|
||||
..
|
||||
}) = *r
|
||||
{
|
||||
|
||||
// Collect all named lifetimes. These allow us to prevent duplication
|
||||
// of already existing lifetime names when introducing names for
|
||||
// anonymous late-bound regions.
|
||||
if let Some(name) = r.get_name() {
|
||||
self.used_region_names.insert(name);
|
||||
}
|
||||
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
|
||||
|
@ -2309,12 +2339,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.used_region_names.clear();
|
||||
let mut collector = LateBoundRegionNameCollector {
|
||||
used_region_names: &mut self.used_region_names,
|
||||
type_collector: SsoHashSet::new(),
|
||||
};
|
||||
let mut collector = RegionNameCollector::new();
|
||||
value.visit_with(&mut collector);
|
||||
self.used_region_names = collector.used_region_names;
|
||||
self.region_index = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,17 @@ impl BoundRegionKind {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_name(&self) -> Option<Symbol> {
|
||||
if self.is_named() {
|
||||
match *self {
|
||||
BoundRegionKind::BrNamed(_, name) => return Some(name),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Article {
|
||||
|
@ -1445,6 +1456,23 @@ impl<'tcx> Region<'tcx> {
|
|||
*self.0.0
|
||||
}
|
||||
|
||||
pub fn get_name(self) -> Option<Symbol> {
|
||||
if self.has_name() {
|
||||
let name = match *self {
|
||||
ty::ReEarlyBound(ebr) => Some(ebr.name),
|
||||
ty::ReLateBound(_, br) => br.kind.get_name(),
|
||||
ty::ReFree(fr) => fr.bound_region.get_name(),
|
||||
ty::ReStatic => Some(kw::StaticLifetime),
|
||||
ty::RePlaceholder(placeholder) => placeholder.name.get_name(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Is this region named by the user?
|
||||
pub fn has_name(self) -> bool {
|
||||
match *self {
|
||||
|
|
|
@ -745,6 +745,14 @@ pub(crate) struct UseEqInstead {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parser::use_empty_block_not_semi)]
|
||||
pub(crate) struct UseEmptyBlockNotSemi {
|
||||
#[primary_span]
|
||||
#[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
// SnapshotParser is used to create a snapshot of the parser
|
||||
// without causing duplicate errors being emitted when the `Parser`
|
||||
// is dropped.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error};
|
||||
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error, UseEmptyBlockNotSemi};
|
||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
|
||||
|
||||
|
@ -664,6 +664,14 @@ impl<'a> Parser<'a> {
|
|||
mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
|
||||
) -> PResult<'a, Vec<T>> {
|
||||
let open_brace_span = self.token.span;
|
||||
|
||||
// Recover `impl Ty;` instead of `impl Ty {}`
|
||||
if self.token == TokenKind::Semi {
|
||||
self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
|
||||
self.bump();
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
self.expect(&token::OpenDelim(Delimiter::Brace))?;
|
||||
attrs.extend(self.parse_inner_attributes()?);
|
||||
|
||||
|
@ -1305,12 +1313,19 @@ impl<'a> Parser<'a> {
|
|||
let mut generics = self.parse_generics()?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
|
||||
let (variants, _) = self
|
||||
.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant())
|
||||
.map_err(|e| {
|
||||
self.recover_stmt();
|
||||
e
|
||||
})?;
|
||||
// Possibly recover `enum Foo;` instead of `enum Foo {}`
|
||||
let (variants, _) = if self.token == TokenKind::Semi {
|
||||
self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
|
||||
self.bump();
|
||||
(vec![], false)
|
||||
} else {
|
||||
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
|
||||
|e| {
|
||||
self.recover_stmt();
|
||||
e
|
||||
},
|
||||
)?
|
||||
};
|
||||
|
||||
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
|
||||
Ok((id, ItemKind::Enum(enum_definition, generics)))
|
||||
|
|
|
@ -70,23 +70,21 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
|||
let self_type = tcx.type_of(impl_did);
|
||||
debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
|
||||
|
||||
let span = tcx.hir().span(impl_hir_id);
|
||||
let param_env = tcx.param_env(impl_did);
|
||||
assert!(!self_type.has_escaping_bound_vars());
|
||||
|
||||
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
|
||||
|
||||
let span = match tcx.hir().expect_item(impl_did).kind {
|
||||
ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
|
||||
ItemKind::Impl(impl_) => impl_.self_ty.span,
|
||||
_ => bug!("expected Copy impl item"),
|
||||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(span, impl_hir_id);
|
||||
match can_type_implement_copy(tcx, param_env, self_type, cause) {
|
||||
Ok(()) => {}
|
||||
Err(CopyImplementationError::InfrigingFields(fields)) => {
|
||||
let item = tcx.hir().expect_item(impl_did);
|
||||
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
|
||||
tr.path.span
|
||||
} else {
|
||||
span
|
||||
};
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
|
@ -166,10 +164,6 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
|||
err.emit();
|
||||
}
|
||||
Err(CopyImplementationError::NotAnAdt) => {
|
||||
let item = tcx.hir().expect_item(impl_did);
|
||||
let span =
|
||||
if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
|
||||
|
||||
tcx.sess.emit_err(CopyImplOnNonAdt { span });
|
||||
}
|
||||
Err(CopyImplementationError::HasDestructor) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue