Skip to content

Commit 7caf35b

Browse files
committed
Auto merge of rust-lang#134318 - matthiaskrgr:rollup-jda0jkx, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#132939 (Suggest using deref in patterns) - rust-lang#133293 (Updates Solaris target information, adds Solaris maintainer) - rust-lang#133392 (Fix ICE when multiple supertrait substitutions need assoc but only one is provided) - rust-lang#133986 (Add documentation for anonymous pipe module) - rust-lang#134022 (Doc: Extend for tuples to be stabilized in 1.85.0) - rust-lang#134259 (Clean up `infer_return_ty_for_fn_sig`) - rust-lang#134264 (Arbitrary self types v2: Weak & NonNull diagnostics) r? `@ghost` `@rustbot` modify labels: rollup
2 parents b57d93d + 0f82802 commit 7caf35b

37 files changed

+1152
-329
lines changed

compiler/rustc_hir/src/hir.rs

+16
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,22 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
20252025
}
20262026
}
20272027

2028+
/// Checks if the specified expression needs parentheses for prefix
2029+
/// or postfix suggestions to be valid.
2030+
/// For example, `a + b` requires parentheses to suggest `&(a + b)`,
2031+
/// but just `a` does not.
2032+
/// Similarly, `(a + b).c()` also requires parentheses.
2033+
/// This should not be used for other types of suggestions.
2034+
pub fn expr_needs_parens(expr: &Expr<'_>) -> bool {
2035+
match expr.kind {
2036+
// parenthesize if needed (Issue #46756)
2037+
ExprKind::Cast(_, _) | ExprKind::Binary(_, _, _) => true,
2038+
// parenthesize borrows of range literals (Issue #54505)
2039+
_ if is_range_literal(expr) => true,
2040+
_ => false,
2041+
}
2042+
}
2043+
20282044
#[derive(Debug, Clone, Copy, HashStable_Generic)]
20292045
pub enum ExprKind<'hir> {
20302046
/// Allow anonymous constants from an inline `const` block

compiler/rustc_hir_analysis/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ hir_analysis_invalid_receiver_ty_help =
249249
hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
250250
consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
251251
252+
hir_analysis_invalid_receiver_ty_help_nonnull_note =
253+
`NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
254+
255+
hir_analysis_invalid_receiver_ty_help_weak_note =
256+
`Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
257+
252258
hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
253259
.note = type of `self` must be `Self` or a type that dereferences to it
254260

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use {rustc_ast as ast, rustc_hir as hir};
4444
use crate::autoderef::Autoderef;
4545
use crate::collect::CollectItemTypesVisitor;
4646
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
47+
use crate::errors::InvalidReceiverTyHint;
4748
use crate::{errors, fluent_generated as fluent};
4849

4950
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
@@ -1749,7 +1750,18 @@ fn check_method_receiver<'tcx>(
17491750
{
17501751
match receiver_validity_err {
17511752
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
1752-
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1753+
let hint = match receiver_ty
1754+
.builtin_deref(false)
1755+
.unwrap_or(receiver_ty)
1756+
.ty_adt_def()
1757+
.and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))
1758+
{
1759+
Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),
1760+
Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),
1761+
_ => None,
1762+
};
1763+
1764+
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
17531765
}
17541766
ReceiverValidityError::DoesNotDeref => {
17551767
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {

compiler/rustc_hir_analysis/src/collect.rs

+94-85
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13401340
..
13411341
})
13421342
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
1343-
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
1343+
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
13441344
}
13451345

13461346
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
@@ -1357,7 +1357,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13571357
None,
13581358
)
13591359
} else {
1360-
infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
1360+
lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
13611361
}
13621362
}
13631363

@@ -1407,99 +1407,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
14071407
ty::EarlyBinder::bind(output)
14081408
}
14091409

1410-
fn infer_return_ty_for_fn_sig<'tcx>(
1411-
sig: &hir::FnSig<'tcx>,
1412-
generics: &hir::Generics<'_>,
1410+
fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1411+
icx: &ItemCtxt<'tcx>,
1412+
sig: &'tcx hir::FnSig<'tcx>,
1413+
generics: &'tcx hir::Generics<'tcx>,
14131414
def_id: LocalDefId,
1415+
) -> ty::PolyFnSig<'tcx> {
1416+
if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() {
1417+
return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1418+
}
1419+
1420+
icx.lowerer().lower_fn_ty(
1421+
icx.tcx().local_def_id_to_hir_id(def_id),
1422+
sig.header.safety,
1423+
sig.header.abi,
1424+
sig.decl,
1425+
Some(generics),
1426+
None,
1427+
)
1428+
}
1429+
1430+
fn recover_infer_ret_ty<'tcx>(
14141431
icx: &ItemCtxt<'tcx>,
1432+
infer_ret_ty: &'tcx hir::Ty<'tcx>,
1433+
generics: &'tcx hir::Generics<'tcx>,
1434+
def_id: LocalDefId,
14151435
) -> ty::PolyFnSig<'tcx> {
14161436
let tcx = icx.tcx;
14171437
let hir_id = tcx.local_def_id_to_hir_id(def_id);
14181438

