1
Fork 0

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:
bors 2022-09-26 19:57:51 +00:00
commit 8b705839cd
132 changed files with 544 additions and 309 deletions

View file

@ -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));
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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 {

View file

@ -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.

View file

@ -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)))

View file

@ -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) => {