Skip to content

Commit

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

Rollup of 9 pull requests

Successful merges:

 - rust-lang#108675 (Document `adt_const_params` feature in Unstable Book)
 - rust-lang#122120 (Suggest associated type bounds on problematic associated equality bounds)
 - rust-lang#122589 (Fix diagnostics for async block cloning)
 - rust-lang#122835 (Require `DerefMut` and `DerefPure` on `deref!()` patterns when appropriate)
 - rust-lang#123049 (In `ConstructCoroutineInClosureShim`, pass receiver by mut ref, not mut pointer)
 - rust-lang#123055 (enable cargo miri test doctests)
 - rust-lang#123057 (unix fs: Make hurd using explicit new rather than From)
 - rust-lang#123087 (Change `f16` and `f128` clippy stubs to be nonpanicking)
 - rust-lang#123103 (Rename `Inherited` -> `TypeckRootCtxt`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Mar 26, 2024
2 parents 47ecded + 781b225 commit a1b4991
Show file tree
Hide file tree
Showing 51 changed files with 632 additions and 171 deletions.
16 changes: 13 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![allow(rustc::untranslatable_diagnostic)]

use either::Either;
use hir::ClosureKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
Expand Down Expand Up @@ -463,6 +464,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
{
// We already suggest cloning for these cases in `explain_captures`.
} else if let UseSpans::ClosureUse {
closure_kind:
ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)),
args_span: _,
capture_kind_span: _,
path_span,
} = move_spans
{
self.suggest_cloning(err, ty, expr, path_span);
} else if self.suggest_hoisting_call_outside_loop(err, expr) {
// The place where the the type moves would be misleading to suggest clone.
// #121466
Expand Down Expand Up @@ -621,7 +631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}

// FIXME: We make sure that this is a normal top-level binding,
// but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern
// but we could suggest `todo!()` for all uninitialized bindings in the pattern pattern
if let hir::StmtKind::Let(hir::LetStmt { span, ty, init: None, pat, .. }) =
&ex.kind
&& let hir::PatKind::Binding(..) = pat.kind
Expand Down Expand Up @@ -749,7 +759,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
true
}

/// In a move error that occurs on a call wihtin a loop, we try to identify cases where cloning
/// In a move error that occurs on a call within a loop, we try to identify cases where cloning
/// the value would lead to a logic error. We infer these cases by seeing if the moved value is
/// part of the logic to break the loop, either through an explicit `break` or if the expression
/// is part of a `while let`.
Expand Down Expand Up @@ -950,7 +960,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
{
// FIXME: We could check that the call's *parent* takes `&mut val` to make the
// suggestion more targeted to the `mk_iter(val).next()` case. Maybe do that only to
// check for wheter to suggest `let value` or `let mut value`.
// check for whether to suggest `let value` or `let mut value`.

let span = in_loop.span;
if !finder.found_breaks.is_empty()
Expand Down
22 changes: 8 additions & 14 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2289,21 +2289,15 @@ pub enum ImplItemKind<'hir> {
Type(&'hir Ty<'hir>),
}