1419-
match sig.decl.output.get_infer_ret_ty() {
1420-
Some(ty) => {
1421-
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1422-
// Typeck doesn't expect erased regions to be returned from `type_of`.
1423-
// This is a heuristic approach. If the scope has region parameters,
1424-
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
1425-
// otherwise to `ReStatic`.
1426-
let has_region_params = generics.params.iter().any(|param| match param.kind {
1427-
GenericParamKind::Lifetime { .. } => true,
1428-
_ => false,
1429-
});
1430-
let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
1431-
ty::ReErased => {
1432-
if has_region_params {
1433-
ty::Region::new_error_with_message(
1434-
tcx,
1435-
DUMMY_SP,
1436-
"erased region is not allowed here in return type",
1437-
)
1438-
} else {
1439-
tcx.lifetimes.re_static
1440-
}
1441-
}
1442-
_ => r,
1443-
});
1439+
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
14441440

1445-
let mut visitor = HirPlaceholderCollector::default();
1446-
visitor.visit_ty(ty);
1447-
1448-
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
1449-
let ret_ty = fn_sig.output();
1450-
// Don't leak types into signatures unless they're nameable!
1451-
// For example, if a function returns itself, we don't want that
1452-
// recursive function definition to leak out into the fn sig.
1453-
let mut recovered_ret_ty = None;
1454-
1455-
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1456-
diag.span_suggestion(
1457-
ty.span,
1458-
"replace with the correct return type",
1459-
suggestable_ret_ty,
1460-
Applicability::MachineApplicable,
1461-
);
1462-
recovered_ret_ty = Some(suggestable_ret_ty);
1463-
} else if let Some(sugg) = suggest_impl_trait(
1464-
&tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1465-
tcx.param_env(def_id),
1466-
ret_ty,
1467-
) {
1468-
diag.span_suggestion(
1469-
ty.span,
1470-
"replace with an appropriate return type",
1471-
sugg,
1472-
Applicability::MachineApplicable,
1473-
);
1474-
} else if ret_ty.is_closure() {
1475-
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1476-
}
1477-
// Also note how `Fn` traits work just in case!
1478-
if ret_ty.is_closure() {
1479-
diag.note(
1480-
"for more information on `Fn` traits and closure types, see \
1481-
https://doc.rust-lang.org/book/ch13-01-closures.html",
1482-
);
1441+
// Typeck doesn't expect erased regions to be returned from `type_of`.
1442+
// This is a heuristic approach. If the scope has region parameters,
1443+
// we should change fn_sig's lifetime from `ReErased` to `ReError`,
1444+
// otherwise to `ReStatic`.
1445+
let has_region_params = generics.params.iter().any(|param| match param.kind {
1446+
GenericParamKind::Lifetime { .. } => true,
1447+
_ => false,
1448+
});
1449+
let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
1450+
ty::ReErased => {
1451+
if has_region_params {
1452+
ty::Region::new_error_with_message(
1453+
tcx,
1454+
DUMMY_SP,
1455+
"erased region is not allowed here in return type",
1456+
)
1457+
} else {
1458+
tcx.lifetimes.re_static
14831459
}
1484-
1485-
let guar = diag.emit();
1486-
ty::Binder::dummy(tcx.mk_fn_sig(
1487-
fn_sig.inputs().iter().copied(),
1488-
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1489-
fn_sig.c_variadic,
1490-
fn_sig.safety,
1491-
fn_sig.abi,
1492-
))
14931460
}
1494-
None => icx.lowerer().lower_fn_ty(
1495-
hir_id,
1496-
sig.header.safety,
1497-
sig.header.abi,
1498-
sig.decl,
1499-
Some(generics),
1500-
None,
1501-
),
1461+
_ => r,
1462+
});
1463+
1464+
let mut visitor = HirPlaceholderCollector::default();
1465+
visitor.visit_ty(infer_ret_ty);
1466+
1467+
let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
1468+
let ret_ty = fn_sig.output();
1469+
1470+
// Don't leak types into signatures unless they're nameable!
1471+
// For example, if a function returns itself, we don't want that
1472+
// recursive function definition to leak out into the fn sig.
1473+
let mut recovered_ret_ty = None;
1474+
if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1475+
diag.span_suggestion(
1476+
infer_ret_ty.span,
1477+
"replace with the correct return type",
1478+
suggestable_ret_ty,
1479+
Applicability::MachineApplicable,
1480+
);
1481+
recovered_ret_ty = Some(suggestable_ret_ty);
1482+
} else if let Some(sugg) = suggest_impl_trait(
1483+
&tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1484+
tcx.param_env(def_id),
1485+
ret_ty,
1486+
) {
1487+
diag.span_suggestion(
1488+
infer_ret_ty.span,
1489+
"replace with an appropriate return type",
1490+
sugg,
1491+
Applicability::MachineApplicable,
1492+
);
1493+
} else if ret_ty.is_closure() {
1494+
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1495+
}
1496+
1497+
// Also note how `Fn` traits work just in case!
1498+
if ret_ty.is_closure() {
1499+
diag.note(
1500+
"for more information on `Fn` traits and closure types, see \
1501+
https://doc.rust-lang.org/book/ch13-01-closures.html",
1502+
);
15021503
}
1504+
let guar = diag.emit();
1505+
ty::Binder::dummy(tcx.mk_fn_sig(
1506+
fn_sig.inputs().iter().copied(),
1507+
recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1508+
fn_sig.c_variadic,
1509+
fn_sig.safety,
1510+
fn_sig.abi,
1511+
))
15031512
}
15041513

