Skip to content

Commit 7b36e60

Browse files
authored
Rollup merge of rust-lang#129629 - compiler-errors:rtn-in-path, r=jackh726
Implement Return Type Notation (RTN)'s path form in where clauses Implement return type notation (RTN) in path position for where clauses. We already had RTN in associated type position ([e.g.](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=627a4fb8e2cb334863fbd08ed3722c09)), but per [the RFC](https://rust-lang.github.io/rfcs/3654-return-type-notation.html#where-rtn-can-be-used-for-now): > As a standalone type, RTN can only be used as the Self type of a where-clause [...] Specifically, in order to enable code like: ```rust trait Foo { fn bar() -> impl Sized; } fn is_send(_: impl Send) {} fn test<T>() where T: Foo, T::bar(..): Send, { is_send(T::bar()); } ``` * In the resolver, when we see a `TyKind::Path` whose final segment is `GenericArgs::ParenthesizedElided` (i.e. `(..)`), resolve that path in the *value* namespace, since we're looking for a method. * When lowering where clauses in HIR lowering, we first try to intercept an RTN self type via `lower_ty_maybe_return_type_notation`. If we find an RTN type, we lower it manually in a way that respects its higher-ranked-ness (see below) and resolves to the corresponding RPITIT. Anywhere else, we'll emit the same "return type notation not allowed in this position yet" error we do when writing RTN in every other position. * In `resolve_bound_vars`, we add some special treatment for RTN types in where clauses. Specifically, we need to add new lifetime variables to our binders for the early- and late-bound vars we encounter on the method. This implements the higher-ranked desugaring [laid out in the RFC](https://rust-lang.github.io/rfcs/3654-return-type-notation.html#converting-to-higher-ranked-trait-bounds). This PR also adds a bunch of tests, mostly negative ones (testing error messages). In a follow-up PR, I'm going to mark RTN as no longer incomplete, since this PR basically finishes the impl surface that we should initially stabilize, and the RFC was accepted. cc [RFC 3654](rust-lang/rfcs#3654) and rust-lang#109417
2 parents bc8631e + 1de894f commit 7b36e60

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1493
-229
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use super::errors::{
2020
};
2121
use super::LoweringContext;
2222
use crate::{
23-
fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode,
24-
ResolverAstLoweringExt,
23+
fluent_generated as fluent, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition,
24+
ParamMode, ResolverAstLoweringExt,
2525
};
2626

2727
impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -201,6 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
201201
&sym.qself,
202202
&sym.path,
203203
ParamMode::Optional,
204+
AllowReturnTypeNotation::No,
204205
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
205206
None,
206207
);

compiler/rustc_ast_lowering/src/delegation.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use rustc_target::spec::abi;
5252
use {rustc_ast as ast, rustc_hir as hir};
5353

5454
use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
55-
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
55+
use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
5656

5757
pub(crate) struct DelegationResults<'hir> {
5858
pub body_id: hir::BodyId,
@@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
340340
&delegation.qself,
341341
&delegation.path,
342342
ParamMode::Optional,
343+
AllowReturnTypeNotation::No,
343344
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
344345
None,
345346
);

compiler/rustc_ast_lowering/src/expr.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use super::{
2323
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
2424
};
2525
use crate::errors::YieldInClosure;
26-
use crate::{fluent_generated, FnDeclKind, ImplTraitPosition};
26+
use crate::{fluent_generated, AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition};
2727

2828
impl<'hir> LoweringContext<'_, 'hir> {
2929
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
281281
qself,
282282
path,
283283
ParamMode::Optional,
284+
AllowReturnTypeNotation::No,
284285
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
285286
None,
286287
);
@@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
328329
&se.qself,
329330
&se.path,
330331
ParamMode::Optional,
332+
AllowReturnTypeNotation::No,
331333
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
332334
None,
333335
)),
@@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12911293
qself,
12921294
path,
12931295
ParamMode::Optional,
1296+
AllowReturnTypeNotation::No,
12941297
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
12951298
None,
12961299
);
@@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13111314
qself,
13121315
path,
13131316
ParamMode::Optional,
1317+
AllowReturnTypeNotation::No,
13141318
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
13151319
None,
13161320
);
@@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
13361340
&se.qself,
13371341
&se.path,
13381342
ParamMode::Optional,
1343+
AllowReturnTypeNotation::No,
13391344
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
13401345
None,
13411346
);

compiler/rustc_ast_lowering/src/lib.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,23 @@ enum ParamMode {
485485
Optional,
486486
}
487487

