Skip to content

Commit 28532a6

Browse files
authored
Unrolled build for rust-lang#138126
Rollup merge of rust-lang#138126 - compiler-errors:rtn-for-sugg, r=oli-obk Add an opt-out in pretty printing for RTN rendering Today, we render RPITIT types like `impl Sized { T::method(..) }` when RTN is enabled. This is very useful for diagnostics, since it's often not clear what the `impl Sized` type means by itself, and it makes it clear that that's an RPITIT that can be bounded using RTN syntax. See rust-lang#115624. However, since we don't distinguish types that are rendered for the purposes of printing messages vs suggestions, this representation leaks into suggestions and turns into code that can't be parsed. This PR adds a new `with_types_for_suggestion! {}` and `with_types_for_signature! {}` options to the pretty printing architecture to make it clear that we're rendering a type for code suggestions. This can be applied later as we find that we need it.
2 parents 52daa7d + 7a08d03 commit 28532a6

File tree

8 files changed

+152
-30
lines changed

8 files changed

+152
-30
lines changed

compiler/rustc_hir_analysis/src/check/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _};
8484
use rustc_infer::traits::ObligationCause;
8585
use rustc_middle::query::Providers;
8686
use rustc_middle::ty::error::{ExpectedFound, TypeError};
87+
use rustc_middle::ty::print::with_types_for_signature;
8788
use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
8889
use rustc_middle::{bug, span_bug};
8990
use rustc_session::parse::feature_err;
@@ -240,11 +241,11 @@ fn missing_items_err(
240241
(Vec::new(), Vec::new(), Vec::new());
241242

242243
for &trait_item in missing_items {
243-
let snippet = suggestion_signature(
244+
let snippet = with_types_for_signature!(suggestion_signature(
244245
tcx,
245246
trait_item,
246247
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
247-
);
248+
));
248249
let code = format!("{padding}{snippet}\n{padding}");
249250
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
250251
missing_trait_item_label

compiler/rustc_middle/src/ty/print/pretty.rs

+92-25
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ thread_local! {
6363
static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
6464
static REDUCED_QUERIES: Cell<bool> = const { Cell::new(false) };
6565
static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
66+
static RTN_MODE: Cell<RtnMode> = const { Cell::new(RtnMode::ForDiagnostic) };
67+
}
68+
69+
/// Rendering style for RTN types.
70+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
71+
pub enum RtnMode {
72+
/// Print the RTN type as an impl trait with its path, i.e.e `impl Sized { T::method(..) }`.
73+
ForDiagnostic,
74+
/// Print the RTN type as an impl trait, i.e. `impl Sized`.
75+
ForSignature,
76+
/// Print the RTN type as a value path, i.e. `T::method(..): ...`.
77+
ForSuggestion,
6678
}
6779

6880
macro_rules! define_helper {
@@ -124,6 +136,38 @@ define_helper!(
124136
fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
125137
);
126138

139+
#[must_use]
140+
pub struct RtnModeHelper(RtnMode);
141+
142+
impl RtnModeHelper {
143+
pub fn with(mode: RtnMode) -> RtnModeHelper {
144+
RtnModeHelper(RTN_MODE.with(|c| c.replace(mode)))
145+
}
146+
}
147+
148+
impl Drop for RtnModeHelper {
149+
fn drop(&mut self) {
150+
RTN_MODE.with(|c| c.set(self.0))
151+
}
152+
}
153+
154+
/// Print types for the purposes of a suggestion.
155+
///
156+
/// Specifically, this will render RPITITs as `T::method(..)` which is suitable for
157+
/// things like where-clauses.
158+
pub macro with_types_for_suggestion($e:expr) {{
159+
let _guard = $crate::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSuggestion);
160+
$e
161+
}}
162+
163+
/// Print types for the purposes of a signature suggestion.
164+
///
165+
/// Specifically, this will render RPITITs as `impl Trait` rather than `T::method(..)`.
166+
pub macro with_types_for_signature($e:expr) {{
167+
let _guard = $crate::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSignature);
168+
$e
169+
}}
170+
127171
/// Avoids running any queries during prints.
128172
pub macro with_no_queries($e:expr) {{
129173
$crate::ty::print::with_reduced_queries!($crate::ty::print::with_forced_impl_filename_line!(
@@ -1223,22 +1267,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
12231267
}
12241268
}
12251269

1226-
if self.tcx().features().return_type_notation()
1227-
&& let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
1228-
self.tcx().opt_rpitit_info(def_id)
1229-
&& let ty::Alias(_, alias_ty) =
1230-
self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind()
1231-
&& alias_ty.def_id == def_id
1232-
&& let generics = self.tcx().generics_of(fn_def_id)
1233-
// FIXME(return_type_notation): We only support lifetime params for now.
1234-
&& generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime))
1235-
{
1236-
let num_args = generics.count();
1237-
write!(self, " {{ ")?;
1238-
self.print_def_path(fn_def_id, &args[..num_args])?;
1239-
write!(self, "(..) }}")?;
1240-
}
1241-
12421270
Ok(())
12431271
}
12441272

