diff options
| author | bors <bors@rust-lang.org> | 2022-09-26 19:57:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-26 19:57:51 +0000 |
| commit | 8b705839cd656d202e920efa8769cbe43a5ee269 (patch) | |
| tree | 4137d5bdc7d6c4a5fd42c00083775e2b9b123d58 /compiler | |
| parent | 1d1f1426604b7d79138cdfbb31f82f7f44756fba (diff) | |
| parent | 6f5e8c2ed4283035164b84bef627fafb65d4c853 (diff) | |
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
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_passes/src/ast_validation.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_error_messages/locales/en-US/parser.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 81 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/coherence/builtin.rs | 18 |
7 files changed, 124 insertions, 50 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b1d10e07ad0..ecf74c76020 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -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)); } diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 9459cfebde9..07dd03e6e50 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -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 diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 99e5722ddad..70efa748846 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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; } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 258fb2e2f9f..f4f4bb37c1a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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 { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0a81cde93be..ccdffb8ce07 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -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. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e385ac44113..34f25bd0716 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -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))) diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index d08c0d4dbb7..d4eb826f0b4 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -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) => { |
