Skip to content

Commit 268d625

Browse files
committed
Auto merge of #116384 - matthiaskrgr:rollup-se332zs, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #114654 (Suggest `pin!()` instead of `Pin::new()` when appropriate) - #116261 (a small wf and clause cleanup) - #116282 (Fix broken links) - #116328 (Factor out common token generation in `fluent_messages`.) - #116379 (non_lifetime_binders: fix ICE in lint opaque-hidden-inferred-bound) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e3c631b + 9143370 commit 268d625

File tree

25 files changed

+242
-174
lines changed

25 files changed

+242
-174
lines changed

compiler/rustc_fluent_macro/src/fluent.rs

+20-38
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,35 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
4040
}
4141
}
4242

43-
/// Tokens to be returned when the macro cannot proceed.
44-
fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
43+
/// Final tokens.
44+
fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream {
4545
quote! {
46-
pub static DEFAULT_LOCALE_RESOURCE: &'static str = "";
46+
/// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro,
47+
/// imported by `rustc_driver` to include all crates' resources in one bundle.
48+
pub static DEFAULT_LOCALE_RESOURCE: &'static str = #resource;
4749

4850
#[allow(non_upper_case_globals)]
4951
#[doc(hidden)]
52+
/// Auto-generated constants for type-checked references to Fluent messages.
5053
pub(crate) mod fluent_generated {
51-
pub mod #crate_name {
52-
}
54+
#body
5355

56+
/// Constants expected to exist by the diagnostic derive macros to use as default Fluent
57+
/// identifiers for different subdiagnostic kinds.
5458
pub mod _subdiag {
59+
/// Default for `#[help]`
5560
pub const help: crate::SubdiagnosticMessage =
5661
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
62+
/// Default for `#[note]`
5763
pub const note: crate::SubdiagnosticMessage =
5864
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
65+
/// Default for `#[warn]`
5966
pub const warn: crate::SubdiagnosticMessage =
6067
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
68+
/// Default for `#[label]`
6169
pub const label: crate::SubdiagnosticMessage =
6270
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
71+
/// Default for `#[suggestion]`
6372
pub const suggestion: crate::SubdiagnosticMessage =
6473
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
6574
}
@@ -68,6 +77,11 @@ fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
6877
.into()
6978
}
7079

80+
/// Tokens to be returned when the macro cannot proceed.
81+
fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
82+
finish(quote! { pub mod #crate_name {} }, quote! { "" })
83+
}
84+
7185
/// See [rustc_fluent_macro::fluent_messages].
7286
pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
7387
let crate_name = std::env::var("CARGO_PKG_NAME")
@@ -311,39 +325,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
311325
}
312326
}
313327

314-
quote! {
315-
/// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro,
316-
/// imported by `rustc_driver` to include all crates' resources in one bundle.
317-
pub static DEFAULT_LOCALE_RESOURCE: &'static str = include_str!(#relative_ftl_path);
318-
319-
#[allow(non_upper_case_globals)]
320-
#[doc(hidden)]
321-
/// Auto-generated constants for type-checked references to Fluent messages.
322-
pub(crate) mod fluent_generated {
323-
#constants
324-
325-
/// Constants expected to exist by the diagnostic derive macros to use as default Fluent
326-
/// identifiers for different subdiagnostic kinds.
327-
pub mod _subdiag {
328-
/// Default for `#[help]`
329-
pub const help: crate::SubdiagnosticMessage =
330-
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
331-
/// Default for `#[note]`
332-
pub const note: crate::SubdiagnosticMessage =
333-
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
334-
/// Default for `#[warn]`
335-
pub const warn: crate::SubdiagnosticMessage =
336-
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
337-
/// Default for `#[label]`
338-
pub const label: crate::SubdiagnosticMessage =
339-
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
340-
/// Default for `#[suggestion]`
341-
pub const suggestion: crate::SubdiagnosticMessage =
342-
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
343-
}
344-
}
345-
}
346-
.into()
328+
finish(constants, quote! { include_str!(#relative_ftl_path) })
347329
}
348330

349331
fn variable_references<'a>(msg: &Message<&'a str>) -> Vec<&'a str> {

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_infer::traits::util;
1616
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1717
use rustc_middle::ty::fold::BottomUpFolder;
1818
use rustc_middle::ty::util::ExplicitSelf;
19+
use rustc_middle::ty::ToPredicate;
1920
use rustc_middle::ty::{
2021
self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
2122
};
@@ -2279,16 +2280,16 @@ pub(super) fn check_type_bounds<'tcx>(
22792280
//
22802281
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
22812282
}
2282-
_ => predicates.push(ty::Clause::from_projection_clause(
2283-
tcx,
2283+
_ => predicates.push(
22842284
ty::Binder::bind_with_vars(
22852285
ty::ProjectionPredicate {
22862286
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
22872287
term: normalize_impl_ty.into(),
22882288
},
22892289
bound_vars,
2290-
),
2291-
)),
2290+
)
2291+
.to_predicate(tcx),
2292+
),
22922293
};
22932294
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
22942295
};

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1130,11 +1130,11 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
11301130
let wf_obligations =
11311131
bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
11321132
let normalized_bound = wfcx.normalize(span, None, bound);
1133-
traits::wf::predicate_obligations(
1133+
traits::wf::clause_obligations(
11341134
wfcx.infcx,
11351135
wfcx.param_env,
11361136
wfcx.body_def_id,
1137-
normalized_bound.as_predicate(),
1137+
normalized_bound,
11381138
bound_span,
11391139
)
11401140
});
@@ -1234,7 +1234,7 @@ fn check_impl<'tcx>(
12341234
wfcx.infcx,
12351235
wfcx.param_env,
12361236
wfcx.body_def_id,
1237-
&trait_pred,
1237+
trait_pred,
12381238
ast_trait_ref.path.span,
12391239
item,
12401240
);
@@ -1443,13 +1443,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
14431443
debug!(?predicates.predicates);
14441444
assert_eq!(predicates.predicates.len(), predicates.spans.len());
14451445
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
1446-
traits::wf::predicate_obligations(
1447-
infcx,
1448-
wfcx.param_env,
1449-
wfcx.body_def_id,
1450-
p.as_predicate(),
1451-
sp,
1452-
)
1446+
traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
14531447
});
14541448
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
14551449
wfcx.register_obligations(obligations);

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