15051514
pub fn suggest_impl_trait<'tcx>(

compiler/rustc_hir_analysis/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,14 @@ pub(crate) struct NonConstRange {
16551655
pub span: Span,
16561656
}
16571657

1658+
#[derive(Subdiagnostic)]
1659+
pub(crate) enum InvalidReceiverTyHint {
1660+
#[note(hir_analysis_invalid_receiver_ty_help_weak_note)]
1661+
Weak,
1662+
#[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)]
1663+
NonNull,
1664+
}
1665+
16581666
#[derive(Diagnostic)]
16591667
#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
16601668
#[note]
@@ -1673,6 +1681,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
16731681
#[primary_span]
16741682
pub span: Span,
16751683
pub receiver_ty: Ty<'tcx>,
1684+
#[subdiagnostic]
1685+
pub hint: Option<InvalidReceiverTyHint>,
16761686
}
16771687

16781688
#[derive(Diagnostic)]

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+28-24
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1+
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
22
use rustc_errors::codes::*;
33
use rustc_errors::struct_span_code_err;
44
use rustc_hir as hir;
55
use rustc_hir::def::{DefKind, Res};
6-
use rustc_hir::def_id::DefId;
76
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
87
use rustc_middle::span_bug;
98
use rustc_middle::ty::fold::BottomUpFolder;
109
use rustc_middle::ty::{
1110
self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
1211
TypeVisitableExt, Upcast,
1312
};
14-
use rustc_span::{ErrorGuaranteed, Span};
13+
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
1514
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
1615
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
1716
use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
@@ -128,8 +127,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
128127
}
129128
}
130129

131-
let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default();
130+
let mut needed_associated_types = FxIndexSet::default();
132131

132+
let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1);
133133
let regular_traits_refs_spans = trait_bounds
134134
.into_iter()
135135
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
@@ -145,13 +145,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
145145
let bound_predicate = pred.kind();
146146
match bound_predicate.skip_binder() {
147147
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
148-
let pred = bound_predicate.rebind(pred);
149-
associated_types.entry(original_span).or_default().extend(
150-
tcx.associated_items(pred.def_id())
148+
// FIXME(negative_bounds): Handle this correctly...
149+
let trait_ref =
150+
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
151+
needed_associated_types.extend(
152+
tcx.associated_items(trait_ref.def_id())
151153
.in_definition_order()
152154
.filter(|item| item.kind == ty::AssocKind::Type)
153155
.filter(|item| !item.is_impl_trait_in_trait())
154-
.map(|item| item.def_id),
156+
// If the associated type has a `where Self: Sized` bound,
157+
// we do not need to constrain the associated type.
158+
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
159+
.map(|item| (item.def_id, trait_ref)),
155160
);
156161
}
157162
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
@@ -201,26 +206,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
201206
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
202207
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
203208
// corresponding `Projection` clause
204-
for def_ids in associated_types.values_mut() {
205-
for (projection_bound, span) in &projection_bounds {
206-
let def_id = projection_bound.item_def_id();
207-
def_ids.swap_remove(&def_id);
208-
if tcx.generics_require_sized_self(def_id) {
209-
tcx.emit_node_span_lint(
210-
UNUSED_ASSOCIATED_TYPE_BOUNDS,
211-
hir_id,
212-
*span,
213-
crate::errors::UnusedAssociatedTypeBounds { span: *span },
214-
);
215-
}
209+
for (projection_bound, span) in &projection_bounds {
210+
let def_id = projection_bound.item_def_id();
211+
let trait_ref = tcx.anonymize_bound_vars(
212+
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
213+
);
214+
needed_associated_types.swap_remove(&(def_id, trait_ref));
215+
if tcx.generics_require_sized_self(def_id) {
216+
tcx.emit_node_span_lint(
217+
UNUSED_ASSOCIATED_TYPE_BOUNDS,
218+
hir_id,
219+
*span,
220+
crate::errors::UnusedAssociatedTypeBounds { span: *span },
221+
);
216222
}
217-
// If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
218-
// type in the `dyn Trait`.
219-
def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
220223
}
221224

222225
if let Err(guar) = self.check_for_required_assoc_tys(
223-
associated_types,
226+
principal_span,
227+
needed_associated_types,
224228
potential_assoc_types,
225229
hir_trait_bounds,
226230
) {

0 commit comments

Comments
 (0)