/// Bind a type to an associated type (i.e., `A = Foo`).
/// An associated item binding.
///
/// Bindings like `A: Debug` are represented as a special type `A =
/// $::Debug` that is understood by the HIR ty lowering code.
/// ### Examples
///
/// FIXME(alexreg): why have a separate type for the binding case,
/// wouldn't it be better to make the `ty` field an enum like the
/// following?
///
/// ```ignore (pseudo-rust)
/// enum TypeBindingKind {
/// Equals(...),
/// Binding(...),
/// }
/// ```
/// * `Trait<A = Ty, B = Ty>`
/// * `Trait<G<Ty> = Ty>`
/// * `Trait<A: Bound>`
/// * `Trait<C = { Ct }>` (under feature `associated_const_equality`)
/// * `Trait<f(): Bound>` (under feature `return_type_notation`)
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct TypeBinding<'hir> {
pub hir_id: HirId,
Expand Down Expand Up @@ -2336,7 +2330,7 @@ impl<'hir> From<AnonConst> for Term<'hir> {
pub enum TypeBindingKind<'hir> {
/// E.g., `Foo<Bar: Send>`.
Constraint { bounds: &'hir [GenericBound<'hir>] },
/// E.g., `Foo<Bar = ()>`, `Foo<Bar = ()>`
/// E.g., `Foo<Bar = ()>`.
Equality { term: Term<'hir> },
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ language_item_table! {

Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0);
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;

Expand Down
169 changes: 107 additions & 62 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,85 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa
use super::HirTyLowerer;

impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Prohibit or lint against *bare* trait object types depending on the edition.
///
/// *Bare* trait object types are ones that aren't preceeded by the keyword `dyn`.
/// In edition 2021 and onward we emit a hard error for them.
pub(super) fn prohibit_or_lint_bare_trait_object_ty(
&self,
self_ty: &hir::Ty<'_>,
in_path: bool,
) {
let tcx = self.tcx();

let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
self_ty.kind
else {
return;
};

let needs_bracket = in_path
&& !tcx
.sess
.source_map()
.span_to_prev_source(self_ty.span)
.ok()
.is_some_and(|s| s.trim_end().ends_with('<'));

let is_global = poly_trait_ref.trait_ref.path.is_global();

let mut sugg = vec![(
self_ty.span.shrink_to_lo(),
format!(
"{}dyn {}",
if needs_bracket { "<" } else { "" },
if is_global { "(" } else { "" },
),
)];

if is_global || needs_bracket {
sugg.push((
self_ty.span.shrink_to_hi(),
format!(
"{}{}",
if is_global { ")" } else { "" },
if needs_bracket { ">" } else { "" },
),
));
}

if self_ty.span.edition().at_least_rust_2021() {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
let mut diag =
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
if self_ty.span.can_be_used_for_suggestions()
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
{
// FIXME: Only emit this suggestion if the trait is object safe.
diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable);
}
// Check if the impl trait that we are considering is an impl of a local trait.
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
if self_ty.span.can_be_used_for_suggestions() {
lint.multipart_suggestion_verbose(
"if this is an object-safe trait, use `dyn`",
sugg,
Applicability::MachineApplicable,
);
}
self.maybe_suggest_blanket_trait_impl(self_ty, lint);
});
}
}

/// Make sure that we are in the condition to suggest the blanket implementation.
pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
&self,
self_ty: &hir::Ty<'_>,
diag: &mut Diag<'_, G>,
Expand Down Expand Up @@ -75,9 +152,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}

/// Make sure that we are in the condition to suggest `impl Trait`.
fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
let tcx = self.tcx();
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
// FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
// and suggest `Trait0<Ty = impl Trait1>`.
let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
(sig, generics, None)
Expand Down Expand Up @@ -186,71 +265,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
false
}

pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
let tcx = self.tcx();
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
self_ty.kind
{
let needs_bracket = in_path
&& !tcx
.sess
.source_map()
.span_to_prev_source(self_ty.span)
.ok()
.is_some_and(|s| s.trim_end().ends_with('<'));

let is_global = poly_trait_ref.trait_ref.path.is_global();

let mut sugg = Vec::from_iter([(
self_ty.span.shrink_to_lo(),
format!(
"{}dyn {}",
if needs_bracket { "<" } else { "" },
if is_global { "(" } else { "" },
),
)]);
fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) {
let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id);