+23-37
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,9 @@ fn check_predicates<'tcx>(
376376
let always_applicable_traits = impl1_predicates
377377
.iter()
378378
.copied()
379-
.filter(|(clause, _span)| {
379+
.filter(|&(clause, _span)| {
380380
matches!(
381-
trait_predicate_kind(tcx, clause.as_predicate()),
381+
trait_specialization_kind(tcx, clause),
382382
Some(TraitSpecializationKind::AlwaysApplicable)
383383
)
384384
})
@@ -402,7 +402,7 @@ fn check_predicates<'tcx>(
402402
.iter()
403403
.any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
404404
{
405-
check_specialization_on(tcx, clause.as_predicate(), span)
405+
check_specialization_on(tcx, clause, span)
406406
}
407407
}
408408
}
@@ -441,19 +441,16 @@ fn trait_predicates_eq<'tcx>(
441441
}
442442

443443
#[instrument(level = "debug", skip(tcx))]
444-
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) {
445-
match predicate.kind().skip_binder() {
444+
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) {
445+
match clause.kind().skip_binder() {
446446
// Global predicates are either always true or always false, so we
447447
// are fine to specialize on.
448-
_ if predicate.is_global() => (),
448+
_ if clause.is_global() => (),
449449
// We allow specializing on explicitly marked traits with no associated
450450
// items.
451-
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
452-
trait_ref,
453-
polarity: _,
454-
})) => {
451+
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
455452
if !matches!(
456-
trait_predicate_kind(tcx, predicate),
453+
trait_specialization_kind(tcx, clause),
457454
Some(TraitSpecializationKind::Marker)
458455
) {
459456
tcx.sess
@@ -467,18 +464,15 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
467464
.emit();
468465
}
469466
}
470-
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
471-
projection_ty,
472-
term,
473-
})) => {
467+
ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
474468
tcx.sess
475469
.struct_span_err(
476470
span,
477471
format!("cannot specialize on associated type `{projection_ty} == {term}`",),
478472
)
479473
.emit();
480474
}
481-
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
475+
ty::ClauseKind::ConstArgHasType(..) => {
482476
// FIXME(min_specialization), FIXME(const_generics):
483477
// It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
484478
// about the actual rules that would be sound. Can't just always error here because otherwise
@@ -490,33 +484,25 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
490484
}
491485
_ => {
492486
tcx.sess
493-
.struct_span_err(span, format!("cannot specialize on predicate `{predicate}`"))
487+
.struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
494488
.emit();
495489
}
496490
}
497491
}
498492

499-
fn trait_predicate_kind<'tcx>(
493+
fn trait_specialization_kind<'tcx>(
500494
tcx: TyCtxt<'tcx>,
501-
predicate: ty::Predicate<'tcx>,
495+
clause: ty::Clause<'tcx>,
502496
) -> Option<TraitSpecializationKind> {
503-
match predicate.kind().skip_binder() {
504-
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
505-
trait_ref,
506-
polarity: _,
507-
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
508-
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
509-
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
510-
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(_))
511-
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
512-
| ty::PredicateKind::AliasRelate(..)
513-
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
514-
| ty::PredicateKind::Subtype(_)
515-
| ty::PredicateKind::Coerce(_)
516-
| ty::PredicateKind::ObjectSafe(_)
517-
| ty::PredicateKind::ClosureKind(..)
518-
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
519-
| ty::PredicateKind::ConstEquate(..)
520-
| ty::PredicateKind::Ambiguous => None,
497+
match clause.kind().skip_binder() {
498+
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
499+
Some(tcx.trait_def(trait_ref.def_id).specialization_kind)
500+
}
501+
ty::ClauseKind::RegionOutlives(_)
502+
| ty::ClauseKind::TypeOutlives(_)
503+
| ty::ClauseKind::Projection(_)
504+
| ty::ClauseKind::ConstArgHasType(..)
505+
| ty::ClauseKind::WellFormed(_)
506+
| ty::ClauseKind::ConstEvaluatable(..) => None,
521507
}
522508
}

