Skip to content

Commit

Permalink
Auto merge of rust-lang#117193 - matthiaskrgr:rollup-bygfdcd, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#116401 (Return multiple object-safety violation errors and code improvements to the object-safety check)
 - rust-lang#116553 (Do not suggest 'Trait<Assoc=arg>' when in trait impl)
 - rust-lang#116931 (Improve the warning messages for the `#[diagnostic::on_unimplemented]`)
 - rust-lang#117008 (Uplift `Canonical` to `rustc_type_ir`)
 - rust-lang#117009 (On unresolved imports, suggest a disambiguated path if necessary to avoid collision with local items)
 - rust-lang#117175 (Rename AsyncCoroutineKind to CoroutineSource)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Oct 25, 2023
2 parents ab5c841 + 4e4e561 commit 7ac9a3a
Show file tree
Hide file tree
Showing 59 changed files with 857 additions and 320 deletions.
6 changes: 3 additions & 3 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
e.id,
None,
e.span,
hir::AsyncCoroutineKind::Block,
hir::CoroutineSource::Block,
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
),
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
Expand Down Expand Up @@ -598,7 +598,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
closure_node_id: NodeId,
ret_ty: Option<hir::FnRetTy<'hir>>,
span: Span,
async_gen_kind: hir::AsyncCoroutineKind,
async_gen_kind: hir::CoroutineSource,
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
) -> hir::ExprKind<'hir> {
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
Expand Down Expand Up @@ -1005,7 +1005,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
inner_closure_id,
async_ret_ty,
body.span,
hir::AsyncCoroutineKind::Closure,
hir::CoroutineSource::Closure,
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
);
let hir_id = this.lower_node_id(inner_closure_id);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
closure_id,
None,
body.span,
hir::AsyncCoroutineKind::Fn,
hir::CoroutineSource::Fn,
|this| {
// Create a block from the user's function body:
let user_body = this.lower_block_expr(body);
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_errors::{
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
use rustc_hir::{AsyncCoroutineKind, CoroutineKind, LangItem};
use rustc_hir::{CoroutineKind, CoroutineSource, LangItem};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
Expand Down Expand Up @@ -2506,8 +2506,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let kind = match use_span.coroutine_kind() {
Some(coroutine_kind) => match coroutine_kind {
CoroutineKind::Async(async_kind) => match async_kind {
AsyncCoroutineKind::Block => "async block",
AsyncCoroutineKind::Closure => "async closure",
CoroutineSource::Block => "async block",
CoroutineSource::Closure => "async closure",
_ => bug!("async block/closure expected, but async function found."),
},
CoroutineKind::Coroutine => "coroutine",
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
};
let mir_description = match hir.body(body).coroutine_kind {
Some(hir::CoroutineKind::Async(gen)) => match gen {
hir::AsyncCoroutineKind::Block => " of async block",
hir::AsyncCoroutineKind::Closure => " of async closure",
hir::AsyncCoroutineKind::Fn => {
hir::CoroutineSource::Block => " of async block",
hir::CoroutineSource::Closure => " of async closure",
hir::CoroutineSource::Fn => {
let parent_item =
hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
let output = &parent_item
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
use rustc_hir::{AsyncCoroutineKind, CoroutineKind, Mutability};
use rustc_hir::{CoroutineKind, CoroutineSource, Mutability};
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
Expand Down Expand Up @@ -560,9 +560,9 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &

fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str {
match coroutine_kind {
Some(CoroutineKind::Async(AsyncCoroutineKind::Block)) => "async_block",
Some(CoroutineKind::Async(AsyncCoroutineKind::Closure)) => "async_closure",
Some(CoroutineKind::Async(AsyncCoroutineKind::Fn)) => "async_fn",
Some(CoroutineKind::Async(CoroutineSource::Block)) => "async_block",
Some(CoroutineKind::Async(CoroutineSource::Closure)) => "async_closure",
Some(CoroutineKind::Async(CoroutineSource::Fn)) => "async_fn",
Some(CoroutineKind::Coroutine) => "coroutine",
None => "closure",
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
pub struct Coroutine(pub hir::CoroutineKind);
impl<'tcx> NonConstOp<'tcx> for Coroutine {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
if let hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) = self.0 {
if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 {
Status::Unstable(sym::const_async_blocks)
} else {
Status::Forbidden
Expand All @@ -372,8 +372,8 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
if let hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) = self.0 {
let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
if let hir::CoroutineKind::Async(hir::CoroutineSource::Block) = self.0 {
ccx.tcx.sess.create_feature_err(
errors::UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
Expand Down
51 changes: 20 additions & 31 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,7 @@ impl<'hir> Body<'hir> {
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum CoroutineKind {
/// An explicit `async` block or the body of an async function.
Async(AsyncCoroutineKind),
Async(CoroutineSource),

/// A coroutine literal created via a `yield` inside a closure.
Coroutine,
Expand All @@ -1520,56 +1520,45 @@ pub enum CoroutineKind {
impl fmt::Display for CoroutineKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CoroutineKind::Async(k) => fmt::Display::fmt(k, f),
CoroutineKind::Async(k) => {
if f.alternate() {
f.write_str("`async` ")?;
} else {
f.write_str("async ")?
}
k.fmt(f)
}
CoroutineKind::Coroutine => f.write_str("coroutine"),
}
}
}

impl CoroutineKind {
pub fn descr(&self) -> &'static str {
match self {
CoroutineKind::Async(ask) => ask.descr(),
CoroutineKind::Coroutine => "coroutine",
}
}
}

/// In the case of a coroutine created as part of an async construct,
/// which kind of async construct caused it to be created?
/// In the case of a coroutine created as part of an async/gen construct,
/// which kind of async/gen construct caused it to be created?
///
/// This helps error messages but is also used to drive coercions in
/// type-checking (see #60424).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum AsyncCoroutineKind {
/// An explicit `async` block written by the user.
pub enum CoroutineSource {
/// An explicit `async`/`gen` block written by the user.
Block,

/// An explicit `async` closure written by the user.
/// An explicit `async`/`gen` closure written by the user.
Closure,

/// The `async` block generated as the body of an async function.
/// The `async`/`gen` block generated as the body of an async/gen function.
Fn,
}

impl fmt::Display for AsyncCoroutineKind {
impl fmt::Display for CoroutineSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
AsyncCoroutineKind::Block => "async block",
AsyncCoroutineKind::Closure => "async closure body",
AsyncCoroutineKind::Fn => "async fn body",
})
}
}

impl AsyncCoroutineKind {
pub fn descr(&self) -> &'static str {
match self {
AsyncCoroutineKind::Block => "`async` block",
AsyncCoroutineKind::Closure => "`async` closure body",
AsyncCoroutineKind::Fn => "`async fn` body",
CoroutineSource::Block => "block",
CoroutineSource::Closure => "closure body",
CoroutineSource::Fn => "fn body",
}
.fmt(f)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,44 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
if self.missing_lifetimes() { "lifetime" } else { "generic" }
}

/// Returns true if the generic type is a trait
/// and is being referred to from one of its trait impls
fn is_in_trait_impl(&self) -> bool {
if self.tcx.is_trait(self.def_id) {
// Here we check if the reference to the generic type
// is from the 'of_trait' field of the enclosing impl

let parent = self.tcx.hir().get_parent(self.path_segment.hir_id);
let parent_item = self
.tcx
.hir()
.get_by_def_id(self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id);

// Get the HIR id of the trait ref
let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else {
return false;
};

// Get the HIR id of the 'of_trait' field of the impl
let hir::Node::Item(hir::Item {
kind:
hir::ItemKind::Impl(hir::Impl {
of_trait: Some(hir::TraitRef { hir_ref_id: id_in_of_trait, .. }),
..
}),
..
}) = parent_item
else {
return false;
};

// Check that trait is referred to from the of_trait field of impl
trait_ref_id == id_in_of_trait
} else {
false
}
}

fn num_provided_args(&self) -> usize {
if self.missing_lifetimes() {
self.num_provided_lifetime_args()
Expand Down Expand Up @@ -955,20 +993,26 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
// If there is a single unbound associated type and a single excess generic param
// suggest replacing the generic param with the associated type bound
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
let suggestions = iter::zip(unused_generics, &unbound_types)
.map(|(potential, name)| (potential.span().shrink_to_lo(), format!("{name} = ")))
.collect::<Vec<_>>();
// Don't suggest if we're in a trait impl as
// that would result in invalid syntax (fixes #116464)
if !self.is_in_trait_impl() {
let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
let suggestions = iter::zip(unused_generics, &unbound_types)
.map(|(potential, name)| {
(potential.span().shrink_to_lo(), format!("{name} = "))
})
.collect::<Vec<_>>();

if !suggestions.is_empty() {
err.multipart_suggestion_verbose(
format!(
"replace the generic bound{s} with the associated type{s}",
s = pluralize!(unbound_types.len())
),
suggestions,
Applicability::MaybeIncorrect,
);
if !suggestions.is_empty() {
err.multipart_suggestion_verbose(
format!(
"replace the generic bound{s} with the associated type{s}",
s = pluralize!(unbound_types.len())
),
suggestions,
Applicability::MaybeIncorrect,
);
}
}
} else if remove_entire_generics {
let span = self
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) = (parent_node, callee_node)
{
let fn_decl_span = if hir.body(body).coroutine_kind
== Some(hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Closure))
== Some(hir::CoroutineKind::Async(hir::CoroutineSource::Closure))
{
// Actually need to unwrap one more layer of HIR to get to
// the _real_ closure...
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// In the case of the async block that we create for a function body,
// we expect the return type of the block to match that of the enclosing
// function.
Some(hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Fn)) => {
Some(hir::CoroutineKind::Async(hir::CoroutineSource::Fn)) => {
debug!("closure is async fn body");
let def_id = self.tcx.hir().body_owner_def_id(body.id());
self.deduce_future_output_from_obligations(expr_def_id, def_id).unwrap_or_else(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, GenericParamDefKind, Ty, TyCtxt, UserType,
self, AdtKind, CanonicalUserType, GenericParamDefKind, IsIdentity, Ty, TyCtxt, UserType,
};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef, UserArgs, UserSelfTy};
use rustc_session::lint;
Expand Down Expand Up @@ -207,6 +207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
debug!("fcx {}", self.tag());

// FIXME: is_identity being on `UserType` and not `Canonical<UserType>` is awkward
if !canonical_user_type_annotation.is_identity() {
self.typeck_results
.borrow_mut()
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use rustc_hir::def::Res;
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
AsyncCoroutineKind, CoroutineKind, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath,
Stmt, StmtKind, TyKind, WherePredicate,
CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath, Stmt,
StmtKind, TyKind, WherePredicate,
};
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::traits::{self, StatementAsExpression};
Expand Down Expand Up @@ -536,7 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Coroutine(def_id, ..)
if matches!(
self.tcx.coroutine_kind(def_id),
Some(CoroutineKind::Async(AsyncCoroutineKind::Closure))
Some(CoroutineKind::Async(CoroutineSource::Closure))
) =>
{
errors::SuggestBoxing::AsyncBody
Expand Down
21 changes: 11 additions & 10 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1584,14 +1584,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
target: &str,
types: &FxIndexMap<TyCategory, FxIndexSet<Span>>,
) {
for (key, values) in types.iter() {
for (kind, values) in types.iter() {
let count = values.len();
let kind = key.descr();
for &sp in values {
err.span_label(
sp,
format!(
"{}{} {}{}",
"{}{} {:#}{}",
if count == 1 { "the " } else { "one of the " },
target,
kind,
Expand Down Expand Up @@ -2952,17 +2951,19 @@ pub enum TyCategory {
Foreign,
}

impl TyCategory {
fn descr(&self) -> &'static str {
impl fmt::Display for TyCategory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Closure => "closure",
Self::Opaque => "opaque type",
Self::OpaqueFuture => "future",
Self::Coroutine(gk) => gk.descr(),
Self::Foreign => "foreign type",
Self::Closure => "closure".fmt(f),
Self::Opaque => "opaque type".fmt(f),
Self::OpaqueFuture => "future".fmt(f),
Self::Coroutine(gk) => gk.fmt(f),
Self::Foreign => "foreign type".fmt(f),
}
}
}

impl TyCategory {
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
match *ty.kind() {
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
Expand Down
Loading

0 comments on commit 7ac9a3a

Please sign in to comment.