if is_global || needs_bracket {
sugg.push((
self_ty.span.shrink_to_hi(),
format!(
"{}{}",
if is_global { ")" } else { "" },
if needs_bracket { ">" } else { "" },
),
));
if let Some((_, hir::Node::TypeBinding(binding))) = parents.next()
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(obj_ty) } = binding.kind
{
if let Some((_, hir::Node::TraitRef(..))) = parents.next()
&& let Some((_, hir::Node::Ty(ty))) = parents.next()
&& let hir::TyKind::TraitObject(..) = ty.kind
{
// Assoc ty bounds aren't permitted inside trait object types.
return;
}

if self_ty.span.edition().at_least_rust_2021() {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
let mut diag =
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
if self_ty.span.can_be_used_for_suggestions()
&& !self.maybe_lint_impl_trait(self_ty, &mut diag)
{
diag.multipart_suggestion_verbose(
label,
sugg,
Applicability::MachineApplicable,
);
}
// check if the impl trait that we are considering is a impl of a local trait
self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
let lo = if binding.gen_args.span_ext.is_dummy() {
binding.ident.span
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
if self_ty.span.can_be_used_for_suggestions() {
lint.multipart_suggestion_verbose(
"if this is an object-safe trait, use `dyn`",
sugg,
Applicability::MachineApplicable,
);
}
self.maybe_lint_blanket_trait_impl(self_ty, lint);
});
binding.gen_args.span_ext
};
let hi = obj_ty.span;

if !lo.eq_ctxt(hi) {
return;
}

diag.span_suggestion_verbose(
lo.between(hi),
"you might have meant to write a bound here",
": ",
Applicability::MaybeIncorrect,
);
}
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2339,12 +2339,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
)
}
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
self.maybe_lint_bare_trait(hir_ty, in_path);
self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path);

let repr = match repr {
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar,
};

self.lower_trait_object_ty(
hir_ty.span,
hir_ty.hir_id,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
Some(ret_coercion) => {
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
let ret_ty = self.infcx.shallow_resolve(ret_ty);
self.can_coerce(arm_ty, ret_ty)
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
// The match arms need to unify for the case of `impl Trait`.
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 @@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
bound_vars,
);

let c_result = self.inh.infcx.canonicalize_response(result);
let c_result = self.infcx.canonicalize_response(result);
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);

// Normalize only after registering in `user_provided_sigs`.
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
.any(|n| roots_reachable_from_non_diverging.visited(n));

let infer_var_infos: UnordBag<_> = self
.inh
.infer_var_info
.borrow()
.items()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
let scope_tree = self.tcx.region_scope_tree(def_id);
let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) };
let mut typeck_results = self.inh.typeck_results.borrow_mut();
let mut typeck_results = self.typeck_results.borrow_mut();
typeck_results.rvalue_scopes = rvalue_scopes;
}

Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod suggestions;
use crate::coercion::DynamicCoerceMany;
use crate::fallback::DivergingFallbackBehavior;
use crate::fn_ctxt::checks::DivergingBlockBehavior;
use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited};
use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
use hir::def_id::CRATE_DEF_ID;
use rustc_errors::{DiagCtxt, ErrorGuaranteed};
use rustc_hir as hir;
Expand Down Expand Up @@ -108,7 +108,7 @@ pub struct FnCtxt<'a, 'tcx> {

pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,

pub(super) inh: &'a Inherited<'tcx>,
pub(super) root_ctxt: &'a TypeckRootCtxt<'tcx>,

pub(super) fallback_has_occurred: Cell<bool>,

Expand All @@ -118,12 +118,12 @@ pub struct FnCtxt<'a, 'tcx> {

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn new(
inh: &'a Inherited<'tcx>,
root_ctxt: &'a TypeckRootCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId,
) -> FnCtxt<'a, 'tcx> {
let (diverging_fallback_behavior, diverging_block_behavior) =
parse_never_type_options_attr(inh.tcx);
parse_never_type_options_attr(root_ctxt.tcx);
FnCtxt {
body_id,
param_env,
Expand All @@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
stack: Vec::new(),
by_id: Default::default(),
}),
inh,
root_ctxt,
fallback_has_occurred: Cell::new(false),
diverging_fallback_behavior,
diverging_block_behavior,
Expand Down Expand Up @@ -206,9 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
type Target = Inherited<'tcx>;
type Target = TypeckRootCtxt<'tcx>;
fn deref(&self) -> &Self::Target {
self.inh
self.root_ctxt
}
}

Expand Down
Loading

0 comments on commit a1b4991

Please sign in to comment.