compiler/rustc_hir_typeck/src/method/suggest.rs

+68-6
Original file line numberDiff line numberDiff line change
@@ -2494,10 +2494,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24942494
// Try alternative arbitrary self types that could fulfill this call.
24952495
// FIXME: probe for all types that *could* be arbitrary self-types, not
24962496
// just this list.
2497-
for (rcvr_ty, post) in &[
2498-
(rcvr_ty, ""),
2499-
(Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
2500-
(Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
2497+
for (rcvr_ty, post, pin_call) in &[
2498+
(rcvr_ty, "", None),
2499+
(
2500+
Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
2501+
"&mut ",
2502+
Some("as_mut"),
2503+
),
2504+
(
2505+
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
2506+
"&",
2507+
Some("as_ref"),
2508+
),
25012509
] {
25022510
match self.lookup_probe_for_diagnostic(
25032511
item_name,
@@ -2531,6 +2539,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25312539
Err(_) => (),
25322540
}
25332541

2542+
let pred = ty::TraitRef::new(
2543+
self.tcx,
2544+
self.tcx.lang_items().unpin_trait().unwrap(),
2545+
[*rcvr_ty],
2546+
);
2547+
let unpin = self.predicate_must_hold_considering_regions(&Obligation::new(
2548+
self.tcx,
2549+
ObligationCause::misc(rcvr.span, self.body_id),
2550+
self.param_env,
2551+
pred,
2552+
));
25342553
for (rcvr_ty, pre) in &[
25352554
(Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::OwnedBox), "Box::new"),
25362555
(Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin), "Pin::new"),
@@ -2554,7 +2573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25542573
// Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
25552574
// implement the `AsRef` trait.
25562575
let skip = skippable.contains(&did)
2557-
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
2576+
|| (("Pin::new" == *pre) && ((sym::as_ref == item_name.name) || !unpin))
25582577
|| inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
25592578
// Make sure the method is defined for the *actual* receiver: we don't
25602579
// want to treat `Box<Self>` as a receiver if it only works because of
@@ -2566,7 +2585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25662585
);
25672586
err.multipart_suggestion(
25682587
"consider wrapping the receiver expression with the \
2569-
appropriate type",
2588+
appropriate type",
25702589
vec![
25712590
(rcvr.span.shrink_to_lo(), format!("{pre}({post}")),
25722591
(rcvr.span.shrink_to_hi(), ")".to_string()),
@@ -2578,6 +2597,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25782597
}
25792598
}
25802599
}
2600+
// We special case the situation where `Pin::new` wouldn't work, and instead
2601+
// suggest using the `pin!()` macro instead.
2602+
if let Some(new_rcvr_t) = Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin)
2603+
// We didn't find an alternative receiver for the method.
2604+
&& !alt_rcvr_sugg
2605+
// `T: !Unpin`
2606+
&& !unpin
2607+
// The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`.
2608+
&& sym::as_ref != item_name.name
2609+
// Either `Pin::as_ref` or `Pin::as_mut`.
2610+
&& let Some(pin_call) = pin_call
2611+
// Search for `item_name` as a method accessible on `Pin<T>`.
2612+
&& let Ok(pick) = self.lookup_probe_for_diagnostic(
2613+
item_name,
2614+
new_rcvr_t,
2615+
rcvr,
2616+
ProbeScope::AllTraits,
2617+
return_type,
2618+
)
2619+
// We skip some common traits that we don't want to consider because autoderefs
2620+
// would take care of them.
2621+
&& !skippable.contains(&Some(pick.item.container_id(self.tcx)))
2622+
// We don't want to go through derefs.
2623+
&& pick.autoderefs == 0
2624+
// Check that the method of the same name that was found on the new `Pin<T>`
2625+
// receiver has the same number of arguments that appear in the user's code.
2626+
&& inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
2627+
{
2628+
let indent = self.tcx.sess
2629+
.source_map()
2630+
.indentation_before(rcvr.span)
2631+
.unwrap_or_else(|| " ".to_string());
2632+
err.multipart_suggestion(
2633+
"consider pinning the expression",
2634+
vec![
2635+
(rcvr.span.shrink_to_lo(), format!("let mut pinned = std::pin::pin!(")),
2636+
(rcvr.span.shrink_to_hi(), format!(");\n{indent}pinned.{pin_call}()")),
2637+
],
2638+
Applicability::MaybeIncorrect,
2639+
);
2640+
// We don't care about the other suggestions.
2641+
alt_rcvr_sugg = true;
2642+
}
25812643
}
25822644
}
25832645
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {

0 commit comments

Comments
 (0)