488+
#[derive(Copy, Clone, Debug)]
489+
enum AllowReturnTypeNotation {
490+
/// Only in types, since RTN is denied later during HIR lowering.
491+
Yes,
492+
/// All other positions (path expr, method, use tree).
493+
No,
494+
}
495+
488496
enum GenericArgsMode {
497+
/// Allow paren sugar, don't allow RTN.
489498
ParenSugar,
499+
/// Allow RTN, don't allow paren sugar.
500+
ReturnTypeNotation,
501+
// Error if parenthesized generics or RTN are encountered.
490502
Err,
503+
/// Silence errors when lowering generics. Only used with `Res::Err`.
504+
Silence,
491505
}
492506

493507
impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -1226,7 +1240,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12261240
}
12271241

12281242
let id = self.lower_node_id(t.id);
1229-
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
1243+
let qpath = self.lower_qpath(
1244+
t.id,
1245+
qself,
1246+
path,
1247+
param_mode,
1248+
AllowReturnTypeNotation::Yes,
1249+
itctx,
1250+
None,
1251+
);
12301252
self.ty_path(id, t.span, qpath)
12311253
}
12321254

@@ -2203,6 +2225,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22032225
&None,
22042226
&p.path,
22052227
ParamMode::Explicit,
2228+
AllowReturnTypeNotation::No,
22062229
itctx,
22072230
Some(modifiers),
22082231
) {
@@ -2341,6 +2364,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23412364
&None,
23422365
path,
23432366
ParamMode::Optional,
2367+
AllowReturnTypeNotation::No,
23442368
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
23452369
None,
23462370
);
@@ -2419,6 +2443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24192443
qself,
24202444
path,
24212445
ParamMode::Optional,
2446+
AllowReturnTypeNotation::No,
24222447
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
24232448
None,
24242449
);

compiler/rustc_ast_lowering/src/pat.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use super::errors::{
1111
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
1212
};
1313
use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
14-
use crate::ImplTraitPosition;
14+
use crate::{AllowReturnTypeNotation, ImplTraitPosition};
1515

1616
impl<'a, 'hir> LoweringContext<'a, 'hir> {
1717
pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
@@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
3838
qself,
3939
path,
4040
ParamMode::Optional,
41+
AllowReturnTypeNotation::No,
4142
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
4243
None,
4344
);
@@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
5556
qself,
5657
path,
5758
ParamMode::Optional,
59+
AllowReturnTypeNotation::No,
5860
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
5961
None,
6062
);
@@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6668
qself,
6769
path,
6870
ParamMode::Optional,
71+
AllowReturnTypeNotation::No,
6972
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
7073
None,
7174
);

compiler/rustc_ast_lowering/src/path.rs

+69-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
55
use rustc_hir::def_id::DefId;
66
use rustc_hir::GenericArg;
77
use rustc_middle::span_bug;
8+
use rustc_session::parse::add_feature_diagnostics;
89
use rustc_span::symbol::{kw, sym, Ident};
910
use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
1011
use smallvec::{smallvec, SmallVec};
@@ -15,10 +16,9 @@ use super::errors::{
1516
GenericTypeWithParentheses, UseAngleBrackets,
1617
};
1718
use super::{
18-
GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode,
19-
ResolverAstLoweringExt,
19+
AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
20+
LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
2021
};
21-
use crate::ImplTraitPosition;
2222