@@ -1306,6 +1334,46 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
13061334
)
13071335
}
13081336

1337+
fn pretty_print_rpitit(
1338+
&mut self,
1339+
def_id: DefId,
1340+
args: ty::GenericArgsRef<'tcx>,
1341+
) -> Result<(), PrintError> {
1342+
let fn_args = if self.tcx().features().return_type_notation()
1343+
&& let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
1344+
self.tcx().opt_rpitit_info(def_id)
1345+
&& let ty::Alias(_, alias_ty) =
1346+
self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind()
1347+
&& alias_ty.def_id == def_id
1348+
&& let generics = self.tcx().generics_of(fn_def_id)
1349+
// FIXME(return_type_notation): We only support lifetime params for now.
1350+
&& generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime))
1351+
{
1352+
let num_args = generics.count();
1353+
Some((fn_def_id, &args[..num_args]))
1354+
} else {
1355+
None
1356+
};
1357+
1358+
match (fn_args, RTN_MODE.with(|c| c.get())) {
1359+
(Some((fn_def_id, fn_args)), RtnMode::ForDiagnostic) => {
1360+
self.pretty_print_opaque_impl_type(def_id, args)?;
1361+
write!(self, " {{ ")?;
1362+
self.print_def_path(fn_def_id, fn_args)?;
1363+
write!(self, "(..) }}")?;
1364+
}
1365+
(Some((fn_def_id, fn_args)), RtnMode::ForSuggestion) => {
1366+
self.print_def_path(fn_def_id, fn_args)?;
1367+
write!(self, "(..)")?;
1368+
}
1369+
_ => {
1370+
self.pretty_print_opaque_impl_type(def_id, args)?;
1371+
}
1372+
}
1373+
1374+
Ok(())
1375+
}
1376+
13091377
fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
13101378
None
13111379
}
@@ -3123,22 +3191,21 @@ define_print! {
31233191
ty::AliasTerm<'tcx> {
31243192
match self.kind(cx.tcx()) {
31253193
ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
3126-
ty::AliasTermKind::ProjectionTy
3127-
| ty::AliasTermKind::WeakTy
3128-
| ty::AliasTermKind::OpaqueTy
3129-
| ty::AliasTermKind::UnevaluatedConst
3130-
| ty::AliasTermKind::ProjectionConst => {
3131-
// If we're printing verbosely, or don't want to invoke queries
3132-
// (`is_impl_trait_in_trait`), then fall back to printing the def path.
3133-
// This is likely what you want if you're debugging the compiler anyways.
3194+
ty::AliasTermKind::ProjectionTy => {
31343195
if !(cx.should_print_verbose() || with_reduced_queries())
31353196
&& cx.tcx().is_impl_trait_in_trait(self.def_id)
31363197
{
3137-
return cx.pretty_print_opaque_impl_type(self.def_id, self.args);
3198+
p!(pretty_print_rpitit(self.def_id, self.args))
31383199
} else {
31393200
p!(print_def_path(self.def_id, self.args));
31403201
}
31413202
}
3203+
| ty::AliasTermKind::WeakTy
3204+
| ty::AliasTermKind::OpaqueTy
3205+
| ty::AliasTermKind::UnevaluatedConst
3206+
| ty::AliasTermKind::ProjectionConst => {
3207+
p!(print_def_path(self.def_id, self.args));
3208+
}
31423209
}
31433210
}
31443211

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_middle::traits::IsConstable;
2626
use rustc_middle::ty::error::TypeError;
2727
use rustc_middle::ty::print::{
2828
PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _,
29-
with_forced_trimmed_paths, with_no_trimmed_paths,
29+
with_forced_trimmed_paths, with_no_trimmed_paths, with_types_for_suggestion,
3030
};
3131
use rustc_middle::ty::{
3232
self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder,
@@ -110,7 +110,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
110110
fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
111111
(
112112
generics.tail_span_for_predicate_suggestion(),
113-
format!("{} {}", generics.add_where_or_trailing_comma(), pred),
113+
with_types_for_suggestion!(format!("{} {}", generics.add_where_or_trailing_comma(), pred)),
114114
)
115115
}
116116

@@ -136,7 +136,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
136136
if hir_generics.where_clause_span.from_expansion()
137137
|| hir_generics.where_clause_span.desugaring_kind().is_some()
138138
|| projection.is_some_and(|projection| {
139-
tcx.is_impl_trait_in_trait(projection.def_id)
139+
(tcx.is_impl_trait_in_trait(projection.def_id)
140+
&& !tcx.features().return_type_notation())
140141
|| tcx.lookup_stability(projection.def_id).is_some_and(|stab| stab.is_unstable())
141142
})
142143
{

tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ note: required by a bound in `is_send`
1515
|
1616
LL | fn is_send(_: impl Send) {}
1717
| ^^^^ required by this bound in `is_send`
18+
help: consider further restricting the associated type
19+
|
20+
LL | >() where <T as Foo>::method(..): Send {
21+
| ++++++++++++++++++++++++++++++++++
1822

1923
error: aborting due to 1 previous error
2024

tests/ui/associated-type-bounds/return-type-notation/display.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ note: required by a bound in `needs_trait`
1111
|
1212
LL | fn needs_trait(_: impl Trait) {}
1313
| ^^^^^ required by this bound in `needs_trait`
14+
help: consider further restricting the associated type
15+
|
16+
LL | fn foo<T: Assoc>(t: T) where <T as Assoc>::method(..): Trait {
17+
| +++++++++++++++++++++++++++++++++++++
1418

1519
error[E0277]: the trait bound `impl Sized { <T as Assoc>::method_with_lt(..) }: Trait` is not satisfied
1620
--> $DIR/display.rs:16:17
@@ -25,6 +29,10 @@ note: required by a bound in `needs_trait`
2529
|
2630
LL | fn needs_trait(_: impl Trait) {}
2731
| ^^^^^ required by this bound in `needs_trait`
32+
help: consider further restricting the associated type
33+
|
34+
LL | fn foo<T: Assoc>(t: T) where <T as Assoc>::method_with_lt(..): Trait {
35+
| +++++++++++++++++++++++++++++++++++++++++++++
2836

2937
error[E0277]: the trait bound `impl Sized: Trait` is not satisfied
3038
--> $DIR/display.rs:18:17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ run-rustfix
2+
3+
#![allow(unused)]
4+
#![feature(return_type_notation)]
5+
6+
trait Foo {
7+
fn missing() -> impl Sized;
8+
}
9+
10+
impl Foo for () {
11+
//~^ ERROR not all trait items implemented, missing: `missing`
12+
fn missing() -> impl Sized { todo!() }
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ run-rustfix
2+
3+
#![allow(unused)]
4+
#![feature(return_type_notation)]
5+
6+
trait Foo {
7+
fn missing() -> impl Sized;
8+
}
9+
10+
impl Foo for () {
11+
//~^ ERROR not all trait items implemented, missing: `missing`
12+
}
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0046]: not all trait items implemented, missing: `missing`
2+
--> $DIR/rendering.rs:10:1
3+
|
4+
LL | fn missing() -> impl Sized;
5+
| --------------------------- `missing` from trait
6+
...
7+
LL | impl Foo for () {
8+
| ^^^^^^^^^^^^^^^ missing `missing` in implementation
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0046`.

0 commit comments

Comments
 (0)