Skip to content

Commit

Permalink
Auto merge of #102324 - matthiaskrgr:rollup-6l70oz3, r=matthiaskrgr
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Sep 26, 2022
2 parents 1d1f142 + 6f5e8c2 commit 8b70583
Show file tree
Hide file tree
Showing 132 changed files with 544 additions and 309 deletions.
7 changes: 3 additions & 4 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand Down Expand Up @@ -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));
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/parser.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
81 changes: 54 additions & 27 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}

Expand All @@ -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;
}
}
Expand Down
28 changes: 28 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
29 changes: 22 additions & 7 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -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()?);

Expand Down Expand Up @@ -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)))
Expand Down
18 changes: 6 additions & 12 deletions compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
_2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
// mir::Constant
// + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9
// + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
}

bb1: {
Expand All @@ -37,7 +37,7 @@
- _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- // mir::Constant
- // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
- // + literal: Const { ty: for<'a> fn(&'a u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
+ _6 = _7; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ _5 = (*_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ goto -> bb2; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
Expand All @@ -53,7 +53,7 @@
- _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- // mir::Constant
- // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
- // + literal: Const { ty: for<'a> fn(&'a [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
+ _9 = _10; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ _8 = (*_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ goto -> bb3; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42
// + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
}

bb1: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53
// + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
}

bb1: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
_2 = core::str::<impl str>::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
// mir::Constant
// + span: $DIR/deduplicate_blocks.rs:5:13: 5:21
// + literal: Const { ty: for<'r> fn(&'r str) -> &'r [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
}

bb1: {
Expand Down
2 changes: 1 addition & 1 deletion src/test/mir-opt/derefer_complex_case.main.Derefer.diff
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
_7 = <std::slice::Iter<'_, i32> as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
// mir::Constant
// + span: $DIR/derefer_complex_case.rs:6:17: 6:26
// + literal: Const { ty: for<'r> fn(&'r mut std::slice::Iter<'_, i32>) -> Option<<std::slice::Iter<'_, i32> as Iterator>::Item> {<std::slice::Iter<'_, i32> as Iterator>::next}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, i32>) -> Option<<std::slice::Iter<'_, i32> as Iterator>::Item> {<std::slice::Iter<'_, i32> as Iterator>::next}, val: Value(<ZST>) }
}

bb3: {
Expand Down
Loading

0 comments on commit 8b70583

Please sign in to comment.