2323
impl<'a, 'hir> LoweringContext<'a, 'hir> {
2424
#[instrument(level = "trace", skip(self))]
@@ -28,6 +28,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2828
qself: &Option<ptr::P<QSelf>>,
2929
p: &Path,
3030
param_mode: ParamMode,
31+
allow_return_type_notation: AllowReturnTypeNotation,
3132
itctx: ImplTraitContext,
3233
// modifiers of the impl/bound if this is a trait path
3334
modifiers: Option<ast::TraitBoundModifiers>,
@@ -103,8 +104,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
103104
{
104105
GenericArgsMode::ParenSugar
105106
}
107+
Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => {
108+
match allow_return_type_notation {
109+
AllowReturnTypeNotation::Yes => GenericArgsMode::ReturnTypeNotation,
110+
AllowReturnTypeNotation::No => GenericArgsMode::Err,
111+
}
112+
}
106113
// Avoid duplicated errors.
107-
Res::Err => GenericArgsMode::ParenSugar,
114+
Res::Err => GenericArgsMode::Silence,
108115
// An error
109116
_ => GenericArgsMode::Err,
110117
};
@@ -164,11 +171,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
164171
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
165172
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
166173
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
174+
// If this is a type-dependent `T::method(..)`.
175+
let generic_args_mode = if i + 1 == p.segments.len()
176+
&& matches!(allow_return_type_notation, AllowReturnTypeNotation::Yes)
177+
{
178+
GenericArgsMode::ReturnTypeNotation
179+
} else {
180+
GenericArgsMode::Err
181+
};
182+
167183
let hir_segment = self.arena.alloc(self.lower_path_segment(
168184
p.span,
169185
segment,
170186
param_mode,
171-
GenericArgsMode::Err,
187+
generic_args_mode,
172188
itctx,
173189
None,
174190
));
@@ -238,11 +254,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
238254
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
239255
}
240256
GenericArgs::Parenthesized(data) => match generic_args_mode {
241-
GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data(
242-
data,
243-
itctx,
244-
bound_modifier_allowed_features,
245-
),
257+
GenericArgsMode::ReturnTypeNotation => {
258+
let mut err = if !data.inputs.is_empty() {
259+
self.dcx().create_err(BadReturnTypeNotation::Inputs {
260+
span: data.inputs_span,
261+
})
262+
} else if let FnRetTy::Ty(ty) = &data.output {
263+
self.dcx().create_err(BadReturnTypeNotation::Output {
264+
span: data.inputs_span.shrink_to_hi().to(ty.span),
265+
})
266+
} else {
267+
self.dcx().create_err(BadReturnTypeNotation::NeedsDots {
268+
span: data.inputs_span,
269+
})
270+
};
271+
if !self.tcx.features().return_type_notation
272+
&& self.tcx.sess.is_nightly_build()
273+
{
274+
add_feature_diagnostics(
275+
&mut err,
276+
&self.tcx.sess,
277+
sym::return_type_notation,
278+
);
279+
}
280+
err.emit();
281+
(
282+
GenericArgsCtor {
283+
args: Default::default(),
284+
constraints: &[],
285+
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
286+
span: path_span,
287+
},
288+
false,
289+
)
290+
}
291+
GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self
292+
.lower_parenthesized_parameter_data(
293+
data,
294+
itctx,
295+
bound_modifier_allowed_features,
296+
),
246297
GenericArgsMode::Err => {
247298
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
248299
let sub = if !data.inputs.is_empty() {
@@ -279,7 +330,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
279330
}
280331
},
281332
GenericArgs::ParenthesizedElided(span) => {
282-
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
333+
match generic_args_mode {
334+
GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => {
335+
// Ok
336+
}
337+
GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
338+
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
339+
}
340+
}
283341
(
284342
GenericArgsCtor {
285343
args: Default::default(),

compiler/rustc_hir_analysis/messages.ftl

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
3737
3838
hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here
3939
40-
hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
40+
hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated {$what} of a trait with uninferred generic parameters
4141
.suggestion = use a fully qualified path with inferred lifetimes
4242
4343
hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
@@ -48,6 +48,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
4848
4949
hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}
5050
51+
hir_analysis_bad_return_type_notation_position = return type notation not allowed in this position yet
52+
5153
hir_analysis_cannot_capture_late_bound_const =
5254
cannot capture late-bound const parameter in {$what}
5355
.label = parameter defined here

compiler/rustc_hir_analysis/src/collect.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
460460
[] => (generics.span, format!("<{lt_name}>")),
461461
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
462462
};
463-
mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
463+
mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
464464
fspan: lt_sp,
465465
first: sugg,
466466
sspan: span.with_hi(item_segment.ident.span.lo()),
@@ -502,11 +502,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
502502
}
503503
Ty::new_error(
504504
self.tcx(),
505-
self.tcx().dcx().emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
505+
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
506506
span,
507507
inferred_sugg,
508508
bound,
509509
mpart_sugg,
510+
what: "type",
510511
}),
511512
)
512513
}

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
240240
for predicate in hir_generics.predicates {
241241
match predicate {
242242
hir::WherePredicate::BoundPredicate(bound_pred) => {
243-
let ty = icx.lower_ty(bound_pred.bounded_ty);
243+
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
244+
244245
let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
245246
// Keep the type around in a dummy predicate, in case of no bounds.
246247
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
@@ -770,6 +771,10 @@ impl<'tcx> ItemCtxt<'tcx> {
770771
continue;
771772
};
772773

774+
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
775+
// want to only consider predicates with `Self: ...`, but we don't want
776+
// `OnlySelfBounds(true)` since we want to collect the nested associated
777+
// type bound as well.
773778
let (only_self_bounds, assoc_name) = match filter {
774779
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
775780
(OnlySelfBounds(false), None)
@@ -780,14 +785,10 @@ impl<'tcx> ItemCtxt<'tcx> {
780785
}
781786
};
782787

783-
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
784-
// want to only consider predicates with `Self: ...`, but we don't want
785-
// `OnlySelfBounds(true)` since we want to collect the nested associated
786-
// type bound as well.
787788
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
788789
ty
789790
} else if matches!(filter, PredicateFilter::All) {
790-
self.lower_ty(predicate.bounded_ty)
791+
self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty)
791792
} else {
792793
continue;
793794
};

0 commit comments

Comments
 (0)